Why New TLS Requirement Stops PowerShell Scripts Sending Email

Time to Review Use of Send-MailMessage Cmdlet with Exchange Online

Microsoft is in the process of removing TLS 1.0 and 1.1 support from Exchange Online to enforce the requirement to use TLS 1.2. It will take time before every mailbox server declines old TLS connections, but it’s going to happen. And when Exchange Online enforces TLS 1.2, it can stop PowerShell scripts sending email using the Send-MailMessage cmdlet via the SMTP AUTH protocol. Our script to send a welcome message to new users is a good example of the type which will be affected.

The problem occurs because the workstation where the script runs attempts to negotiate a TLS 1.0 or 1.1 connection for the SMTP AUTH protocol. Exchange Online uses opportunistic TLS to negotiate connections with mail clients and other servers. An inbound connection for SMTP AUTH can be serviced by any Exchange Online server, but after Microsoft upgrades a server, it will reject TLS 1.0 and 1.1 connection requests and only accept email if the sending server allows messages to be passed in an unencrypted form. PowerShell responds with the error “The SMTP server requires a secure connection or the client was not authenticated.” In this case, setting up the secure connection is the problem.

To be fair to Microsoft, they flagged this issue at Ignite 2020, noting in a supporting blog post that: “Both TLS 1.0/1.1 and Basic Auth are often used for SMTP AUTH. The deprecation of TLS 1.0/1.1 will break message submission for SMTP AUTH clients that continue to use it.”

Force PowerShell to Use TLS 1.2

The solution is to force PowerShell to use TLS 1.2 when it negotiates an SMTP AUTH connection to Exchange Online. This is done by running a command to select TLS 1.2 using the .NET ServicePointManager class. For example:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

You can include the command in your PowerShell profile, and the setting will apply to all connections created during the session. It’s probably better to include the command in any script which uses the Send-MailMessage cmdlet.

The issue has been known for a while and other email platforms also insist on TLS 1.2 connection and use the same solution for PowerShell (here’s an example). Given the popularity of Office 365, Exchange Online’s new insistence on TLS 1.2 might create more of a fuss due to the number of scripts likely to be affected.

Send-MailMessage and Gmail

The advent of the problem caused me to look at using Send-MailMessage with Gmail. I discovered that you don’t have to specify TLS 1.2 (this may change in future). After turning off two-factor authentication for my account and allowing access to insecure apps for the account, this rudimentary code was enough to send a message via Gmail.

$EmailParams = @{
    SmtpServer = 'smtp.gmail.com'
    Port = 587
    UseSsl = $true
    Credential  = 'MyGoogleAccount'
    From = 'MyGoogleAccount@gmail.com'
    To = 'Ken.Bowers@office365itpros.com'
    Subject = 'Sending emails from Gmail with PowerShell'
    Body = "Email is just Wonderful!"
}
Send-MailMessage @EmailParams

This is the kind of change that results in a two-line update in the Office 365 for IT Pros eBook. Because we update every month, our text covers topics and issues that no other book attempts to do. If you’re responsible for an Office 365 tenant, you should subscribe today.

2 Replies to “Why New TLS Requirement Stops PowerShell Scripts Sending Email”

    1. It’s not odd. It happens when Microsoft wants to signal that they plan to remove a cmdlet so that people can phase out using the older cmdlet and replace it with a new one. It happened with the Search-Mailbox cmdlet. The difference there is that a replacement existed. No replacement has so far emerged for Send-MailMessage.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.