For this PowerShell cmdlet of the day, we're covering the PowerShell cmdlet Send-MailMessage. This PowerShell cmdlet serves one purpose and one purpose only; to send email in a lot of different ways.

Since there are so many ways the Send-MailMessage cmdlet can send email messages, let's dive right in and start covering all of the common examples you may run into. In this article, we're going to cover many examples ranging from the simplest all the way up to some scenarios that I wish upon no one!

If you'd like to go from PowerShell newbie to PowerShell guru, I recommend devouring this FREE mini-course on building a PowerShell tool. This is a step-by-step tutorial with full explanations and guidance from Adam the Automator!

This post will be a great resource to bookmark in case you ever come across instances where you need to send email with PowerShell and forget the syntax.

The SMTP Server

All email has to go through an SMTP server somewhere via a server and a port. To specify a the SMTP server to use, use a parameter called SMTPServer that allows you to specify the SMTP server to establish a connection and relay mail through. However, it is not required.

If you don't specify a value for the SMTPServer parameter, the value stored in the $PSEmailServer preference variable will be used. You can assign a value to this variable just like you would any other variable.

PS51> $PSEmailServer = 'smtp.server.local'
Assigning a value to the $PSEmailServer preference variable

However, this variable does not live across PowerShell sessions. This means you must define it every time a new PowerShell session is open. For this reason, I recommend either using it by defining it above your Send-MailMessage reference or not defining it all. Instead, I'd personally provide the SMTPServer parameter value. This way you don't have to manage an outside variable that might change on you.

PS51> Send-MailMessage -SmtpServer 'smtp.server.local'
Sending email through smtp.server.local port 25

Port

By default, the value that the cmdlet will attempt to send an email through the SMTP server is port 25. This is plain, unencrypted SMTP. However, nowadays, it's more common to send encrypted email using SSL/TLS (We'll cover these scenarios later).

If you need to change the port from 25, you can use the Port parameter.

PS51> Send-MailMessage -SmtpServer 'smtp.server.local' -Port 587
Sending email through port 587 (TLS)

Recipients and Originators

To send an email to different recipients via methods like the To, Cc and Bcc fields, the cmdlet has various parameters to accommodate this.

The To, Cc and Bcc Parameters

The cmdlet has three parameters each supporting multiple recipients separated by a comma called To, Cc and Bcc.

You can specify single addresses like below.

PS51> Send-MailMessage -To [email protected] -Cc [email protected] -Bcc [email protected] -Subject 'this is a subject'
Sending email to one recipient via To, Cc and Bcc

Or you can specify multiple recipients for each parameter value.

PS51> Send-MailMessage -To [email protected], [email protected] -Cc [email protected], [email protected] -Bcc [email protected],[email protected] -Subject 'this is a subject'
Sending email to multiple recipients via To, Cc and Bcc

The From Parameter

When sending email, you can also specify the From parameter which will set the reply-to header in the email. This parameter only allows one address. Should a recipient choose to reply to the email, this will be the email address that reply will come back to.

PS51> Send-MailMessage -From [email protected] -To [email protected] -Subject 'this is a subject'
Sending email from an address

By default, using an email address will simply show the email address in the recipient's FROM field. However, if you'd like to specify a name or some kind of label like Service Account Mailbox, you may also specify a name and an email like:

Adam Bertram <[email protected]>

Notice that the Subject parameter was used. This parameter is always required. You'll see this parameter used in all examples.

Body

The Body parameter allows you to specify what will be in the email body. At the most simplest, you can specify any text you'd like and the cmdlet will send it via plaintext.

PS51> Send-MailMessage -From [email protected] -To [email protected] -Subject 'this is a subject' -Body 'this is the body'

Sending HTML Body Emails

You can also send an email body via HTML rather than plaintext. To do that, use the same Body parameter as you would with plaintext but use HTML for the string and use the BodyAsHtml switch parameter.

$body = @'
<table style="width:100%">
  <tr>
    <th>Firstname</th>
    <th>Lastname</th> 
    <th>Age</th>
  </tr>
  <tr>
    <td>Jill</td>
    <td>Smith</td> 
    <td>50</td>
  </tr>
  <tr>
    <td>Eve</td>
    <td>Jackson</td> 
    <td>94</td>
  </tr>
</table>
'@

PS51> Send-MailMessage -From [email protected] -To [email protected] -Subject 'this is a subject' -Body $body -BodyAsHtml
Sending an HTML table in an email
Notice in the above example, I enclosed the body string in @' and '@. This is called a here string. This allows you to define long strings typically seen in email bodies that contain carriage returns. Here strings preserve formatting of strings and is a great way to define the email body especially if it's in HTML.

Encoding

If you have special characters in the subject or body of your email, you can use the Encoding parameter. This parameter allows you to encode the email subject and body via the specified encoding type before sending.

You have a few options here:

  • ASCII (default)
  • UTF8
  • UTF7
  • UTF32
  • Unicode
  • BigEndianUnicode
  • Default
  • OEM
