Send SMTP email with authentication from PowerShell

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 "testscript@rcmtech.co.uk" -To "robin@rcmtech.co.uk" -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 username@domain.net.securestring

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 "username@myisp.net",(Get-Content -Path username@myisp.net.securestring | ConvertTo-SecureString)

So now shove the whole lot together, on one line (because we can, and bigger is better, right?):

Send-MailMessage -From "username@myisp.net" -To "robin@rcmtech.co.uk" -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 "username@myisp.net",(Get-Content -Path username@myisp.net.securestring | 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 = "username@myisp.net"
$EncryptedPasswordFile = "username@myisp.net.securestring"
$SecureStringPassword = Get-Content -Path $EncryptedPasswordFile | ConvertTo-SecureString
$EmailCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $SMTPUsername,$SecureStringPassword
$MailTo = "robin@rcmtech.co.uk"
$MailFrom = "username@myisp.net"
$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.

This entry was posted in PowerShell and tagged , , , , , , , , , , , , , , , , , , . Bookmark the permalink.

9 Responses to Send SMTP email with authentication from PowerShell

  1. This was a great article. Thank-you!

    Like

  2. Pingback: Send email via Yahoo with PowerShell | Robin CM's IT Blog

  3. Black says:

    Hi,

    thank you, very good article.

    In my opinion DPAPI is not only machine specific but also user specific!

    Greetings
    Black

    Like

    • Black says:

      this means you have to do the ‘Read-Host …’ command with the same user running the send-mailmessage, if you want to run the send-mailmessage in a script as scheduled task think about it

      Liked by 1 person

  4. Sergio says:

    This article was very easy to follow through. Thanks for sharing!

    Like

  5. Dimce says:

    Thanks a lot for sharing this. After reading many other posts, this brought the solution for sending a mail using encrypted password for SMTP-authentication.

    Like

  6. mjouan says:

    awsome thanks you so much pretty nice

    Like

  7. Mel says:

    Very useful, I was thinking how can I do it and I always hide it in a variable for a specific session. Now with your method, I am in peace. Thanks a lot.

    Note: it did not work for me until I added the option: -UseSsl after -Port 587

    Like

  8. Sinh Do says:

    Great

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.