You can use the built-in Send-MailMessage cmdlet to send SMTP e-mails from PowerShell (previously you can use the .Net System.Net.Mail
class to send e-mail messages). Send-MailMessage allows you to send messages with attachments, use HTML format for the body of the message, enable delivery notification, send a message to multiple recipients at once, etc. In this article, we’ll see how to use the Send-MailMessage
cmdlet to send e-mail messages from within your PowerShell scripts.
PowerShell Send-MailMessage Cmdlet
To get the syntax of the cmdlet, run this command:
Send-MailMessage [-To] <String[]> [-Subject] <String> [[-Body] <String>] [[-SmtpServer] <String>] [-Attachments <String[]>] [-Bcc <String[]>] [-BodyAsHtml] [-Cc <String[]>] [-Credential <PSCredential>] [-DeliveryNotificationOption {None | OnSuccess | OnFailure | Delay | Never}] [-Encoding <Encoding>] -From <String> [-Port <Int32>] [-Priority {Normal | Low | High}] [-UseSsl] [<CommonParameters>] The Send-MailMessage cmdlet sends an email message from within Windows PowerShell.
Here are the main options:
- From – is a sender address. You can send an email message on behalf of any email address if the SMTP server does not check the sender address (anonymous relay);
- To – the recipient’s email address;
- SMTPServer –the address of the SMTP server through which you want to send the e-mail.
The SMTP server address is not required if you set the mail server address in the $PSEmailServer environment variable:
$PSEmailServer = "smtp.woshub.com"
You can send an email to one or more recipient mailboxes, to a Teams channel, or an address in an Exchange distribution group.
Note that in the last command, we additionally set the UTF8 encoding for the email. Otherwise, if the email subject or body contains non-ANSI characters, they will be displayed incorrectly.
Windows PowerShell uses ANSI and ASCII encoding by default. If you’ve updated your PS version to PowerShell Core, keep in mind that this version already uses UTF-8 encoding by default.
You can specify multiple recipients by using the parameters:
To
– the regular recipient’s email addresses;Cc
– the email addresses to send a carbon copy (CC) of the email message;Bcc
– the e-mail addresses that will receive a copy of the e-mail but will not be listed as a recipient of the message.
You can enable a delivery notification for an email using -DeliveryNotificationOptions (which allows you to be notified when the recipient receives an email). The notification types available are:
- OnSuccess (Notify if the delivery is successful)
- OnFailure (Notify if the delivery is unsuccessful)
- Delay (Notify if the delivery is delayed)
You can specify multiple options in one command:
The delivery notification will be sent to the mailbox that is specified in the “From” field.
You can also set the priority of the email message (not shown in some clients):
If you want to add an attachment to your email, use the -Attachments option. In the example below, we are going to send an e-mail in the HTML format (-BodyAsHtml) and attach file1.txt and report.xsls from the local drive.
In this example, we have also replaced the recipient’s display name with “DC server”.
Here is how the HTML email with attachments looks in the Gmail interface.
Set-Mailbox it_dept -MessageCopyForSentAsEnabled $True
Using Send-MailMessage with SMTP Auth and TLS/SSL
By default, the Send-MailMessage cmdlet sends an e-mail via the default unencrypted SMTP port TCP 25. If your SMTP server allows sending e-mail only using an encrypted protocol, you can specify the port number in the -Port attribute (most often it is 465 or 587) and the –UseSsl option:
-SmtpServer 'smtp.woshub.com' -Port 465 –UseSsl
An error will occur if the SMTP server’s SSL certificate doesn’t match the FQDN specified in the HELO:
Send-MailMessage: The remote certificate is invalid according to the validation procedure.
You may also receive an error when sending an email using SSL/TLS encryption:
Send-MailMessage : Unable to read data from the transport connection: net_io_connectionclosed
- That the specified SMTP port is open and accessible from your computer:
Test-NetConnection smtp.woshub.com –Port 465
- Try a different SMTP port. For example, 587 (msa) instead of 465 (smtps). Port 587 is the default when using the STARTTLS extension;
- If you are using an older operating system (Windows Server 2012/Windows 8 and below), you must enable TLS 1.2 protocol support for PowerShell by using the command:
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
The table below lists the SMTP server settings for the popular public e-mail providers that you can use to send messages from PowerShell (note that you must allow e-mail to be sent via SMTP in the account interface.):
Name | SMTP Server Address | Port | Encryption Type |
Gmail | smtp.gmail.com | 587 | TLS |
Microsoft (Office) 365 | smtp.office365.com | 587 | TLS |
Outlook.com | smtp-mail.outlook.com | 587 | TLS |
Yahoo | smtp.mail.yahoo.com | 587 | TLS |
iCloud mail | smtp.mail.me.com | 587 | TLS |
AOL | smtp.aol.com | 465 | SSL |
If the SMTP server doesn’t allow anonymous email (relay is denied), you will see this error:
5.7.1 Client was not authenticated.
The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.57 SMTP; Client was not authenticated to send anonymous mail during MAIL FROM.
Then you can authenticate to the SMTP server using the -Credential option.
You can also specify the account credentials to use for authentication in the variable:
How to Send an Email via the Gmail SMTP with PowerShell?
To send an email from your mailbox on one of the public mail services, it is recommended that you use an App Password instead of a password to access your account/mailbox. For example, in Gmail, you can create an app password after you enable the two-factor authentication for your Google Account. Generate and copy your app password on Google (it’s a 16-character password).
A warning is displayed when you use the Send-MailMessage command in new versions of PowerShell Core 7.x:
WARNING: The command 'Send-MailMessage' is obsolete. This cmdlet does not guarantee secure connections to SMTP servers. While there is no immediate replacement available in PowerShell, we recommend you do not use Send-MailMessage at this time. See https://aka.ms/SendMailMessage for more information.
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.
We cover the process of writing the one-line script in detail in our Mailtrap tutorial:
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.

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.

