Easily send your DevOps reporting by email with this PowerShell function, because the Send-MailMessage cmdlet is obsolete. Of course you’ll be using StartTLS and authenticated SMTP as additional security.
Important: Is SMTP blocked? Many cloud providers (like Azure and AWS) block outbound SMTP on port 25. If you are running your script in the cloud, you should use an API-based approach instead. See my guide on Sending Mail through the SendGrid API with PowerShell.
If you’re trying to send an email using the Send-MailMessage cmdlet, it throws a warning on your shell:
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.
Time for something else, right?
In this post I provide you with a small PowerShell function you can use as to send email over an secured SMTP connection with SMTP authentication and StartTLS. As a framework you can use it in your own scripting, extend it, and you can even turn it into a PowerShell module. The mail function is quite rudimentary and has a lot of assumptions in it. All provided AS-IS.
Found this guide helpful? You can support my independent deep dives into Windows Server and DevOps by donating via PayPal. Every bit of support helps keep saotn.org fast and updated!
For modern Microsoft 365 environments, you should look into the Graph API or Mailozaurr (a popular community module). In this post I provide other options.
PowerShell function to send SMTP email
You can use the following function to send a basic email to an email address of your choosing. On your shell, or command line interface / cli, it prompts you for your SMTP authentication password. This way, using a SecureString, your password is not saved in PowerShells history file $env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt.
Function Send-MyMailMessage($from, $to)
{
$mailFrom = "${from}"
$mailTo = "${to}"
$Subject = "Test email"
$Body = "This is my email message"
$SMTPServer = "smtp.example.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SMTPServer, 587)
$SMTPClient.EnableSsl = $true
$ww = read-host -AsSecureString "Provide your email password."
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("${from}", "$(${ww} | convertfrom-securestring -AsPlainText)");
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)
}
Be sure to change the SMTP server address on line 6, and maybe the SMTP port 587 on line 7.
When you call Send-MyMailMessage with arguments $from and $to, like:
PS > Send-MyMailMessage jan@example.com admin@example.net
Provide your email password.: *****************
and you fill out your SMTP authentication password, an email is sent to admin@example.net with jan@example.com as the sender’s from address.
Instead of using .NET’s SMTP Class Net.Mail.SmtpClient, you can also use and reference MailKit.
Such a small, and rather static, PowerShell mail sending function is ideal for DevOps reporting. Of course you can expand the function with additional input variables and command line arguments, etc.
Send-MgUserMail as Send-MailMessage replacement
Another great option is to switch to Send-MgUserMail as the Send-MailMessage replacement. Send-MgUserMail is located in the Microsoft.Graph.Users.Actions Module.
About Send-MgUserMail:
Send the message specified in the request body using either JSON or MIME format. When using JSON format, you can include a file attachment in the same sendMail action call. When using MIME format: This method saves the message in the Sent Items folder. Alternatively, create a draft message to send later. To learn more about the steps involved in the backend before a mail is delivered to recipients, see here.
It is not hard cooking up a Send-MgUserMail script to send an email. Harm Veenstra over at “PowerShell is fun :)” has detailed instructions setting this up. Check it out here:
Send-MailKitMessage
Send-MailKitMessage is also a replacement for the obsolete Send-MailMessage, implementing the Microsoft recommended MailKit library.
Installing Send-MailKitMessage module
Installing the Send-MailKitMessage module is as easy as:
Install-Module -Name "Send-MailKitMessage" -Scope CurrentUser # For current user only (does not require elevated privileges)
Install-Module -Name "Send-MailKitMessage" -Scope AllUsers # For all users (requires elevated privileges)
Send email using Send-MailKitMessage
MailKit is alo mentioned in my post Use authenticated SMTP over TLS encrypted connections, in PHP, ASP and ASP.NET: Quick MailKit example.
Sending email using Send-MailKitMessage is easy and pretty straightforward. The aforementioned GitHub project page lists all parameters. As a test, I took some of them and created the following script:
using module Send-MailKitMessage;
#use secure connection if available ([bool], optional)
$UseSecureConnectionIfAvailable = $true;
#authentication ([System.Management.Automation.PSCredential], optional)
$SMTPUser = "emailaddress@example.org"
$SMTPPass = "your-p4ssw0rd%"
$Credential = [System.Management.Automation.PSCredential]::new("${SMTPUser}", (ConvertTo-SecureString -String "${SMTPPass}" -AsPlainText -Force));
#SMTP server ([string], required)
$SMTPServer = "smtp.example.org";
#port ([int], required)
$Port = 587;
#sender ([MimeKit.MailboxAddress] http://www.mimekit.net/docs/html/T_MimeKit_MailboxAddress.htm, required)
$From = [MimeKit.MailboxAddress]"sender@example.org";
#recipient list ([MimeKit.InternetAddressList] http://www.mimekit.net/docs/html/T_MimeKit_InternetAddressList.htm, required)
$RecipientList = [MimeKit.InternetAddressList]::new();
$RecipientList.Add([MimeKit.InternetAddress]"recipient@example.com");
#subject ([string], optional)
$Subject = [string]"Test email";
#text body ([string], optional)
$TextBody = [string]"TextBody";
#HTML body ([string], optional)
$HTMLBody = [string]"HTMLBody";
#splat parameters
$Parameters = @{
"UseSecureConnectionIfAvailable" = $UseSecureConnectionIfAvailable
"Credential" = $Credential
"SMTPServer" = $SMTPServer
"Port" = $Port
"From" = $From
"RecipientList" = $RecipientList
"Subject" = $Subject
"TextBody" = $TextBody
"HTMLBody" = $HTMLBody
};
#send message
Send-MailKitMessage @Parameters;
As you can see I changed $Credential a bit so not all is in one line and SMTP username and SMTP password are in their own variables. Be sure to set (and keep) $UseSecureConnectionIfAvailable to $true, as this sets MailKit.Security.SecureSocketOptions to Auto. Making the SMTP connection using StartTLS / TLS if available on your SMTP server.
Frequently Asked Questions
The Send-MailMessage cmdlet in PowerShell is considered obsolete and should be avoided for sending emails. It lacks support for modern email authentication and secure connections, making it potentially insecure. Microsoft recommends using alternative solutions like the Send-MgUserMail cmdlet or the Mailkit module.
Alternatives for PowerShell Send-MailMessage are Send-MgUserMail, Send-MgUserMessage and Send-MailKitMessage. The first two rely on Microsoft.Graph.
Conclusion
This post showed you how to send email with PowerShell using Net.Mail.SmtpClient, because the PS Send-MailMessage cmdlet is obsolete. The provided function uses StartTLS for encryption and SMTP authentication to your SMTP server for additional security. As an alternative to Send-MailMessage, information about Send-MgUserMail and an example for Send-MailKitMessage are also provided.
Quick Guide: SMTP vs. API
| Feature | Standard SMTP (Send-MailMessage) | SendGrid API (REST) |
| Best For | Internal servers, Exchange, local relays. | Azure/AWS, Cloud apps, High-volume. |
| Common Ports | 587 (StartTLS) or 465 (SSL). | 443 (HTTPS). |
| Cloud Status | Port 25 is almost always blocked. | Fully supported in all cloud environments. |
| Security | Basic Auth / IP Whitelisting. | Secure API Keys / Bearer Tokens. |
| Analytics | Minimal (Server logs only). | Full (Opens, clicks, bounces). |
When configuring SMTP, aim for Port 587 with StartTLS as it is the modern standard for secure mail submission. If you are unsure if your server supports it, you can manually test SMTP authentication and StartTLS via Telnet or OpenSSL first. Avoid Port 25 for anything other than internal relays, as most modern cloud providers (Azure/AWS) block it by default to prevent spam.
Summary
- To send email with PowerShell, use a custom function since Send-MailMessage is obsolete and lacks security features.
- For secure SMTP connections, implement StartTLS and use SMTP authentication when sending emails.
- Consider alternatives like Send-MgUserMail or MailKit’s Send-MailKitMessage for better compatibility and security.
- Make sure to modify the SMTP server details in the provided function and keep your credentials secure.
- Cloud environments often block outbound SMTP; use API-based methods when applicable.