logo

Why PowerShell Send-MailMessage Is Deprecated and What to Use Instead

Introduction to Sending Emails with PowerShell

PowerShell is an indispensable tool for task automation, configuration management, system monitoring and querying data. But you can also send email with PowerShell. For instance, PowerShell scripts can monitor systems and post email alerts for specific events, resource constraints or completed tasks. However, it’s critical to ensure that emails are sent in a secure manner. Let’s dive into why the old PowerShell Send-MailMessage cmdlet has been deprecated and explore how to send email from PowerShell using modern alternatives like Microsoft Graph API, MailKit and PnPOnline.

Why PowerShell Send-MailMessage Is Obsolete

The Send-MailMessage cmdlet in PowerShell was historically used to send emails. It provided a straightforward way for administrators to integrate email notifications into scripts. However, due to its inability to guarantee secure connections to SMTP servers and its lack of support for modern email authentication protocols like DKIM and SPF, it was officially marked as obsolete in PowerShell 7.0 and has since been deprecated by Microsoft. Instead, Microsoft suggests using the Send-MgUserMail cmdlet or secure tools such as Mailkit.

Here is a basic example of how administrators used to use PowerShell to send email to someone’s email address. Note that $PSEmailServer is a preference variable that sets the default SMTP server for the current PowerShell session.

$PSEmailServer = 'smtp.server.local'
Send-MailMessage -From 'sender@netwrix.com' -To 'recipient@netwrix.com' -Subject 'Test' -Body 'This is a test email'

Modern Methods for Sending Mail Messages in PowerShell

With the deprecation of the Send-MailMessage cmdlet, modern, secure options for sending emails in PowerShell have emerged to replace it, including Microsoft Graph API, MailKit and PnPOnline.

Using Microsoft Graph API for Email Management

One popular example is Microsoft Graph API, which uses the Send-MgUserMail cmdlet from the Microsoft Graph PowerShell SDK. Microsoft Graph API offers extensive functionality for email management, including sending messages via Office 365 accounts. Some of its features include:

  • Enhanced security with modern authentication protocols
  • Integration with Microsoft 365 services
  • Support for advanced email features like rich text formatting, attachments and dynamic recipient lists
  • Improved error handling and logging capabilities

Here is an example:

# Connect to Microsoft Graph

Connect-MgGraph -Scopes "Mail.Send"

# Prepare email parameters

$params = @{

    Message = @{

        Subject = "Test Email"

        Body = @{

            ContentType = "Text"

            Content = "This is a test email sent using Microsoft Graph API."

        }

        ToRecipients = @(

            @{

                EmailAddress = @{

                    Address = "recipient@example.com"

                }

            }

        )

    }

    SaveToSentItems = $true

}

# Send the email

Send-MgUserMail -UserId "sender@example.com" -BodyParameter $params

Using MailKit for Email Automation

Another secure alternative is MailKit, a cross-platform email library for .NET. Here are some of the benefits it offers:

  • Support for modern encryption protocols and authentication methods
  • Cross-platform compatibility across different operating systems
  • Comprehensive support for MIME, IMAP, POP3 and SMTP protocols
  • Regular updates to address security concerns and add new features
  • Fine-grained control over email composition and sending

Below is an example:

# Install MailKit if not already installed

Install-Module -Name MailKit -Force

# Import the module

Import-Module MailKit

# Email configuration

$smtpServer = "smtp.example.com"

$smtpPort = 587

$senderEmail = "sender@example.com"

$senderName = "Sender Name"

$recipientEmail = "recipient@example.com"

$subject = "Test Email from MailKit"

$body = "This is a test email sent using MailKit in PowerShell."

# Create a new MimeMessage

$message = New-Object MimeKit.MimeMessage

$message.From.Add((New-Object MimeKit.MailboxAddress($senderName, $senderEmail)))

$message.To.Add((New-Object MimeKit.MailboxAddress($recipientEmail)))

$message.Subject = $subject

$message.Body = New-Object MimeKit.TextPart("plain") { Text = $body }

# Create SmtpClient object

$smtp = New-Object MailKit.Net.Smtp.SmtpClient

try {

    # Connect to SMTP server

    $smtp.Connect($smtpServer, $smtpPort, [MailKit.Security.SecureSocketOptions]::StartTls)

    # Authenticate (if required)

    $smtp.Authenticate($senderEmail, "YourPassword")

    # Send the email

    $smtp.Send($message)

    Write-Host "Email sent successfully!"

}