Enter the credentials using the pop-up window and continue. Soon after that, the test email should appear in your virtual inbox.
For full instructions on how to send test emails from PowerShell using Mailtrap, watch our dedicated tutorial:
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:
Parameter | Description |
---|---|
-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 |
-DeliveryNotificationOption | The sender(s) specified in the Form parameter will be notified on the email delivery. Here are the options:
|
-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 = "live.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 Sending 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 categorizes email performace data by email category, mailbox provider, and/or domain.

Other features of Mailtrap Email Sending 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 Sending Domains in your Mailtrap account, as described in this knowledge base article.
Then, to send with Mailtrap in Windows PowerShell, first choose one of the sending streams Transactional or Bulk. Afterward, decide whether you will be using SMTP or API and find the necessary credentials under your selection.

Example code for sending via API:
# Define the API endpoint
$uri = "https://send.api.mailtrap.io/api/send"
# Define the JSON data
$jsonData = '{"from":{"email":"mailtrap@invminds.com","name":"Mailtrap Test"},"to":[{"email":"mailtrap.foo@gmail.com"}],"subject":"You are awesome!","text":"Congrats for sending test email with Mailtrap!","category":"Integration Test"}'
# Set headers
$headers = @{
"Content-Type" = "application/json"
"Authorization" = "Bearer 20a792***"
}
# Send the POST request
$response = Invoke-RestMethod -Uri $uri -Method Post -Body $jsonData -Headers $headers
# Display the response
$response
Example code for sending via SMTP:
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 "<live.smtp.mailtrap.io>" -Port 587 -UseSsl
For full instructions on how to send emails from PowerShell using the Mailtrap Email Sending email API, watch our dedicated tutorial:
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.
For full instructions on how to send emails from PowerShell using the Gmail SMTP, watch our dedicated tutorial:
SMTP settings for popular email providers
Service | SMTP server | Port | Connection |
Gmail | smtp.gmail.com | 587 25 465 | TLS TLS SSL |
Office 365 | smtp.office365.com | 587 25 | TLS |
Outlook.com | smtp-mail.outlook.com | 587 25 | TLS |
Yahoo mail | smtp.mail.yahoo.com | 587 25 465 | TLS TLS SSL |
Windows Live Hotmail | smtp.live.com | 587 25 | TLS |
Zoho | smtp.zoho.com | 587 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
- VBA
- VC++
- C++/CLI
- 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.
For full instructions on how to send emails from PowerShell using EASendMail, watch our dedicated tutorial:
Mass mailing from PowerShell using EASendMail Service Queue
[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
For full instructions on how to send mass emails from PowerShell, watch our dedicated tutorial:
Send emails from PowerShell using System.Net.Mail API
$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)
Доброго времени суток друзья. Хочу поделиться с Вами не большим скриптом на powershell отправки сообщения на внешнюю почту с авторизацией на примере smtp.yandex.ru
Класс System.Net.Mail.MailMessage
Имя | Описание | |
---|---|---|
![]() | AlternateViews | Возвращает коллекцию вложений, используемую для хранения альтернативных форм тела сообщения. |
![]() | Attachments | Возвращает коллекцию вложений, используемую для хранения данных, вложенных в это сообщение электронной почты. |
![]() | Bcc | Возвращает коллекцию адресов, содержащую получателей скрытой копии (BCC) данного сообщения электронной почты. |
![]() | Body | Получает или задает основную часть сообщения. |
![]() | BodyEncoding | Получает или задает кодировку, используемую для кодирования тела сообщения. |
![]() | BodyTransferEncoding | Получает или задает кодирование передачи, используемое для кодирования тела сообщения. |
![]() | CC | Возвращает коллекцию адресов, содержащую получателей копии (CC) данного сообщения электронной почты. |
![]() | DeliveryNotificationOptions | Получает или задает уведомления о доставке данного сообщения электронной почты. |
![]() | From | Получает или задает адрес отправителя данного сообщения электронной почты. |
![]() | Headers | Возвращает заголовки электронной почты, передаваемые с данным сообщением. |
![]() | HeadersEncoding | Получает или задает кодировку, используемую для пользовательских заголовков данного сообщения электронной почты. |
![]() | IsBodyHtml | Получает или задает значение, показывающее, имеет ли основная часть почтового сообщения формат HTML. |
![]() | Priority | Получает или задает приоритет данного сообщения электронной почты. |
![]() | ReplyTo | Устаревшее. Получает или задает адрес ReplyTo для данного почтового сообщения. |
![]() | ReplyToList | Получает или задает список адресов для ответа для данного сообщения электронной почты. |
![]() | Sender | Получает или задает адрес отправителя данного сообщения электронной почты. |
![]() | Subject | Получает или задает строку темы для данного сообщения электронной почты. |
![]() | SubjectEncoding | Получает или задает кодировку, используемую для темы данного сообщения электронной почты. |
![]() | To | Возвращает коллекцию адресов, содержащую получателей данного сообщения электронной почты. |
Класс Net.Mail.SmtpClient
Имя | Описание | |
---|---|---|
![]() | AlternateViews | Возвращает коллекцию вложений, используемую для хранения альтернативных форм тела сообщения. |
![]() | ClientCertificates | Указывает, какие сертификаты следует использовать для установки SSL-подключения. |
![]() | Credentials | Возвращает или задает учетные данные, используемые для проверки подлинности отправителя. |
![]() | DeliveryFormat | Получает или задает формат доставки, используемый SmtpClient для отправки электронной почты. |
![]() | DeliveryMethod | Указывает, как будут обрабатываться исходящие сообщения электронной почты. |
![]() | EnableSsl | Указывает, использует ли SmtpClient протокол SSL для шифрования подключения. |
![]() | Host | Возвращает или задает имя или IP-адрес хоста, используемого для SMTP-транзакций. |
![]() | PickupDirectoryLocation | Возвращает или задает папку, в которой приложения сохраняют почтовые сообщения для обработки локальным SMTP-сервером. |
![]() | Port | Возвращает или задает порт, используемый для SMTP-транзакций. |
![]() | ServicePoint | Возвращает сетевое подключение, используемое для передачи сообщения электронной почты. |
![]() | TargetName | Получает или задает имя поставщика услуг (SPN) для проверки подлинности при использовании расширенной защиты. |
![]() | Timeout | Возвращает или задает значение, указывающее промежуток времени, после которого для синхронного вызова Send истечет время тайм-аута. |
![]() | UseDefaultCredentials | Возвращает или задает значение Boolean, которое управляет отправкой учетных данных DefaultCredentials вместе с запросами. |
Имя | Описание | |
---|---|---|
![]() | Dispose() | Отправляет сообщение QUIT на SMTP-сервер, правильно завершает TCP-подключение и освобождает все ресурсы, используемые текущим экземпляром класса SmtpClient. |
![]() | Dispose(Boolean) | Отправляет сообщение QUIT на SMTP-сервер, правильно завершает TCP-подключение и освобождает все ресурсы, используемые текущим экземпляром класса SmtpClient, и при необходимости освобождает управляемые ресурсы. |
![]() | Equals(Object) | Определяет, равен ли заданный объект текущему объекту. (Унаследовано от Object.) |
![]() | Finalize | Позволяет объекту попытаться освободить ресурсы и выполнить другие операции по очистке перед тем, как объект будет утилизирован сборщиком мусора. (Унаследовано от Object.) |
![]() | GetHashCode | Играет роль хэш-функции для определённого типа. (Унаследовано от Object.) |
![]() | GetType | Возвращает объект класса Type для текущего экземпляра. (Унаследовано от Object.) |
![]() | MemberwiseClone | Создает “поверхностную” копию текущего объекта. (Унаследовано от Object.) |
![]() | OnSendCompleted | Создает событие SendCompleted. |
![]() | Send(MailMessage) | Отправляет указанное сообщение на сервер SMTP для доставки. |
![]() | Send(String, String, String, String) | Отправляет указанное сообщение электронной почты на сервер SMTP для доставки. Отправитель, получатели, тема и основная часть сообщения указываются с помощью объектов String. |
![]() | SendAsync(MailMessage, Object) | Отправляет указанное сообщение электронной почты на сервер SMTP для доставки. Этот метод не блокирует вызывающий поток и позволяет вызывающей стороне передать объект в метод, вызванный после завершения операции. |
![]() | SendAsync(String, String, String, String, Object) | Отправляет сообщение электронной почты на сервер SMTP для доставки. Отправитель, получатели, тема и основная часть сообщения указываются с помощью объектов String. Этот метод не блокирует вызывающий поток и позволяет вызывающей стороне передать объект в метод, вызванный после завершения операции. |
![]() | SendAsyncCancel | Отменяет асинхронную операцию отправки сообщения электронной почты. |
![]() | SendMailAsync(MailMessage) | Отправляет указанное сообщение SMTP-серверу для доставки в качестве асинхронной операции. |
![]() | SendMailAsync(String, String, String, String) | Отправляет указанное сообщение SMTP-серверу для доставки в качестве асинхронной операции. . Отправитель, получатели, тема и основная часть сообщения указываются с помощью объектов String. |
![]() | ToString | Возвращает строковое представление текущего объекта. (Унаследовано от Object.) |
Имя | Описание | |
---|---|---|
![]() | SendCompleted | Происходит после завершения асинхронной операции по отправке электронной почты. |
Листинг скрипта отправики письма
#Адрес сервера SMTP для отправки
$serverSmtp = "smtp.yandex.ru"
#Порт сервера
$port = 587
#От кого
$From = "login@yandex.ru"
#Кому
$To = "myMail@mail.ru"
#Тема письма
$subject = "Письмо с вложением"
#Логин и пароль от ящики с которого отправляете login@yandex.ru
$user = "login"
$pass = "12345678"
#Путь до файла
$file = "C:\arhive.zip"
#Создаем два экземпляра класса
$att = New-object Net.Mail.Attachment($file)
$mes = New-Object System.Net.Mail.MailMessage
#Формируем данные для отправки
$mes.From = $from
$mes.To.Add($to)
$mes.Subject = $subject
$mes.IsBodyHTML = $true
$mes.Body = "<h1>Тестовое письмо</h1>"
#Добавляем файл
$mes.Attachments.Add($att)
#Создаем экземпляр класса подключения к SMTP серверу
$smtp = New-Object Net.Mail.SmtpClient($serverSmtp, $port)
#Сервер использует SSL
$smtp.EnableSSL = $true
#Создаем экземпляр класса для авторизации на сервере яндекса
$smtp.Credentials = New-Object System.Net.NetworkCredential($user, $pass);
#Отправляем письмо, освобождаем память
$smtp.Send($mes)
$att.Dispose()
I am trying to add a in-line code and not a function to send an email to the below code, also would like to use the $json in the summary and the body like below, but I ran into an error where the summary cannot be null (Just trying to use the same summary in JSON)
$VIPResults = Get-NSVIPAlertingStatus
if ($null -ne $VIPResults)
{
foreach ($R in ($VIPResults | Where-Object Status -notmatch "Up|Out Of Service"))
{
if ($R.status -eq "Down")
{
$Stauts = $R.Status
$Severity = "5"
}
Elseif ($R.status -eq "Resolved")
{
$Stauts = $R.Status
$Severity = "0"
}
Write-Verbose "$(Get-Date): Send Alert: Netscaler $($R.name) on $($R.netscalername) is $($R.Status)" -Verbose
$JSON = @"
{
"summary": "Netscaler $($R.name) on $($R.netscalername) is $($R.Status)",
"node": "$($R.netscalername)",
"team": "",
"severity": $Severity,
"sop_link": "",
"category": "Netscaler component $($R.name)",
"integration": ""
}
"@
Write-Verbose "$(Get-Date):se" -Verbose
$Json
Invoke-WebRequest -Uri http:\\test.com -Method Post -Body \$Json -ContentType application/json -Verbose
}
}
I tried to add this below the invoke webrequest line, is that correct to place the $mailsplat line here
Write-Verbose "$(Get-Date):se" -Verbose
$Json
Invoke-WebRequest -Uri http:\\test.com -Method Post -Body \$Json -ContentType application/json -Verbose
$MailSplat = @{
To = "[email protected]"
From = "[email protected]"
Subject = $JSON.Summary
Body = $JSON
SmtpServer = "hub.test.com"
BodyAsHtml = $true
}
Send-MailMessage @MailSplat
}}
Practical Graph: Generate a Mailbox Traffic Report
Analyzing Mail Activity Usage Data to Compute Traffic for Each Domain
I was asked how easy it would be to generate a report about the number of emails sent per domain in a Microsoft 365 tenant. My initial response focused on the message trace log, with the idea that you could extract the domain for each outbound email and count them. This was a bad idea. The message trace log only holds data for the last ten days and is cluttered with information about system messages, such as public folder replication (for those who still use public folders). In any case, it would take a lot of work to extract and refine the information to answer the question.
Mail Usage Reports
Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/reports/getEmailActivityUserDetail(period='D90')" -OutputFilePath 'c:\temp\Data.csv'
Report Refresh Date : 2023-07-22 User Principal Name : Jeff.Clark@office365itpros.com Display Name : Jeff Clark Is Deleted : False Deleted Date : Last Activity Date : 2023-07-22 Send Count : 129 Receive Count : 637 Read Count : 692 Meeting Created Count : 0 Meeting Interacted Count : 0 Assigned Products : OFFICE 365 E3 Report Period : 90
In addition, because Microsoft calculates the mail activity data daily (it’s always a couple of days behind), fetching this data will be much faster and more scalable than attempting to retrieve and process message-tracing events.
Microsoft Graph PowerShell SDK Access to Usage Data
Connect-MgGraph -Scopes ReportSettings.ReadWrite.All, Directory.Read.All, Reports.Read.All Get-MgReportEmailActivityUserDetail -Period 'D7' -OutFile 'c:\temp\d7.csv'
- Run the Get-MgReportEmailActivityUserDetail to retrieve the mail usage data for 7, 30, 90, and 180 days.
- The cmdlet writes the mail usage data out to a CSV file. We end up with 4 files, one for each period, which the script can import into an array.
- Find all licensed user accounts with Get-MgUser. The code I use is:
[array]$Users = Get-MgUser -Filter "assignedLicenses/`$count ne 0 and userType eq 'Member'" -ConsistencyLevel eventual -CountVariable Records -All | Sort-Object UserPrincipalName
- For each account, fetch its mail usage activity and build a map of the account’s mail activity over 6, 30, 90, and 180 days.
- Write the information into a PowerShell list.
Here’s the code I wrote:
Write-Output "Fetching mail activity usage report data..." Get-MgReportEmailActivityUserDetail -Period 'D7' -OutFile 'c:\temp\d7.csv' Get-MgReportEmailActivityUserDetail -Period 'D30' -OutFile 'c:\temp\d30.csv' Get-MgReportEmailActivityUserDetail -Period 'D90' -OutFile 'c:\temp\d90.csv' Get-MgReportEmailActivityUserDetail -Period 'D180' -OutFile 'c:\temp\d180.csv' # Import the data into arrays [array]$D7Data = Import-CSV 'c:\temp\d7.csv' | Sort-Object 'User Principal Name' [array]$D30Data = Import-CSV 'c:\temp\d30.csv' | Sort-Object 'User Principal Name' [array]$D90ata = Import-CSV 'c:\temp\d90.csv' | Sort-Object 'User Principal Name' [array]$D180Data = Import-CSV 'c:\temp\d180.csv' | Sort-Object 'User Principal Name' # Process mailboxes $Report = [System.Collections.Generic.List[Object]]::new() ForEach ($User in $Users) { [array]$D7Email = $D7Data | Where-Object {$_.'User Principal Name' -eq $User.UserPrincipalName} [array]$D30Email = $D30Data| Where-Object {$_.'User Principal Name' -eq $User.UserPrincipalName} [array]$D90Email = $D90ata | Where-Object {$_.'User Principal Name' -eq $User.UserPrincipalName} [array]$D180Email = $D180Data | Where-Object {$_.'User Principal Name' -eq $User.UserPrincipalName} If ($D7Email.'Report Refresh Date') { $ReportDate = Get-Date($D7Email.'Report Refresh Date') -format dd-MMM-yyyy } Else { $ReportDate = $Null } If ($D7Email.'Last Activity Date') { $LastActivityDate = Get-Date($D7Email.'Last Activity Date') -format dd-MMM-yyyy } Else { $LastActivityDate = $Null } $ReportLine = [PSCustomObject] @{ User = $User.UserPrincipalName Name = $User.DisplayName 'Data Date' = $ReportDate 'Last Activity' = $LastActivityDate 'D7 Mail In' = $D7Email.'Receive Count' 'D7 Mail Out' = $D7Email.'Send Count' 'D30 Mail In' = $D30Email.'Receive Count' 'D30 Mail Out' = $D30EMail.'Send Count' 'D90 Mail In' = $D90Email.'Receive Count' 'D90 Mail Out' = $D90Email.'Send Count' 'D180 Mail In' = $D180Email.'Receive Count' 'D180 Mail Out' = $D180Email.'Send Count' Domain = $User.Mail.Split('@')[1]} $Report.Add($ReportLine) }
User : Jeff.Clark@office365itpros.com Name : Jeff Clark Data Date : 22-Jul-2023 Last Activity : 22-Jul-2023 D7 Mail In : 53 D7 Mail Out : 9 D30 Mail In : 105 D30 Mail Out : 17 D90 Mail In : 200 D90 Mail Out : 27 D180 Mail In : 637 D180 Mail Out : 129 Domain : Office365itpros.com
Piping the data to Out-GridView gives a good overview of the mail usage activity for accounts across the four periods (Figure 1).

