A useful technique for Exchange Server administrators is to be able to send email messages via SMTP from PowerShell. In this series of articles I will take you through different scripting techniques for sending email from your scripts.

There are a few different ways to do this, depending on the version of PowerShell installed on your computer or server. You can check the version number by typing $host in a PowerShell window.

PowerShell 1.0 will show this result:

PS C:\> $host

Name             : ConsoleHost
Version          : 1.0.0.0

PowerShell 2.0 will show this result:

PS C:\> $host

Name             : ConsoleHost
Version          : 2.0

Let’s take a look at how we can send SMTP email using each version of PowerShell.

Sending SMTP Email with PowerShell 1.0

For PowerShell 1.0 we can send mail by running these commands.

PS C:\> $smtp = New-Object Net.Mail.SmtpClient("ho-ex2010-caht1.exchangeserverpro.net")
PS C:\> $smtp.Send("reports@exchangeserverpro.net","administrator@exchangeserverpro.net","Test Email","This is a test")

So what did we just do there? Let’s break it down.

  1. Created a new instance of a .NET object of class SmtpClient, connected to the SMTP server ho-ex2010-caht1 (a Hub Transport server)
  2. Used the Send method of the object to send an email message with the following:
    • From address of “reports@exchangeserverpro.net”
    • To address of “administrator@exchangeserverpro.net
    • Subject of “Test Email”
    • Body of “This is a test”

How to Send SMTP Email Using PowerShell (Part 1)

That works fine, though perhaps a bit cumbersome to type it out every time. Instead what we could do is create a script to send SMTP email using PowerShell 1.0.

#
#.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)

We can save that code as Send-Email.ps1 and run it from the PowerShell window.

PS C:\Scripts> .\Send-Email.ps1 -To "administrator@exchangeserverpro.net" -Subject "Test email" -Body "This is a test"

Less typing required, especially when you hard-code some of the variables such as the From address and SMTP server.

Sending SMTP Email with PowerShell 2.0

PowerShell 2.0 makes life a little easier thanks to the built in cmdlet Send-MailMessage. To send the same email as the above example we would run this command:

PS C:\> Send-MailMessage -From "reports@exchangeserverpro.net" -To "administrator@exchangeserverpro.net" -Subject "Test email" -Body "This is a test email"

One of the first things you might notice in the command above is that no SMTP server was specified. Send-MailMessage does have a -SmtpServer parameter, but if you don’t specify one it will just use the $PSEmailServer preference variable instead. This can be set for the session by running the following command:

PS C:\> $PSEmailServer = "ho-ex2010-caht1.exchangeserverpro.net"

Another point to note with Send-MailMessage is that is uses authenticated SMTP connections. By default it will use the credentials of the user executing the command. So you need to make sure you’re using an SMTP server that either:

