23 Oct 2011

How to Send SMTP Email Using PowerShell

In the last part of this series we looked at simple techniques for sending email from PowerShell. In this article we'll take a closer look at how you can create the email message body for emails that you are sending via PowerShell.

In the last article I demonstrated a simple PowerShell script for sending emails that contained the following code, using the SmtpClient .NET object .

# #.SYNOPSIS #Sends SMTP email via the Hub Transport server # #.EXAMPLE #.\Send-Email.ps1 -To "administrator@exchangeserverpro.net" -Subject "Test email" -Body "This is a test" #  param( [string]$to, [string]$subject, [string]$body )  $smtpServer = "ho-ex2010-caht1.exchangeserverpro.net" $smtpFrom = "reports@exchangeserverpro.net" $smtpTo = $to $messageSubject = $subject $messageBody = $body  $smtp = New-Object Net.Mail.SmtpClient($smtpServer) $smtp.Send($smtpFrom,$smtpTo,$messagesubject,$messagebody)

Now let's build on that example by adding more content to the message body of the emails.

Using Command Output as Email Message Content with PowerShell

When running this script anything that we specify with the -Body parameter will be the message body of the email. It could be a text string, or it could even be the output from another PowerShell command. For example:

[PS] C:\Scripts>.\Send-Email.ps1 -To "administrator@exchangeserverpro.net" -Subject "List of Exchange Servers" -Body (Get-ExchangeServer)

The command above would produce an email that looks like this:

Neat trick, but notice how the list of Exchange servers appears as all one string that wraps over two lines? Wouldn't it be nicer to see the server names displayed in an easier to read list format? Let's take a look at how you can achieve that.

[PS] C:\Scripts>[string]$emailbody = ""  [PS] C:\Scripts>$servers = Get-ExchangeServer  [PS] C:\Scripts>foreach ($server in $servers) {$emailbody = $emailbody + $server.name + "`r`n"}  [PS] C:\Scripts>.\Send-Email.ps1 -To "administrator@exchangeserverpro.net" -Subject "List of Exchange Servers" -Body $emailbody

So what did I do there? Here are the steps I just followed:

  1. Declare a variable $emailbody as type string. This will be the variable that is passed to the script to be the message body of the email that gets sent.
  2. Used the Get-ExchangeServer cmdlet to retrieve a list of the Exchange servers in the organization into an array of $servers.
  3. Looped through the array using the ForEach-Object (abbreviated to "foreach") cmdlet and appended each server name to the $emailbody string, including (and this is the important part) a carriage return after each server name.
  4. Ran the script using the $emailbody variable for the -Body script parameter.

The result is an email that looks like this; much better don't you agree?

Now this is only a demonstration. In reality you probably aren't going to want to send yourself an email with a list of your Exchange servers, at least not very often.

However you can use the same techniques I've just demonstrated to build scripts that email you any command or script output, such as a list of mailboxes with no storage quotas that you have emailed to yourself automatically each month.

Using File Contents as Email Message Content with PowerShell

Another technique for getting content for the message body of an email sent via PowerShell is to use the contents of a file.

For example, I run continuous pings between certain servers to detect any network interruptions that may be occurring. An entry is written to a log file any time a ping times out. Every day I want to receive an email with the results of the previous day's ping monitoring, so I can do that using a script like this.

# #.SYNOPSIS #Sends daily dropped ping report # #.EXAMPLE #.\Send-DroppedPingReport.ps1 #  $smtpServer = "ho-ex2010-caht1.exchangeserverpro.net" $smtpFrom = "reports@exchangeserverpro.net" $smtpTo = "administrator@exchangeserverpro.net" $messageSubject = "Dropped ping report"  [string]$messagebody = ""  $logs = Get-Content C:\Logs\droppedpings.log  foreach ($log in $logs ) { 	$messagebody = $messagebody + $log + "`r`n" }  $smtp = New-Object Net.Mail.SmtpClient($smtpServer) $smtp.Send($smtpFrom,$smtpTo,$messagesubject,$messagebody)

This is the same technique that was used earlier to create an array and loop through it to add the carriage returns so that the email is formatted nicely. The main difference is the use of Get-Content instead of Get-ExchangeServer.

As you can see it is very simple to create useful, informative emails that are sent by your PowerShell scripts.

No comments:

Post a Comment