How to Send an Email Using Windows PowerShell

Windows PowerShell is mostly known as a command-line shell used to solve some administration tasks in Windows and apps running on this OS. At the same time, it is a scripting language that allows you to tailor cmdlets – lightweight commands to perform specific functions. And today, we’ll talk about Send-MailMessage, a cmdlet to send emails from PowerShell, as well as other ways to handle this. 

The simplest script to send an email with PowerShell 

Let’s start with simple things. Here is a one-line script based on the Send-MailMessage cmdlet you can use right now to send an email from PowerShell using SMTP protocol.

Send-MailMessage -To “<recipient’s email address>” -From “<sender’s email address>”  -Subject “Your message subject” -Body “Some important plain text!” -Credential (Get-Credential) -SmtpServer “<smtp server>” -Port 587

All you need is to insert the email address of a sender and a recipient, as well as specify the SMTP server you’re going to use. Then copy-paste this script to your PowerShell and press enter. 

Mailtrap will help us to check whether it works. Sign up and go to your Demo inbox. Find SMTP credentials and tweak the script like this:

Send-MailMessage -To “jon-snow@winterfell.com” -From “mother-of-dragons@houseoftargaryen.net”  -Subject “Hey, Jon” -Body “Some important plain text!” -Credential (Get-Credential) -SmtpServer “smtp.mailtrap.io” -Port 587

Here, we’ve just specified the SMTP host. The addresses of the recipient and the sender are not real, as you might have guessed. And that’s one of the benefits of using a fake SMTP server. You don’t have to deal with actual email to test the email workflow. Alternatively, you can use a dummy email, but it can be a poor testing practice. Learn why in our blog post Why Using Dummy Email for Testing Just Doesn’t Work

Once you copy and paste this script to PowerShell and hit enter, a window requesting SMTP credentials (username and password) will pop up. Fill them in with those of Mailtrap, and that’s it. Check your Demo inbox and find your message. 

Can I send an HTML email or an email with attachments from PowerShell to multiple recipients?

Yes you can! Send-MailMessage lets you pump up your email with the many parameters including HTML content, priority, and so on. Also, you can send emails to multiple recipients by specifying them in the corresponding parameter. Here is what you can make use of:

ParameterDescription
-To Email address of a recipient or recipients
-Bcc Email address of a BCC recipient or recipients
-Cc Email address of a CC recipient or recipients
-From Sender’s email address
-Subject Email subject
-Body Email body text
-BodyAsHtml Defines that email body text contains HTML
-Attachments Filenames to be attached and the path to them
-Credential Authentication to send the email from the account
-SmtpServer Name of the SMTP server
-Port Port of the SMTP server
-DeliveryNotificationOptionThe sender(s) specified in the Form parameter will be notified on the email delivery. Here are the options:
  • None – notifications are off (default parameter) 
  • OnSuccess – notification of a successful delivery 
  • OnFailure – notification of an unsuccessful delivery 
  • Delay – notification of a delayed delivery
  • Never – never receive notifications
  • -Encoding The encoding for the body and subject
    -Priority Defines the level of priority of the message. Valid options are:
  • Normal (default parameter)
  • Low
  • High
  • -UseSsl Connection to the SMTP server will be established using the Secure Sockets Layer (SSL) protocol

    So, let’s make a script that will send an email containing HTML text and an attachment. This time, we’ll define the parameters in advance and then refer to them in the Send-MailMessage cmdlet:

    $From = "mother-of-dragons@houseoftargaryen.net"
    $To = "jon-snow@winterfell.com", "jorah-mormont@night.watch”
    $Cc = "tyrion-lannister@westerlands.com"
    $Attachment = "C:\Temp\Drogon.jpg"
    $Subject = "Photos of Drogon"
    $Body = "<h2>Guys, look at these pics of Drogon!</h2><br><br>"
    $Body += “He is so cute!” 
    $SMTPServer = "smtp.mailtrap.io"
    $SMTPPort = "587"
    Send-MailMessage -From $From -to $To -Cc $Cc -Subject $Subject -Body $Body -BodyAsHtml -SmtpServer $SMTPServer -Port $SMTPPort -UseSsl -Credential (Get-Credential) -Attachments $Attachment

    As you noticed, we used $Body += to add a new line to the body text of the message. And that’s how the email looks in the Mailtrap inbox.

    Send an email from PowerShell using the Gmail SMTP server

    Everything is cool when you use a fake SMTP server for testing. But what if we send a message via a real one like Gmail. In this case, add smtp.gmail.com as the SMTP host and use real email addresses for a sender (your Gmail address) and a recipient. 

    We made an attempt and filled in credentials in the pop-up window. But the server replied with an error – 551 Authentication Required. To fix this issue, you need to turn on the Less secure app access in the Security tab of your Google Account. We did it, and PowerShell successfully delivered our message to the destination. Discover more about SMTP response codes and commands in our dedicated blog post. 

    SMTP settings for popular email providers 

    Not everyone is a Gmail user. So, the following data might be to the point if you use another SMTP host.

    ServiceSMTP serverPortConnection
    Gmailsmtp.gmail.com587
    25
    465
    TLS
    TLS
    SSL
    Office 365smtp.office365.com587
    25
    TLS
    Outlook.comsmtp-mail.outlook.com587
    25
    TLS
    Yahoo mailsmtp.mail.yahoo.com587
    25
    465
    TLS
    TLS
    SSL
    Windows Live Hotmailsmtp.live.com587
    25
    TLS
    Zohosmtp.zoho.com587
    465
    TLS
    SSL

    Send emails from PowerShell using EASendMail 

    EASendMail is an SMTP component that supports such protocols as SMTP, ESMTP (extended SMTP), EWS (Exchange Web Service), and WebDAV (Web Distributed Authoring and Versioning) protocols. The component is mostly used to send emails in COM/.NET/.NET Core environment applications and apps built with:

    • ASP
    • VB
    • VBA
    • VC++
    • C++/CLI
    • C#
    • VB.NET
    • JavaScript
    • ASP.NET
    • Delphi 

    Also, you can use EASendMail to send emails from PowerShell. God only knows why you may need it but here is a guide for this:

    • Step 1: Install EASendMail using the installer
    • Step 2: Create the following script
    [reflection.assembly]::LoadFile("C:\Program Files (x86)\EASendMail\Lib\net20\EASendMail.dll")
    #change the path to the EASendMail.dll file if you have another build of run-time assembly for .NET Framework, .NET Core, or .NET Compact Framework
    
    function SendMailTo($sender, $name, $address, $subject, $body, $htmlFormat) {
    
        $mail = New-Object EASendMail.SmtpMail("TryIt") # you can replace “TryIt” with your license code for EASendMail SMTP component
        $mail.From.Address = $sender
    
        $recipient = New-Object EASendMail.MailAddress($name, $address)
        $mail.To.Add($recipient) > $null
    
        $mail.Subject = $subject
        if($htmlFormat) {
            $mail.HtmlBody = $body
        }
        else {
            $mail.TextBody = $body
        }
    
        $server = New-Object EASendMail.SmtpServer("smtp.mailtrap.io")
        $server.User = "*********"
        $server.Password = "*********"
    
        $server.Port = 587
    
        $server.ConnectType = [EASendMail.SmtpConnectType]::ConnectTryTLS
    # specify your settings of the SMTP server, username, password, port, and connection type
    
        $smtp = New-Object EASendMail.SmtpClient
        $smtp.SendMail($server, $mail)
    }
    
    function SendMailFromPowerShell () {
        $sender = "mother-of-dragons@houseoftargaryen.net"
        $name = "Jon Snow"
        $address = "jon-snow@winterfell.com"
        $subject = "Happy Samhain"
        $body = "Jonny, congrats on Samhain!"
    # specify your settings of sender’s email address and name, recipient’s email address, as well as subject and body text of the message
        try {
            "Start to send email to {0} ..." -f $address
            SendMailTo $sender $name $address $subject $body ""
            "Email to {0} has been submitted to server!" -f $address
        }
        catch [System.Exception] {
            "Failed to send email: {0}" -f  $_.Exception.Message
        }
    }
    
    SendMailFromPowerShell
    • Step 3: Run the script and check the Mailtrap Demo inbox. Here is the message. 

    Mass mailing from PowerShell using EASendMail Service Queue

    EASendMail SMTP component is useful for sending mass emails. For this, you don’t have to code multiple threadings.  All you need is EASendMail Service that can send messages with multiple threadings automatically in background queue. Take a look at the following script for mass mailing of a message with an HTML template:

    [reflection.assembly]::LoadFile("C:\Program Files (x86)\EASendMail\Lib\net20\EASendMail.dll")
    #change the path to the EASendMail.dll file if you have another build of run-time assembly for .NET Framework, .NET Core, or .NET Compact Framework
    
    function SendMailToQueue($sender, $name, $address, $subject, $body, $htmlFormat) {
    
        $mail = New-Object EASendMail.SmtpMail("TryIt")
        $mail.From.Address = $sender
    
        $recipient = New-Object EASendMail.MailAddress($name, $address)
        $mail.To.Add($recipient) > $null
    
        $mail.Subject = $subject
        if($htmlFormat) {
            $mail.HtmlBody = $body
        }
        else {
            $mail.TextBody = $body
        }
    
        $server = New-Object EASendMail.SmtpServer("smtp.mailtrap.io")
        $server.User = "*********"
        $server.Password = "*********"
    
        $server.Port = 587
    
        $server.ConnectType = [EASendMail.SmtpConnectType]::ConnectTryTLS
    # specify your settings of the SMTP server, username, password, port, and connection type
    
        $smtp = New-Object EASendMail.SmtpClient
        $smtp.SendMailToQueue($server, $mail)
    }
    
    function OpenConnection () {
    
        $connectionString = "Server=localhost\AdminSystem;Database=test;Integrated security=SSPI;MultipleActiveResultSets=True;"
        Write-Host(("Connecting database {0} ..." -f $connectionString))
        $sqlConnection = New-Object System.Data.SqlClient.SqlConnection
        $sqlConnection.ConnectionString = $connectionString
    # You can change the connection string to yours by specifying user and password: $connectionString = "Server=localhost\AdminSystem;Database=dbname;User Id=user;Password=yourpassword;MultipleActiveResultSets=True;"
        $sqlConnection.Open()
        Write-Host 'Connected'
        return $sqlConnection
    }
    
    function BuildHtmlBody ($sqlConnection) {
        Write-Host "Building HTML body based on database ..."
    
        $sqlQuery = "SELECT ID, Name, Email, Age, Department FROM users"
        $sqlCommand = New-Object System.Data.SqlClient.SqlCommand($sqlQuery, $sqlConnection);
        $reader = $sqlCommand.ExecuteReader()
    
        $html = "<!DOCTYPE html><html><body>"
        $html += "<div style=""font-family:'Segoe UI', Calibri, Arial, Helvetica; font-size: 14px; max-width: 768px;"">"
        $html += "Dear {name}, <br /><br />This is a congrats email on Samhain. <br />"
        $html += "Here is full data in table:<br /><br />"
        $html +="<table style='border-spacing: 0px; border-style: solid; border-color: #ccc; border-width: 0 0 1px 1px;'>"
    
        while ($reader.Read()) {
            $name = $reader.GetString(1)
            $address = $reader.GetString(2)
            $age = $reader.GetInt32(3)
            $department = $reader.GetString(4)
    
            $html += "<tr>"
            $html += "<td style='padding: 10px; border-style: solid; border-color: #ccc; border-width: 1px 1px 0 0;'>{0}</td>"  -f $name
            $html += "<td style='padding: 10px; border-style: solid; border-color: #ccc; border-width: 1px 1px 0 0;'>{0}</td>" -f $address
            $html += "</tr>"
    
        }
    
        $reader.Close > $null
        $reader.Dispose > $null
    
        $sqlCommand.Close > $null
        $sqlCommand.Dispose > $null
    
        return $html
    }
    
    function SendMailFromDBToQueue () {
        $sender = "mother-of-dragons@houseoftargaryen.net"
        $subject = "Happy Samhain"
    
        $sqlConnection = OpenConnection
        $bodyTemplate = BuildHtmlBody($sqlConnection)
    
    $sqlQuery = "SELECT ID, Name, Email, Age, Department FROM users"
            $sqlCommand = New-Object System.Data.SqlClient.SqlCommand($sqlQuery, $sqlConnection);
            $reader = $sqlCommand.ExecuteReader()
            while ($reader.Read()) {
                $name = $reader.GetString(1).Trim()
                $address = $reader.GetString(2).Trim()
                $body = $bodyTemplate.Replace("{name}", $name)
    
                Write-Host(("Start to send email to {0} ..." -f $address))
                SendMailToQueue $sender $name $address $subject $body "html"
                Write-Host(("Email to {0} has been submitted to easendmail service!" -f $address))
            }
    
            $reader.Close > $null
            $reader.Dispose > $null
    
            $sqlCommand.Close > $null
            $sqlCommand.Dispose > $null
    
            $sqlConnection.Close > $null
            $sqlConnection.Dispose > $null
        }
        catch [System.Exception] {
            "Failed to send email: {0}" -f  $_.Exception.Message
        }
    }
    
    SendMailFromDBToQueue

    Send emails from PowerShell using System.Net.Mail API

    Send-MailMessage cmdlet is the most common option for sending emails from PowerShell. But this was not always the case. It became available starting from PowerShell 3.0 and was based on System.Net.Mail API. It is a namespace that contains classes to send electronic messages to the SMTP server. The delivery is carried out using the SmtpClient.Send or .Send method. Let’s take a look at the following example:

    $EmailFrom = “mother-of-dragons@houseoftargaryen.net”
    $EmailTo = “jon-snow@winterfell.com”
    $Subject = “Happy Samhain”
    $Body = “Jonny, congrats on Samhain!”
    $SMTPServer = “smtp.mailtrap.io”
    $SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
    $SMTPClient.EnableSsl = $true
    $SMTPClient.Credentials = New-Object System.Net.NetworkCredential("<username>", "<password>");
    $SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)

    Check out Mailtrap’s Demo inbox and voila – it’s in. Alternatively, you can use the .Send method and modified syntax like this one:

    $smtpFrom = “mother-of-dragons@houseoftargaryen.net”
    $smtpTo = “jon-snow@winterfell.com”
    $messageSubject = “Happy Samhain”
    $messageBody = “Jonny, congrats on Samhain!”
    $smtpServer = “smtp.mailtrap.io”
    $smtp = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
    $smtp.EnableSsl = $true
    $smtp.Credentials = New-Object System.Net.NetworkCredential("94b784b5970edf", "01a5d515011f6e");
    $smtp.Send($smtpFrom , $smtpTo, $messageSubject, $messageBody)

    To wrap up

    The System.Net.Mail namespace is also used to create and send messages in ASP.NET C# that we’ve also blogged about. And that’s it for today. We hope that this blog post broadened your skills in using PowerShell. Follow our blog and discover useful expertise for your projects.