How to Send an Email Using Windows PowerShell

On September 11, 2019
9min read
Zakhar Yung Technical Content Writer @Mailtrap

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.

To check if the code works properly, you can send a test email to a virtual inbox. For this, you need a proper email-testing solution, such as Mailtrap Email Sandbox belonging to the Mailtrap email delivery platform. 

Email Sandbox provides you with a virtual inbox (or up to 300 virtual inboxes with its highest plan) to which you can send test emails and then inspect and debug them. This way, the solution creates a safe environment for you to find any issues related to your emails without the risk of spamming real recipients or ruining your domain reputation since you no longer have to use your personal inbox for testing purposes.

The features of Mailtrap Email Sandbox include HTML/CSS analysis, email content spam score checking and previewing, insight into valuable tech info, domain blacklist reports, and more. This means that this testing solution will come in handy regardless of if you are working with plain text or HTML emails, include images/attachments or not, and so on.

To send a test email to Email Sandbox, this is the script you can use:

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 an email testing solution – you don’t have to deal with an actual email to test the email workflow. 

Once you copy and paste this script to PowerShell and hit Enter, a window requesting the SMTP credentials (username and password) of your virtual inbox will pop up. You can find those credentials in your Mailtrap account under Email Sandbox – > Inboxes – > SMTP Settings.

Enter the credentials using the pop-up window and continue. Soon after that, the test email should appear in your virtual inbox.

Alternatively, you can use a dummy email, but that can be poor testing practice. Learn why in our blog post Why Using Dummy Email for Testing Just Doesn’t Work.

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

    You can now preview how this email looks and do an analysis of its HTML/CSS using Mailtrap Email Sandbox’s HTML Check feature. This feature gives you insight into the support top email clients have for the HTML elements and CSS rules used in your emails.

    For any unsupported or partially supported elements/rules, it will provide a list of email clients facing the issue as well as a link to the line of code containing the element/rule.

    Start testing your PowerShell emails for free.

    Send an email from PowerShell using Mailtrap Email API

    The Mailtrap email delivery platform also comes with an email-sending solution called Mailtrap Email API you can use to send your emails to real recipients from PowerShell or any other app.

    Email API provides a sending throughput of up to ~10,000 emails/second but also more control over email deliverability thanks to its actionable analytics features. 

    Using these actionable analytics features consisting of deliverability alerts, 60-day email logs, dashboards with critical metrics, and webhooks, you can find and fix sending issues very early on.

    What’s more, if you really want to dig deeper into your email performance, you can filter the performance stats Mailtrap Email API shows you by email category, mailbox provider, and or domain.

    Other features of Email API include dedicated IPs, auto IP warmup, and suppression lists, just to name a few.

    So, how does the sending process work?

    First, add and verify a domain under Email API -> Sending Domains in your Mailtrap account, as described in the video below.

    Then, to send with Email API in Windows PowerShell, insert the SMTP credentials provided by the sending solution into the script we used earlier. 

    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

    The credentials will be under Email API – > Sending Domains -> API and SMTP.

    Finally, run the script, enter the username and password requested of you, and your email should be sent off successfully.

    Send an email from PowerShell using the Gmail SMTP server

    In case you want to send emails via Gmail’s SMTP server, simply add smtp.gmail.com as the SMTP host.

    We made an attempt and filled in the 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. Here is a guide for this in the unlikely event that you will need it:

    • 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 go into your Email Sandbox virtual inbox to see the email.

    In the code above, we used Email Sandbox SMTP credentials, and that is why the email ended up there. You can, of course, change this according to your needs.

    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 a background queue. Take a look at the following script for mass mailing 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)

    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.

    Article by Zakhar Yung Technical Content Writer @Mailtrap

    Comments

    3 replies

    Tarun

    Hi,

    How can we add priority(High or Low) to this?

    $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)

    Thank You.

    ali

    Once the script executed it stucks at here
    Supply values for the following parameters:

    what I need to pass at here ??

    Nick

    Thanks a lot for this article, helped in configuration.

    Comments are closed.