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:

How to Send SMTP Email Using PowerShell (Part 2)

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?

How to Send SMTP Email Using PowerShell (Part 2)

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:Logsdroppedpings.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.

How to Send SMTP Email Using PowerShell (Part 2)

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

About the Author

Paul Cunningham

Paul is a former Microsoft MVP for Office Apps and Services. He works as a consultant, writer, and trainer specializing in Office 365 and Exchange Server. Paul no longer writes for Practical365.com.

Comments

  1. Ashok

    Hi, How can i add content in the email body(not in email subject), help me with the script part and write it for me

  2. Tony

    Hi Paul ,

    i need your help please. our SCOM server is down actually and i need to monitor our replication on Hyperv via powershell command. i found this command :
    Get-VMReplication -ComputerName Hyperv1-HQ.domain .com
    i need the output of this poweshell to be send to me and other colleague via email on a daily basis twice per day, what is the way to do it?
    also can i get the output via email for multiple command for example :

    Get-VMReplication -ComputerName Hyperv1-HQ.domain.com
    Get-VMReplication -ComputerName Hyperv2-HQ.domain.com
    etc…

    thanks a lot.
    Tony.

  3. Manoj Kumar Vunnava

    Hi Paul,

    This is very useful article. Thanks for sharing your knowledge. I’m new to powershell scripting and these articles are crystal clear and very useful.

    I wrote a script for my purpose where it has to trigger an email based on the windows event viewer log. The syntax seems to be correct however I’m getting below error. By any chance do you know what is the issue?

    Error message:
    send-mailMessage : Mailbox unavailable. The server response was: 5.7.60 SMTP; Client does not have permissions to send
    as this sender
    At D:\Powershell Scripts\EventLogNotification.ps1:15 char:2
    + send-mailMessage -From $emailfrom -To $emailto -Subject $emailsubject -Body $em …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpExcept
    ion
    + FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage

  4. Mohammed Ali

    Hi,

    While sending email through power shell i’m getting display name as email address.
    Is there parameter to set a Display Name for Email to receive instead of email address

  5. Vivek Devaraj

    That helped me. Thank you!

    God bless

  6. free ip proxy

    Hello,I check your blog named “PowerShell: How to Add a Message Body to Emails Sent from Scripts” daily.Your story-telling style is awesome, keep doing what you’re doing! And you can look our website about free ip proxy https://proxylistdaily4you.blogspot.com/.

  7. Florisz

    @Ricky Valencia
    If you find a solution to put file.txt content in the message body of the email, it would be nice if you share that knowledge here too!

    I and others have the same question.

    1. Avatar photo
      Paul Cunningham

      Ingest the file contents to a variable using Get-Content, then use that variable as the message body.

      Eg..

      $filecontent = Get-Content .File.txt

      Then in the Send-MailMessage command use the -Body parameter, e.g.

      -Body $filecontent

  8. Sean Noy

    Hi Eddie,
    You can create a distribution group and send to that address or create a variable and separate the recipients with ,
    example:

    $recipients = “Boss “, “employee1 ”
    Send-MailMessage -To $recipients -Subject ‘New Mail’ -Body $messagebody -SmtpServer $smatpserver -From ‘alerts@domain.com’

    I prefer distribution group as it is easier to manage without editing the script every time

    Best,
    Sean Noy

  9. Eddie Chua

    how do i send to multiple recipients?

  10. Radhakrishnan Govindan

    Good Article Paul.. Thank you for sharing..

  11. Ricky Valencia Valencia

    Hi Paul,

    Kindly ignore my previous question. I was able to find the solution. I have a second question though, how do i send to multiple recipients?

  12. Ricky Valencia Valencia

    HI Paul,

    Great article. I have a question. I have 2 files (txt files) and the contents of those file I want to make it as email message content and send to my email. How can I do that? THank you.

    1. Tabrez

      Hi Ricky,

      I have the same problem, I have power shell script for sending backup log file (.txt)in email attachment from task scheduler & its working fine . now I want to send .txt file contents in email body , can you please share the script of this.

  13. Anamika

    How to add an attachment. I am using Windows 2012 R2 Server.

      1. Steve

        Very nice (was on the verge of saying elegant). Too bad Send-MailMessage doesn’t do this automatically for txt files (ie treat it as/is).

  14. Sourav M

    Very nice Blog. Thanks much.

  15. Ted Wagner

    Paul,

    Here’s a bit of another challenge. In Exchange, you can create a foreign connector with an address space with a transport rule for routing. An example would be with RightFax.

    new-foreignconnector -name “RightFaxConnector” -addressspaces (“RFAX:*;1″,”FAX:*;1”)

    So, in the example of RightFax, you address for sending would be FAX:Name@1112223333

    To send from an email client, you would simply include brackets: [FAX:Name@1112223333]

    However, with Powershell, the send-mailmessage expects a static format of recipient@domain.com

    However, if you try to use send-mailmessage, the cmdlet won’t recognize the address space and the recipient is invalid.

    Neither the Powershell 1.0 nor the Powershell 2.0 methods work.

    Is it possible to send an email using a different address space with Powershell?

Leave a Reply