Using the PowerShell Send-MailMessage cmdlet

A very handy PowerShell cmdlet that I don’t think enough IT pros take advantage of is Send-MailMessage. This is an easy-to-use cmdlet that allows you to send email messages directly from PowerShell. It doesn’t require any arcane .NET programming, as it’s a simple cmdlet with simple parameters. I’m going to trust you will take some time to read through full help and examples. I’m going to demonstrate a few different ways to use the cmdlet and point out some potential gotchas.

The first potential gotcha is running the PowerShell 2.0 version of the cmdlet. This version lacks a few parameters that you may need to take advantage of. The most important is the port parameter. To send a mail message, you will need to identify your mail server. Traditional SMTP servers run over port 25, but today with the prevalent use of services such as Gmail, it is most likely some other port.
I will also point out that you should expect some trial and error in getting mail messaging to work with PowerShell. One problem I’ve encountered in the past when using an internal mail server like Exchange is that sometimes the mail server doesn’t like what it interprets as anonymous relays, i.e. spam. You may need to provide credentials. Fortunately, that is easily handled with the –Credential parameter. You can enter credentials like you would for cmdlets like Get-WmiObject. However, this could pose a problem if you are trying to use Send-MailMessage in an unattended setting where there is no way to enter a password. In those situations, try to run the command in a process or task that is already running under the proper credentials.
To send a mail message, and I suggest testing with this, you need to provide values for these parameters:

  • To
  • From
  • Subject
  • SMTPServer

The To and From properties should be simple email addresses. I recommend first testing by sending to and from addresses within your own domain. That cuts down on potential relay problems, which is most likely what you will be doing anyay.

​
The cmdlet will also look to the variable $PSEmailServer for a SMTPServer value. If the variable is defined, then you don't need to specify –SMTPServer. Defining $PSEmailServer can be done in your profile. If this simple command fails, you will need to research and refine the command. You may need to supply credentials. You may need to specify a port or that you wish to use SSL. I should also point out that these messages have nothing to do with your email client. You won't see any Sent messages in Outlook or Thunderbird. In my particular situation, I eventually worked out that I needed to specify a port and a different SMTP server name to handle certificate issues. I set my $PSEMailServer to the correct value.
​
Even if you don't see a value for SMTPServer in my expressions, this is the value that will be used. Now that I have verified basic mail functionality let's do something with it. The most important thing to remember is that whatever you want to send as the body of a message must be treated as a string. You might try something like this:
​
But as you can see this fails.
PowerShell Send-MailMessage
The PowerShell Send-MailMessage cmdlet has failed. (Image Credit: Jeff Hicks)
Instead, you need to turn $p into string output. In my inbox, I get a message like this.
Processes list delivered to inbox. (Image Credit: Jeff Hicks)
Processes list delivered to inbox. (Image Credit: Jeff Hicks)
But perhaps I want this to be sent as an attachment.
Sending the process report as an attachment via email. (Image Credit: Jeff Hicks)
Sending the process report as an attachment via email. (Image Credit: Jeff Hicks)
My Thunderbird client attempts to display attachments inline, but you can see there is an attachment. If you think you will be viewing attachments inline, I recommend encoding the files as ASCII. The last, and perhaps most interesting way to use Send-MailMessage is to send an HTML formatted body. I prefer to embed any CSS styling directly in the HTML document. Otherwise if you reference an external CSS source, the person reading the email must have access to that file. Here is a sample script that creates an HTML body and sends it as an email message.
​
A few key points I want to mention. First, you don't need to save the HTML to a file, although you certainly could and then read the file in for the body.

Just remember that the body must be formatted as a string, which is why ConvertTo-HTML is piped to Out-String. Also don't forget the –BodyAsHTML switch parameter. When I run this script, I get an email like this:
Daily process report is emailed. (Image Credit: Jeff Hicks)
Daily process report is emailed. (Image Credit: Jeff Hicks)
  It can really be that simple once you sort out how to establish a connection with your mail server. If you have problems getting started or any follow up questions on this topic, please use the PowerShell forum on the site. And if you are using this cmdlet in your scripts and IT processes, I'd love to hear about it.