catch {

    Write-Host "An error occurred: $($_.Exception.Message)"

}

finally {

    # Disconnect from SMTP server

    $smtp.Disconnect($true)

    $smtp.Dispose()

}

Using PnPOnline to Send Emails

PnPOnline is part of the PnP PowerShell library, making it a convenient tool for system administrators. It can be used to send emails within SharePoint and Microsoft 365 environments; emails are sent from the SharePoint Online “no-reply” address. However, it is limited to internal recipients within the same tenant.

This method offers the following benefits for single-tenant environments:

  • Works natively within Microsoft 365 environments
  • Minimal setup compared to external libraries because it leverages the administrator’s existing connection to Microsoft 365
  • Can send emails to multiple recipients within the same tenant
  • Utilizes SharePoint’s built-in email functionality

An example is shown below:

# Connect to SharePoint site

Connect-PnPOnline -Url "https://yourtenant.sharepoint.com/sites/yoursite" -Interactive

# Define email properties

$recipients = @("recipient1@yourtenant.com", "recipient2@yourtenant.com")

$subject = "New SharePoint Site Created"

$body = @"

Hello Tenant Owner

"@

# Send the email

Send-PnPMail -To $recipients -Subject $subject -Body $body

# Disconnect from SharePoint

Disconnect-PnPOnline

Detailed Examples of Sending Emails in PowerShell

Note that while you cannot use the Send-MailMessage cmdlet in combination with Exchange Online and other email providers, you can still use it to send SMTP emails to any servers that don’t require a secure connection. We’ll use it in the examples below.

Basic SMTP Email Example

To send an email using SMTP with credentials, use  -Credential, as shown in this simple script:

# Define sender and recipient details

$From = "sender@netwrix.com"

$To = "recipient@netwrix.com"

$Subject = "Test Email"

$Body = "This is a test email sent using PowerShell."

# Define SMTP server details

$SMTPServer = "smtp.netwrix.com"

$Port = 587

# Specify credentials

$Password = ConvertTo-SecureString "YourPassword" -AsPlainText -Force

$Credential = New-Object System.Management.Automation.PSCredential ($From, $Password)

# Send the email

Send-MailMessage -From $From -To $To -Subject $Subject -Body $Body -SmtpServer $SMTPServer -Port $Port -UseSsl -Credential $Credential

Sending Emails with Attachments

Now let’s expand that example and send an email with an attachment by using -Attachments:

# SMTP Server and Port

$smtpServer = "smtp.example.com"

$smtpPort = 587

# Email details

$from = "sender@netwrix.com"

$to = "recipient_email@netwrix.com"

$subject = "Subject: Email with Attachment"

$body = "This email contains an attachment."

# Path to the attachment

$attachment = "C:\path\to\your\file.txt"

# Authentication credentials

$username = "your_email@example.com"

$password = "your_password"

$securePassword = ConvertTo-SecureString $password -AsPlainText -Force

$credential = New-Object System.Management.Automation.PSCredential($username, $securePassword)

# Send the email

Send-MailMessage -From $from -To $to -Subject $subject -Body $body `

    -SmtpServer $smtpServer -Port $smtpPort -Credential $credential `

    -UseSsl -Attachments $attachment

HTML-Formatted Emails in PowerShell

There are many instances when sending emails in plain text won’t suffice. HTML formatting allows for richer content presentation, as you can include different styles, images and links within the email body to enhance the email’s visual appeal and functionality. This can be useful for automated notifications, newsletters or alerts where formatting can significantly improve user engagement.

To send HTML-formatted emails, set -BodyAsHtml to $false as shown below:

# Install PnP PowerShell module if not already installed

# Install-Module -Name PnP.PowerShell

# Connect to the Microsoft 365 environment

Connect-PnPOnline -Url https://yourtenant-admin.sharepoint.com -UseWebLogin

# Define email parameters

$To = "recipient@netwrix.com"

$Subject = "PnPOnline Email Example"

$Body = "This is a test email sent using PnPOnline in Microsoft 365."

# Send the email

Send-PnPMail -To $To -Subject $Subject -Body $Body -BodyAsHtml $false

# Disconnect from the session

Disconnect-PnPOnline

Comprehensive Comparison of PowerShell Email Options