PS51> Send-MailMessage -From [email protected] -To [email protected] -Subject 'this is a subject' -Body 'this is the body' -Encoding UTF8
Setting encoding to UTF8

Attachments

The cmdlet can also attach one or more files. To do so, you can use the Attachments parameter and provide the path to the file(s) you'd like to attach.

PS51> Send-MailMessage -From [email protected] -To [email protected] -Subject 'this is a subject' -Body 'this is the body' -Attachments 'C:\file.doc'
Attaching the C:\file.doc to an email

You can also specify multiple attachments via a collection by separating them with a comma.

PS51> Send-MailMessage -From [email protected] -To [email protected] -Subject 'this is a subject' -Body 'this is the body' -Attachments 'C:\file.doc','D:\report.xlsx'
Attaching the C:\file.doc and D:\report.xlsx file to an email

The Attachments parameter also allows you to pipe files via cmdlets like Get-Item and Get-ChildItem to the Send-MailMessage cmdlet as well.

PS51> Get-ChildItem -Path 'C:\MyFiles' | Send-MailMessage -From [email protected] -To [email protected] -Subject 'this is a subject' -Body 'this is the body'
Attaching all files in the C:\MyFiles folder

Secure and Authenticated Email

By default, the cmdlet sends email via unencrypted SMTP communication over port 25. However, it also has support for sending encrypted email via SSL/TLS with a username and password.

If you attempt to relay email through an SMTP server that requires authentication, the command fails with an error message like below.

The SMTP server requires a secure connection or the client was not
authenticated. The server response was: 5.7.0 Must issue a STARTTLS command first.
Error message when attempting to send unencrypted email.

To remedy this, you must first specify the port (typically 587 for TLS) and the UseSsl parameter. This tells the cmdlet to attempt to connect to port 587 on the SMTP Server and encrypt the entire message. You will typically (always?) also need to specify the username/password to authenticate to the SMTP server by using the Credential parameter.

PS51> $credential = Get-Credential
PS51> Send-MailMessage -From [email protected] -To [email protected] -Subject 'this is a subject' -Body 'this is the body' -UseSsl -Port 587 -Credential $credential
Sending a TLS-encrypted email using a credential
Above I'm grabbing a credential (PSCredential) object using the Get-Credential cmdlet. This sometimes poses a problem because it's interactive meaning it stops the script to ask for a username and password. To prevent this, you could create a PSCredential object on the fly.

A common email example is to use Gmail. Using the knowledge you've gained above, you can now easily send email through Gmail using the smtp.gmail.com SMTP server as shown below.

$gmailCred = Get-Credential

$sendMailParams = @{
    From = '[email protected]' ## Must be gmail.com
    To = '[email protected]'
    Subject = 'some subject'
    Body = 'some body'
    SMTPServer = 'smtp.gmail.com'
    SMTPPort = 587
    UseSsl = $true
    Credential = $gmailCred
}

Send-MailMessage @sendMailParams

Assigning Email Priority

Although one feature of email I personally wish would die, you can assign priority levels to the emails you send via the Priority parameter. This priority is then interpreted in various ways by the email client.

High priority message in Outlook

Send-MailMessage allows you to assign an email with three different priorities.

  • Normal (default)
  • High
  • Low
PS51> Send-MailMessage -From [email protected] -To [email protected] -Subject 'this is a subject' -Body 'this is the body' -Priority High
Assigning a high-priority email

But please, for the love of God, don't think all of your emails are high priority!

Delivery Notifications

Finally, you can specify delivery notifications for emails. Delivery notifications are what's typically known as read receipts in some email clients. Delivery notifications allow you to be notified if/when the email is received by the recipient. However, the recipient must still allow it.

You have four options when requesting delivery notifications.

  • None (default)
  • OnSuccess (when the email is delivery is successful)
  • OnFailure (notify if the delivery is unsuccessful)
  • Delay (when the email is delayed via an SMTP server)

You can specify a delivery notification option by using the DeliveryNotificationOptions parameter.

PS51> Send-MailMessage -From [email protected] -To [email protected] -Subject 'this is a subject' -Body 'this is the body' -DeliveryNotificationsOptions 'OnSuccess'
Requesting a notification on delivery

You can also request multiple delivery notifications at once by separating them with a comma.

PS51> Send-MailMessage -From [email protected] -To [email protected] -Subject 'this is a subject' -Body 'this is the body' -DeliveryNotificationsOptions 'OnSuccess','OnFailure','Delay'
Requesting a notification for all types

Summary

In this post, you learned all about the Send-MailMessage cmdlet and what it can. We covered this cmdlet extensively using every parameter it has along with examples. I hope this post can server as a reference for you when using the Send-MailMessage cmdlet.

Further Reading

Be sure to check out some other related posts!

Join the Jar Tippers on Patreon

It takes a lot of time to write detailed blog posts like this one. In a single-income family, this blog is one way I depend on to keep the lights on. I'd be eternally grateful if you could become a Patreon patron today!

Become a Patron!