[array]$Domains = Get-MgDomain | Select-Object -ExpandProperty Id $OutputData = [System.Collections.Generic.List[Object]]::new() ForEach ($Domain in $Domains) { $DomainData = $Report | Where-Object {$_.Domain -eq $Domain} $DomainSendCount = ($DomainData.'D180 Mail out' | Measure-Object -Sum).Sum $DomainOutput = [PSCustomObject] @{ 'Domain' = $Domain 'Send Count' = $DomainSendCount } $OutputData.Add($DomainOutput) } # Display the domain data $OutputData | Sort-Object 'Send Count' -Descending
The resulting output looks like this:
Domain Send Count ------ ---------- redmondwork.org 2503 office365itpros.com 212 office365itproebook.com 0
Dealing with Obfuscated User Data

Fortunately, we can handle this situation in code. This snippet checks if the display concealed names setting is True. If it is, the script resets it to False to expose the real data.
If ((Get-MgBetaAdminReportSetting).DisplayConcealedNames -eq $True) { $Parameters = @{ displayConcealedNames = $False } Update-MgBetaAdminReportSetting -BodyParameter $Parameters $DisplayConcealedNames = $True }
After processing is complete, the script can reset the value to True with:
If ($DisplayConcealedNames -eq $True) { $Parameters = @{ displayConcealedNames = $True } Update-MgBetaAdminReportSetting -BodyParameter $Parameters $DisplayConcealedNames = $Null }
Changing the display concealed names setting is why the script needs the ReportSettings.ReadWrite.All permission. You can download the full script from GitHub.
Never Wasting Time with PowerShell
This is a long-winded answer to a question that I thought would be quick. However, writing PowerShell is never wasted time and this response allowed me to show how to use the Microsoft Graph for PowerShell SDK (V2) to download usage data and change report settings. You never know when this knowledge might be useful!
PowerShell is a great tool to automate tasks and create reports or exports, but at some point, you want to send an email with PowerShell. Maybe when a task failed or too automatically email the report.
For sending emails with PowerShell we could always rely on the send mailmessage cmdlet. But this cmdlet is obsolete now and Microsoft recommends not to use it anymore. So what is currently the best way to send emails with PowerShell?
In this article
In this article, we will look at the alternatives for the Send-MailMessage cmdlet in PowerShell to send email.
Send-MailMessage Obsolete
To send email from PowerShell we could always use the Send-MailMessage cmdlet. This cmdlet allows you to send emails including attachments from an SMTP server that you specify. The problem with the send mailmessage cmdlet is that it doesn’t support modern protocols and authentication.
This means that you can’t use it anymore in combination with Exchange Online for example. You could, however, still use it with other SMTP servers that don’t require a secure connection.
$smtpServer = "smtp.mailserver.com" $smtpPort = 587 $smtpUsername = "user@mailserver.com" $smtpPassword = ConvertTo-SecureString -String "PassWord123" -AsPlainText -Force $smtpCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $smtpUsername, $smtpPassword Send-MailMessage -To "john@contoso.com" -From "powershell@lazyadmin.nl" -Subject "SMTP email" -Body "Email body with message you want to send" -SmtpServer $smtpServer -Port $smtpPort -UseSSL -Credential $smtpCredential
Microsoft isn’t updating the Send-MailMessage
cmdlet at the moment. But there are a couple of alternatives that we can use to send emails. We will focus on 3 methods:
- Using the PnPOnline module
- Sending emails with Microsoft Graph
- Mailozaurr PowerShell Module
Using PnPOnline module – Send-PnPMail
The Send-PnpMail method uses Microsoft Graph in the background. When you install and register the PnPOnline module, the required permissions are automatically added to the enterprise application that is created in Azure. It’s also possible to use the Exchange Online server directly, but then you are limited to internal email only.
A downside of the Send-PnPMail module is that you can’t add attachments to your emails. So keep that in mind. Also, it requires at least PowerShell 7, which isn’t installed by default on Windows 2022 for example.
Sending email with Send-PnPMail
Connect-PnPOnline -url https://lazydev-admin.sharepoint.com -interactive
To simply send an email you will need to specify the From and To address, subject, and body of the email:
Send-PnPMail -From "user@contoso.onmicrosoft.com" -To "recipient@contoso.com" -Subject "Test message" -Body "This is a test message"
The email will be saved in the send items of the mailbox you specified to send from. This method will work for sending emails to both internal and external recipients.
If we look at the documentation of the Send-PnPMail cmdlet then the content type of the body should be HTML by default. However, during my tests, I noticed that HTML wasn’t parsed correctly. Only after I set the BodyContentType
parameter to true was HTML supported:
$EmailParams = @{ From = "admin@lazyadmin.nl" To = "meganb@lazyadmin.nl" Subject = "Domain Controller Health Report" BodyContentType = "HTML" Body = $htmlTable } Send-PnPMail @EmailParams
In the example above I am using splatting to configure the parameters for the Send-PnPMail cmdlet. This makes it easier to read and change the parameters.
$EmailParams = @{ From = "admin@lazyadmin.nl" To = "meganb@lazyadmin.nl" Subject = "Test Email" Body = "This is a test email sent using PowerShell in Office 365." Server = "smtp.myisp.com" Port = 587 EnableSsl = $true Username = "lazyuser" Password = "password123" } Send-PnPMail @EmailParams