FeatureSend-MailMessageMicrosoft Graph APIMailKit
SecurityLimited security with no built-in modern authentication supportSupports modern authentication (OAuth2), secure token handling and multifactor authentication (MFA).Supports TLS, SSL and OAuth2 (modern authentication)
Ease of UseHas straightforward parameters for sending emails, making it suitable for users with basic PowerShell knowledgeSlightly more complex because it requires setup of OAuth2 or Azure authenticationUser-friendly but may have a learning curve for complex tasks like handling attachments
PerformanceSuitable for simple tasks, but less so for large-scale email operations or complex automationHigh performance for large-scale applications; optimized for Microsoft 365 environmentsHigh performance with support for complex email structures and large volumes
Recommended Use Cases  Best for small scripts, basic email notifications and administrative tasks in PowerShell environmentsBest for integrating deeply with Microsoft 365 applications, large-scale automation and SaaS applicationsBest for .NET applications, complex email workflows and email processing

Troubleshooting Common Errors

When you send emails via PowerShell, you are bound to run into issues. Here are some common errors you may encounter and how you can resolve them.

SMTP Server Errors

  • Error: “Unable to connect to the remote server”
    Solution: Verify the SMTP server address and port, and ensure connectivity.
  • Error: “The SMTP server requires a secure connection or the client was not authenticated”
    Solution: Enable SSL/TLS encryption and provide correct credentials.

Credential Issues

  • Error: “The SMTP server rejected the sender address”
    Solution: Verify that the sender’s email address is correct and authorized to send emails.
  • Error: “Authentication failed”
    Solution: Check the username and password and ensure the account has the necessary permissions.

Connection Timeouts

  • Error: “Operation timed out”
    Solution: Check network connectivity. Increase the timeout value in your script.

Best Practices

To help prevent issues, be sure to implement these security best practices:

  • Keep PowerShell and related modules updated to benefit from the latest security patches.
  • Always use the -UseSsl parameter with Send-MailMessage or its equivalent in other methods.
  • Store credentials securely using Windows Credential Manager or modern encryption.

Testing and Debugging Email Scripts

There are some great resources available to help you debug email scripts. One example is Mailtrap, which provides a safe, isolated environment to debug scripts, analyze email content and optimize for deliverability. For instance, Mailtrap enables you to:

  • Test emails without sending them to actual recipients.
  • Review how emails will appear across different devices and email clients.
  • Evaluate emails for spam triggers and improve deliverability.
  • Identify and resolve errors or misconfigurations in email-sending scripts.

Essentially, Mailtrap is a virtual email inbox designed specifically for testing. Simply make a Mailtrap account and configure the SMTP settings. Then you can use a script like the one below:

# Mailtrap SMTP settings

$SMTPServer = "smtp.mailtrap.io"

$Port = 587

$Username = "your_mailtrap_username"

$Password = "your_mailtrap_password"

# Email details

$From = "sender@example.com"

$To = "recipient@example.com"

$Subject = "Test Email"

$Body = "This is a test email sent to Mailtrap."

# Securely create credentials

$Credential = New-Object System.Management.Automation.PSCredential($Username, (ConvertTo-SecureString $Password -AsPlainText -Force))

# Send email

try {

    Send-MailMessage -From $From -To $To -Subject $Subject `

    -Body $Body -SmtpServer $SMTPServer -Port $Port `

    -UseSsl -Credential $Credential

    Write-Host "Email sent successfully to Mailtrap."

} catch {

    Write-Error "Failed to send email. Error: $_"

}

Conclusion

As you can see it is quite easy to make a PowerShell script to send email. However, you must ensure that you do so securely, since SMTP communication is a prime target for hackers and cybercriminals. Remember that the Send-MailMessage cmdlet has been deprecated by Microsoft, so make sure to use a modern tool like Microsoft Graph API, MailKit or PnPOnline to send email from PowerShell. These modern tools offer enhanced security features, better performance and improved compatibility with current email standards. By adopting these alternatives, you can ensure that your PowerShell email scripts are not only functional but also align with best practices in cybersecurity, adding value to your organization.

Since 2012, Jonathan Blackwell, an engineer and innovator, has provided engineering leadership that has put Netwrix GroupID at the forefront of group and user management for Active Directory and Azure AD environments. His experience in development, marketing, and sales allows Jonathan to fully understand the Identity market and how buyers think.