Those are just a few simple examples of how to send email using SMTP and PowerShell 1.0 or 2.0.

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. Adrian Nielsen

    I notice it is not leaving a copy in the outbox. How to do that? Also, how to send a blind copy? Thanks!

  2. Randy

    is there a way to write it using a Send As?

  3. Robert Rogers

    Is there a way to send a local file as an attachment for example a log file?

  4. kylexy

    For my opinion, the command:set-senderidconfig “internalenablue” parameter NEED to be “TRUE” to prevent internal user sending fake emails to other staff.

  5. Amy Hu

    Thank you for your sharing. I tried with your command to send email from Office 365. But with some of the computer, got error:

    Exception calling “Send” with “4” argument(s): “The remote certificate is invalid according to the validation procedure”

    Can you please me with this error?

    Thank you.

    1. Amy Hu

      $EmailFrom = “myaccount@domain.com”

      $EmailTo = “emailaddress@domain.com”

      $Subject = “Test from O365 SMTP”

      $Body = “Test from O365 SMTP Authentication”

      $SMTPServer = “smtp.office365.com”

      $SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)

      $SMTPClient.EnableSsl = $true

      $SMTPClient.Credentials = New-Object System.Net.NetworkCredential(“myaccount@domain.com”, “*****”);

      $SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)

  6. DIDO

    Thanks paulfor all this informations, it’s very kind of you,

  7. Pankaj tambe

    Dear All,

    Can anyone help me out to create a powershell script as per below requirements.
    1. We are planning to add new SMTP address to our existing users and so we want to set auto reply message as per below to all user mailbox.
    2. Script should take user display name with old email id and new email id and set below customize message on each of individual mailboxes
    3. Reply message should be as per below
    4. Script should take all BOLD content from excel sheet and set customize auto reply message to each individual mailboxes

    Dear Sender,

    Please note that my email id has been changed from abc@test.com to xyz@test.com , hence for the please send mail on new email id only…

    Regards,
    ‘User name’

    Note: We are having Exchange 2010 environment

  8. loanemu

    Im obliged for the blog article. Really Great.

  9. Raul

    Researching a little bit i found the solution!
    It was just add a one more line

    $smtp.UseDefaultCredentials=$true

    The script is working fine now!

  10. Raul

    Hi, I wrote this code to send email requesting a few parameters to send an attached file with information between exchange servers in two different organizations

    Write-Host -NoNewLine “Ingrese el fqdn del dominio de correo: ” -ForeGroundColor Yellow;$Suffix=Read-Host
    Write-Host -NoNewLine “Ingrese el nombre de nuestro servidor Exchange: “-ForeGroundColor Yellow; $Server=Read-Host
    Write-Host -NoNewLine “Ingrese la dirección de correo destino: “-ForeGroundColor Yellow;$Receipt_Mail_Address=Read-Host
    Write-Host -NoNewLine “Ingrese la dirección de correo remitente: “-ForeGroundColor Yellow;$Sender_Mail_Address=Read-Host
    Write-Host ” ”
    Write-Host ” ”

    $filename=“c:SyncContacts-“+$Suffix+”.txt”

    $msg=new-object Net.Mail.MailMessage
    $att=new-object Net.Mail.Attachment($filename)
    $smtp=new-object Net.Mail.SmtpClient($Server)

    $msg.From=$Sender_Mail_Address
    $msg.To.Add($Receipt_Mail_Address)
    $msg.Subject = “Correo automatizado – Contacts-“+$Suffix+”.TXT”
    $msg.Body=“Envío automatizado del archivo Contacts-“+$Suffix+”.TXT”
    $msg.Attachments.Add($filename)

    $smtp.Send($msg)
    Write-Host “Enviando Correo automatizado, por favor espere … ” -ForeGroundColor Green
    Write-Host ” ”
    Write-Host ” ”
    Write-Host “Correo enviado” -ForeGroundColor Green

    In Exchange 2010 it works fine, but in Exchange 2013 I receive an SMTP error 5.7.1 unable to relay, thats mean the script works fine but the server are not allowing to relay to the remote host, how can i solve this?

  11. Maher

    HOW TO ermits that authenticated user credential to send email messages via SMTP

  12. Christiaan van der Kooij

    If you want to foricbly send mails anonymous you can use the following script, it also reads a logfile for error strings and parses it in the e-mail for added benefit. 🙂

    $User = “anonymous”
    $PWord = ConvertTo-SecureString –String “anonymous” –AsPlainText -Force
    $Creds = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $user, $pword

    Send-MailMessage -From “from@from.com” -To “to@to.com” `
    -SmtpServer “localmailserveriphere” `
    -Subject “Subject” `
    -BodyAsHtml `
    -Credential $creds `
    -Body @”
    Errors! “`r”
    $(Get-ChildItem C:TEMPsynctool*.log | `
    Select-String -Pattern errors -AllMatches -SimpleMatch |
    Foreach-Object {$_.Line}
    out-string)
    “@

    1. Raj Kamal

      Thanks…It works for me

  13. Jon

    I’m using Send-Mailmessage to generate a number of messages via foreach loop, but it recycles the session for each one. The relay server limit is 15 messages per smtp session, so I’m wondering if there is a way to force close the current SMTP session and make send-mailmessage start a new one.

    thanks!

  14. Sunil

    Hi Paul,

    Yes i did change the server name and valid addresses!

  15. Pat Richard

    Did you change the name of the SmtpClient to match your server name? And change the to/from address to match valid addresses?

  16. Sunil

    I am trying to send mail by same command as gave above i.e.
    PS C:\> $smtp = New-Object Net.Mail.SmtpClient(“ho-ex2010-caht1.exchangeserverpro.net”)
    PS C:\> $smtp.Send(“reports@exchangeserverpro.net”,”administrator@exchangeserverpro.net”,”Test Email”,”This is a test”)

    However i am getting error “Exception calling “Send” with “4” argument(s): “Failure sending mail.”
    At line:1 char:11″

    Can you please help me in this.

    Appreciate your kind help.

    1. DIDO

      hello,
      if i’ve understand you can add ath the end of command -smtpserver and put @IP or mail server name,without using objects.try this

      Send-MailMessage -From “reports@exchangeserverpro.net” -To “administrator@exchangeserverpro.net
      ” -Subject “Test email” -Body “This is a test email” -smtpserver “IP or server’s name”

  17. Boball

    Can you help me with a simple problem I am having due to not being very good at Powershell.

    I am using a super-so-simple get-content command to read a file with a list of users and move their mailbox to another mailstore and I would like to be able to use a send-mailmessage at the end to email each user to say the move has finished.

    The line I am using is as follows,
    Get-Content C:users.txt | Move-Mailbox -TargetDatabase “ServernameFirst Storage GroupMailbox Database” -Confirm:$false

    This works OK enough but I would like to finish it off with the email functionality but I don’t know how to use the outputs of Get-Content such a System.Object, which I presume would do it for me if I knew my a*** from my elbow!
    Any help greatly appreciated.

  18. Mohan

    Very Useful Info. Delivered in an excellent way !!! Thanks much !!!

  19. Rob Roelvink

    By having a quick looking I realized this site contains very helpfull information related to PowerShell.

    Whenever I’ve got enough time I will have a closer look, because with PowerShell you can get almost everything you want to know and to export this information to any format as Word, Excel etc..

  20. Anand

    Thanks for the article. One question though. Will this be useful to test scenarios related to journaling. For instance, I have a requirement to automate tests related to journaling. With the above steps will the exchange server send out journaling messages to the configured connectors? Thanks.

  21. Pat Richard

    Nice info. Learned a couple of things from this, including the $PSEmailServer info and the authenticated sending part.

    Keep it up!

  22. Jeffery Hicks

    Tip: Put the line defining $PSEmailServer in your profile script so you always have it.

Leave a Reply