This tutorial introduces how to send email from PowerShell. It also demonstrates SSL, HTML Email, SQL Server, Email Queue and Exchange Web Service (EWS) usage.
Sections:
To better demonstrate how to send email using SMTP protocol in PowerShell, let’s open PowerShell and set execution policy at first:
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
The Set-ExecutionPolicy cmdlet changes the user preference for the Windows PowerShell execution policy.
The execution policy is part of the security strategy of Windows PowerShell. It determines whether you can load configuration files (including your Windows PowerShell profile) and run scripts. Because we need to run script locally, so we changed the policy to RemoteSigned for current user.
EASendMail is a SMTP component which supports all operations of SMTP/ESMTP protocols (RFC 821, RFC 822, RFC 2554). It also supports Exchange Web Service (EWS) and WebDAV protocols. Before you can use the following example codes, you should download the EASendMail Installer and install it on your machine at first.
Then we can use the following codes to load EASendMail to PowerShell script and use it for sending email.
# please change the path to EASendMail Installation Path.
[reflection.assembly]::LoadFile("C:\Program Files (x86)\EASendMail\Lib\net20\EASendMail.dll")
Because EASendMail has separate builds for .Net Framework, please refer to the following table and choose the correct dll.
Separate builds of run-time assembly for .NET Framework 1.1, 2.0, 3.5, 4.0, 4.5, 4.6.1, .NET Core 2.1 and .NET Compact Framework 2.0, 3.5.
File | .NET Framework Version |
Lib\net11\EASendMail.dll |
Built with .NET Framework 1.1
It requires .NET Framework 1.1, 2.0, 3.5 or later version. |
Lib\net20\EASendMail.dll |
Built with .NET Framework 2.0
It requires .NET Framework 2.0, 3.5 or later version. |
Lib\net35\EASendMail.dll |
Built with .NET Framework 3.5
It requires .NET Framework 3.5 or later version. |
Lib\net40\EASendMail.dll |
Built with .NET Framework 4.0
It requires .NET Framework 4.0 or later version. |
Lib\net45\EASendMail.dll |
Built with .NET Framework 4.5
It requires .NET Framework 4.5 or later version. |
Lib\net461\EASendMail.dll |
Built with .NET Framework 4.6.1
It requires .NET Framework 4.6.1 or later version. |
Lib\netcoreapp2.1\EASendMail.dll |
Built with .NET Core 2.1
It requires .NET Core 2.1 or later version. |
Lib\net20-cf\EASendMail.dll |
Built with .NET Compact Framework 2.0
It requires .NET Compact Framework 2.0, 3.5 or later version. |
Lib\net35-cf\EASendMail.dll |
Built with .NET Compact Framework 3.5
It requires .NET Compact Framework 3.5 or later version. |
Now let’s create a script named “SendEmailFromPowerShell.ps1” by notepad like this:
notepad SendEmailFromPowerShell.ps1
After notepad is opened, input the following codes and save it.
# To use the following codes, please download and install
# https://www.emailarchitect.net/webapp/download/easendmail.exe on your machine
[reflection.assembly]::LoadFile("C:\Program Files (x86)\EASendMail\Lib\net20\EASendMail.dll")
function SendMailTo($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
}
# please change server, user, password to yours
$server = New-Object EASendMail.SmtpServer("mail.emailarchitect.net")
$server.User = "test@emailarchitect.net"
$server.Password = "yourpassword"
# If your 25 port is blocked by ISP, you can try to use 587 port
$server.Port = 25
# Using TryTLS,
# If smtp server supports TLS, then TLS connection is used; otherwise, normal TCP connection is used.
# https://www.emailarchitect.net/easendmail/sdk/?ct=o_smtpconnecttype
$server.ConnectType = [EASendMail.SmtpConnectType]::ConnectTryTLS
# If your server is Exchange 2007 or later version, you can use EWS protocol.
# https://www.emailarchitect.net/easendmail/sdk/?ct=o_serverprotocol
# Set Exchange Web Service Protocol - EWS - Exchange 2007/2010/2013/2016
# $server.Protocol = [EASendMail.ServerProtocol]::ExchangeEWS
$smtp = New-Object EASendMail.SmtpClient
$smtp.SendMail($server, $mail)
}
function SendMailFromPowerShell () {
$sender = "test@emailarchitect.net"
$name = "PowerShell"
$address = "powershell@appmaildev.com"
$subject = "Test email from Powershell"
$body = "This is a test email from Powershell"
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
Run the script like this:
.\SendEmailFromPowerShell.ps1
You will see the status and result in PowerShell Console Output.
When you execute above example code, if it returned an error about “Networking connection/Socket” or “No such host”, it is likely that your SMTP server address is not correct. If it threw an exception about “5xx Relay denied”, it is likely that you did not set user authentication. Another common error is “5xx Must issue a STARTTLS command first” or “No supported authentication marshal found!”, that is because your SMTP server requires user authentication under SSL connection. You can set the SSL connection to solve this problem. You can learn more detail in Troubleshooting section.
Because each email account provider has different server address, so you should query your SMTP server address from your email account provider. To prevent spreading email from the server, most SMTP servers also require user authentication. User name is your email address or your email address without domain part, it depends on your email provider setting.
Finally, if you have already set your account in your email client such as Outlook or Window Mail, you can query your SMTP server address, user in your email client. For example, you can choose menu -> “Tools” - > - “Accounts” - > “Your email account” - > “Properties” - > “Servers” in Outlook express or Windows Mail to get your SMTP server, user. Using EASendMail to send email does not require you have email client installed on your machine or MAPI, however you can query your exist email accounts in your email client.
Here are common settings for well-known email providers:
Gmail SMTP server address is smtp.gmail.com
. It requires implicit SSL or explicit SSL (TLS) connection,
and you should use your Gmail email address as the user name for ESMTP authentication.
For example: your email is gmailid@gmail.com
, and then the user name should be
gmailid@gmail.com
.
Server | Port | SSL/TLS |
smtp.gmail.com | 25, 587 | TLS |
smtp.gmail.com | 465 | SSL |
Important
If you got authentication error, you need to enable Allowing less secure apps or Sign in using App Passwords.
The Gmail IMAP and SMTP servers have been extended to support authorization via the industry-standard OAuth 2.0 protocol. Using OAUTH protocol, user can do authentication by Gmail Web OAuth instead of inputting user and password directly in application. This way is more secure, but a little bit complex.
Hotmail/Live/Outlook.com SMTP server address is smtp.office365.com
. It requires explicit SSL (TLS) connection
to do user authentication, and you should use your Hotmail/Live/Outlook.com email address as the user
name for ESMTP authentication. For example: your email is liveid@hotmail.com
,
and then the user name should be liveid@hotmail.com
.
If your account enabled two-factor authentication, you cannot login your account by normal user authentication, you should use SMTP OAUTH or App Password.
You can generate App Passwords and use this app password instead of your user password.
Server | Port | SSL/TLS |
smtp.office365.com | 25, 587 | TLS |
By default, Office 365 SMTP server uses 587 port and explicit SSL (TLS) connection.
If your account enabled two-factor authentication, you cannot login your account by normal user authentication, you should use SMTP OAUTH or App Password. You can generate App Passwords and use this app password instead of your user password.
Server | Port | SSL/TLS |
smtp.office365.com | 25, 587 (recommended) | TLS |
Yahoo SMTP server address is smtp.mail.yahoo.com
. It supports both Normal/Implicit SSL/Explicit SSL (TLS)
connection to do user authentication, and you should use your Yahoo email address
as the user name for ESMTP authentication. For example: your email is myid@yahoo.com
,
and then the user name should be myid@yahoo.com
.
If you want to use implicit SSL connection with Yahoo SMTP server, you must set the port to 465.
Server | Port | SSL/TLS |
smtp.mail.yahoo.com | 25, 587 | TLS |
smtp.mail.yahoo.com | 465 | SSL |
Important
If you got authentication error, you need to enable Allowing less secure apps in your Yahoo account. Or you can generate App Passwords and use this app password instead of your user password.
Although Yahoo supports OAUTH, but it doesn’t provide mail permission, so OAUTH is not a solution for Yahoo mail.
The following example codes demonstrates how to specify display name and email address by different syntax.
// For single email address (From, ReplyTo, ReturnPath), the syntax can be:
// ["][display name]["]<email address>.
// For example:
"Tester, T" <test@adminsystem.com>
Tester <test@adminsystem.com>
<test@adminsystem.com>
test@adminsystem.com
// For mulitple email address (To, CC, Bcc), the syntax can be:
// [single email],[single email]...
// (,;\r\n) can be used to separate multiple email addresses.
// For example:
"Tester, T" <test1@adminsystem.com>, Tester2 <test2@adminsystem.com>,
<test3@adminsystem.com>, test4@adminsystem.com
Here are some examples:
# From is a MailAddress object, it supports implicit converting from string.
# The syntax is like this: "test@adminsystem.com" or "Tester<test@adminsystem.com>"
# The example code without implicit converting:
$mail = New-Object EASendMail.SmtpMail("TryIt")
$mail.From = New-Object EASendMail.MailAddress("Tester", "test@adminsystem.com")
$mail.From = New-Object EASendMail.MailAddress("Tester<test@adminsystem.com>")
$mail.From = New-Object EASendMail.MailAddress("test@adminsystem.com")
# To, Cc and Bcc is a AddressCollection object, it supports implicit converting
# from string. Multiple addresses are separated with (,;)
# The syntax is like this: "test@adminsystem.com, test1@adminsystem.com"
# The example code without implicit converting:
$mail.To = New-Object EASendMail.AddressCollection("test1@adminsystem.com, test2@adminsystem.com" )
$mail.To = New-Object EASendMail.AddressCollection("Test1<test@adminsystem.com>, Test2<test2@adminsystem.com>")
# You can add more recipient by Add method:
$mail.To.Add((New-Object EASendMail.MailAddress( "tester", "test@adminsystem.com")))
# You can also add carbon copy (CC) or blind carbon copy (BCC) in the email:
$mail.Cc.Add((New-Object EASendMail.MailAddress("CC recipient", "cc@adminsystem.com")))
$mail.Bcc.Add((New-Object EASendMail.MailAddress("Bcc recipient", "bcc@adminsystem.com")))
From, Reply-To, Sender and Return-Path are common email headers in email message. You should always set From property at first, it is a MUST to identify the email sender. The following table lists the header and corresponding properties:
Header | Property |
From | SmtpMail.From |
Reply-To | SmtpMail.ReplyTo |
Sender | SmtpMail.Sender |
Return-Path | SmtpMail.ReturnPath |
From
This property indicates the original email sender. This is what you see as the “FROM” in most mail clients.
Reply-To
This property indicates the reply address. Basically, when the user clicks “reply” in mail client, the Reply-To value should be used as the recpient address of the replied email. If you don’t set this property, the Reply address is same as From address.
Sender
This property indicates the who submit/send the email. When the user received the email, the email client displays: From: “sender address” on behalf of “from address”. If you don’t set this property, the Sender address is same as From address. Sender property is common used by mail listing provider. This property also takes effect to DKIM/DomainKeys signature, if Sender is different with From address, then you should sign DKIM/DomainKeys based on Sender domain instead of From address domain.
Return-Path
This property indicates the delivery notification report address. If you don’t set this property, the Return-Path address is same as From address. This property also takes effect to SPF record, if Return-Path is different with From address, then remote SMTP server checkes SPF record of Return-Path instead of From address.
The following example codes demonstrate how to specify From, Reply-To, Sender and Return-Path in Email. With the following example codes:
report@emailarchitect.net
.sender@emailarchitect.net
on behalf of from@adminsystem.com
.reply@adminsystem.com
.$mail = New-Object EASendMail.SmtpMail("TryIt")
$mail.From = "from@adminsystem.com"
$mail.ReplyTo = "reply@adminsystem.com"
$mail.Sender = "sender@emailarchitect.net"
$mail.ReturnPath = "report@emailarchitect.net"
If you want to set Higher or Lower priority to your email, you can use Priority prority
// Set high priority
$mail.Priority = [EASendMail.MailPriority]::High;
When you send email in above simple VB project, if it returned an error, please have a look at the following tips:
This error means DNS server cannot resolve SMTP server, you should check if you input correct server address. If your server address is correct, you should check if your DNS server setting is correct.
This error means there is a problem with networking connection to SMTP server. You can use Windows built-in Telnet command to detect the networking connection.
Note
Notice: in Windows 2008/Windows 8 or later version, Telnet Client
is not installed
by default, you should enable this command in Control Panel
-> Programs and
Features
-> Turn Windows feature on or off
-> have Telnet Client
checked.
Under DOS command prompt, input “telnet [serveraddress] [port]”:
telnet mail.emailarchitect.net 25
press enter.
If the networking connection to your SMTP server is good, it should return a message
like 220 ...
. If it returns Could not open connection to ...
, that means the
networking connection to SMTP server is bad, or outbound 25 port is blocked by anti-virus
software, firewall or ISP. Please have a look at the following screenshot:
25 port is the default SMTP server port to receive email. However, some ISP block outbound 25 port to prevent user to send email directly to other SMTP server. Therefore, many email providers also provide an alternative port 587 to receive email from such users. 465 port is the common port used to receive email over implicit SSL connection. If you use telnet to test 465 port, it doesn’t return the “220…”, because it requires SSL hand shake. But if the connection is ok, telnet returns a flash cursor.
This error means SMTP server blocks your IP address or email content. You can try to set user/password in your codes to do user authentication and try it again. If email client set user authentication, most SMTP servers do not check client source IP address in black list.
TThis error means user authentication is failed, you should check whether you input correct user/password. Password is always case-sensitive.
For anti-spam policy, most SMTP servers do not accept the email to outbound domain without user authentication. You should set user/password in the codes and try it again.
This error means SMTP server requires SSL/TLS connection. You should enable SSL/TLS connection like this:
# If your smtp server requires TLS connection, please add this line
$server.ConnectType = [EASendMail.SmtpConnectType]::ConnectSSLAuto;
This error means SMTP server doesn’t support user authentication or it requires user authentication over SSL/TLS connection. You can try to remove user/password in your codes and try it again.
If SMTP server returns an error, it usually returns description about this error. Some descriptions also include a HTTP link, you can go to this linked web page to learn more detail. You can also use the following codes to generate a log file to learn all SMTP session between client and server.
[PS - Using log file to detect SMTP server response - Example]
try
{
# add this line here to generate log file
$smtp.LogFileName = "d:\\smtp.txt"
$smtp.SendMail($server, $mail)
Write-Host "email was sent successfully!"
}
catch [System.Exception] {
"Failed to send email: {0}" -f $_.Exception.Message
}
TLS is the successor of SSL, more and more SMTP servers require TLS 1.2 encryption now.
If your operating system is Windows XP/Vista/Windows 7/Windows 2003/2008/2008 R2/2012/2012 R2
,
and you got connection error with SSL/TLS connection,
you need to enable TLS 1.2 protocol in your operating system like this:
Enable TLS 1.2 on Windows XP/Vista/7/10/Windows 2008/2008 R2/2012
Next Section
In this section, I introduced how to send text email in PowerShell script using SMTP protocol. At next section I will introduce how to send HTML email to recipients in SQL server using PowerShell script.