Email is a good way to send notifications from your PowerShell scripts, and it’s super easy. You just need an SMTP server, and use Send-MailMessage:
Send-MailMessage -From "email@example.com" -To "firstname.lastname@example.org" -Subject "Something interesting just happened" -Body "Here's the details about the interesting thing" -SmtpServer smtp.rcmtech.co.uk
You can even omit the -SmtpServer bit if you’ve previously set the $PSEmailServer preference variable.
However, what if you don’t have your own internal mailserver, and the only one available needs credentials? Many ISPs require authenticated SMTP now. Sure, Send-MailMessage has a -Credentials options, but these need to be in the form of a System.Management.Automation.PSCredential object. You can use Get-Credential to generate one of these:
Get-Credential -Message "Cough up" -Username "your_username"
But Get-Credential doesn’t have an option to accept the password as plain text, and storing a password as plain text is bad practice anyway. Thus Get-Credential, in the form used above, will create the right kind of object that you can feed into Send-MailMessage, but it does it in the wrong kind of way – via a pop up a box for you to type your password into, which isn’t that handy for use in unattended scripting.
So the clever way to do this is to create yourself an encrypted password file. You can do this as follows:
Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath email@example.com
Run the above, enter the password (which will be obscured with asterisks as you type it), and hit <Enter>. Now you’ve got a text file with an encrypted password in it. How does this work? Read-Host prompts for text, because we’ve used the -AsSecureString switch it returns the text entered as a System.Security.SecureString object. We then pass this to ConvertFrom-SecureString which takes that object and spits it out as text, encrypted with Windows Data Protection API (DPAPI). You can also use 128, 192 or 256-bit AES encryption.
So now we have the password in a file, and can use this to create a PSCredential object:
New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "firstname.lastname@example.org",(Get-Content -Path email@example.com | ConvertTo-SecureString)
So now shove the whole lot together, on one line (because we can, and bigger is better, right?):
Send-MailMessage -From "firstname.lastname@example.org" -To "email@example.com" -Subject "Something interesting just happened" -Body "Here's the details about the interesting thing" -SmtpServer smtp.myisp.net -Port 587 -Credential (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "firstname.lastname@example.org",(Get-Content -Path email@example.com | ConvertTo-SecureString))
But to make it easier to interpret, here’s the same thing broken down with variables:
$PSEmailServer = "smtp.myisp.net" $SMTPPort = 587 $SMTPUsername = "firstname.lastname@example.org" $EncryptedPasswordFile = "email@example.com" $SecureStringPassword = Get-Content -Path $EncryptedPasswordFile | ConvertTo-SecureString $EmailCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $SMTPUsername,$SecureStringPassword $MailTo = "firstname.lastname@example.org" $MailFrom = "email@example.com" $MailSubject = "Something interesting just happened" $MailBody = "Here's the details about the interesting thing" Send-MailMessage -From $MailFrom -To $MailTo -Subject $MailSubject -Body $MailBody -Port $SMTPPort -Credential $EmailCredential
If your SMTP server requires it, you can also add -UseSsl to Send-MailMessage.
Caveat: If you use DPAPI, the encrypted password file can only be decrypted on the machine that it was encrypted on.
Also see the later post about how to send email via Yahoo Mail from PowerShell, including how to use a plain text password.