---
title: "Send Secure PowerShell Emails: 5 Alternative Methods"
description: "Create Send-MailKitMessage to replace SmtpClient for more secure PowerShell email sending with this step-by-step guide."
canonical: "https://adamtheautomator.com/powershell-email/"
---

# Send Secure PowerShell Emails: 5 Alternative Methods

> Create Send-MailKitMessage to replace SmtpClient for more secure PowerShell email sending with this step-by-step guide.

Source: https://adamtheautomator.com/powershell-email/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![Send Secure PowerShell Emails: 5 Alternative Methods](https://adamtheautomator.com/wp-content/uploads/2020/08/Untitled-design-4-1.png)

# Send Secure PowerShell Emails: 5 Alternative Methods

[![](https://secure.gravatar.com/avatar/f08b754bc0dce1c76685f6afa93185ecfb6f861fd14f993286e06bba69eaeb8b?s=192&d=mm&r=g)Adam Listek](https://adamtheautomator.com/author/alistek/)20 August 20206 min. read

Categories: [IT Ops](/category/it-ops/)

Tags:[PowerShell](/tag/powershell/)

Table of Contents

*   [.NET MailKit](#h-net-mailkit)
*   [Installing MailKit & MimeKit](#h-installing-mailkit-mimekit)
*   [Sending an PowerShell Email via MailKit](#h-sending-an-powershell-email-via-mailkit)
*   [Emulating Send-MailMessage with MailKit](#h-emulating-send-mailmessage-with-mailkit)
*   [Direct Send](#h-direct-send)
*   [Amazon SES](#h-amazon-ses)
*   [Microsoft Graph Email](#h-microsoft-graph-email)
*   [MailGun](#h-mailgun)
*   [Conclusion](#h-conclusion)

Need to notify your team on a failed service, only to find that your PowerShell email has bounced? Unauthenticated email has become difficult to pass in many mail systems. You don’t want to miss an important email notification because you relied on outdated PowerShell cmdlets. The built-in cmdlet [`Send-MailMessage`](https://adamtheautomator.com/send-mailmessage/ "Send-MailMessage") no longer covers sending email securely.

Not a reader? Watch this related video tutorial!

**_Not seeing the video? Make sure your ad blocker is disabled._**

So as useful as this cmdlet is, why is it no longer considered secure? Underneath, this PowerShell cmdlet uses the `SmtpClient` .NET class. Unfortunately, this class [does not support many of the modern encryption protocols](https://github.com/dotnet/platform-compat/blob/master/docs/DE0005.md) and therefore, cannot guarantee a secure connection. The crux of the matter is that `SmtpClient` is not going to be further developed to add features, such as for Opportunistic TLS, the official recommendation has been to no longer use this product.

What may be slightly confusing is that the classes and methods are still present even in the latest .NET Core releases. Though you may still use these methods,, the official recommendation is to move to alternative email sending methods. There are generally two methods now of sending Powershell email.

*   .NET Library
*   REST API

With those two methods in mind, let’s jump into some alternatives!

## .NET MailKit

The most generic method that would replace SmtpClient and Send-MailMessage would be the recommended replacement, which is [MailKit](http://www.mimekit.net/). This is a third-party, open-source library but maintained by a Microsoft employee and officially recommended for use in the documentation. This is similar to how Newtonsoft.JSON became a core part of the .NET platform despite being an open-source product.

### Installing MailKit & MimeKit

Since MailKit and it’s core dependency of MimeKit are not native libraries available to .NET, we will need to install them first.

Make sure to run `Install-Package` as an administrator or else the packages may not install properly.

Using the `Install-Package` cmdlet, install `MailKit` from the `[nuget.org](<http://nuget.org>)` repository. If the installation works properly, you will see a number of dependencies installed alongside MailKit, including MimeKit.

```powershell
Install-Package -Name 'MailKit' -Source 'nuget.org'
```

![Installing MailKit & MimeKit](https://adamtheautomator.com/wp-content/uploads/2020/08/Untitled-55-2.png)

Installing MailKit & MimeKit

### Sending an PowerShell Email via MailKit

The example below shows how we can send an email using the Gmail SMTP server but using MailKit. In this example, PowerShell 7.0.1 is the underlying version and we are using the latest .NET Standard 2.0 version of the DLL. Other DLL versions are available in the parent directory, if needed.

As you can see, we need to load both the MailKit DLL and the MimeKit DLL. If you only load MailKit, an error may not occur, but this will not work. The next steps are pretty similar to how the original `SmtpClient` works in setting up the various configurations.

```powershell
Add-Type -Path "C:\Program Files\PackageManagement\NuGet\Packages\MailKit.2.8.0\lib\netstandard2.0\MailKit.dll"
 Add-Type -Path "C:\Program Files\PackageManagement\NuGet\Packages\MimeKit.2.9.1\lib\netstandard2.0\MimeKit.dll"
 $SMTP     = New-Object MailKit.Net.Smtp.SmtpClient
 $Message  = New-Object MimeKit.MimeMessage
 $TextPart = [MimeKit.TextPart]::new("plain")
 $TextPart.Text = "This is a test."
 $Message.From.Add("myemail1@gmail.com")
 $Message.To.Add("myemail2@somewhereelse.com")
 $Message.Subject = 'Test Message'
 $Message.Body    = $TextPart
 $SMTP.Connect('smtp.gmail.com', 587, $False)
 $SMTP.Authenticate('myemail1@gmail.com', 'appspecificpassword' )
 $SMTP.Send($Message)
 $SMTP.Disconnect($true)
 $SMTP.Dispose()
```

> The reason that the password for the authentication step says `appspecificpassword` is that if you are properly using two-factor authentication, you will need to generate an app-specific password for your applications.

### Emulating Send-MailMessage with MailKit

Although this does not have a direct correlation with `Send-MailMessage`, what if we wanted to create a quick and easy function that wrapped the MailKit functionality into an alternative to the built-in cmdlet? In this example, we can create a `Send-MailkitMessage` function to do a similar series of steps. Keep in mind that this does not replicate all of the functions and is vastly simplified.

```powershell
Function Send-MailkitMessage {
  [CmdletBinding(
      SupportsShouldProcess = $true,
      ConfirmImpact = "Low"
  )] # Terminate CmdletBinding

  Param(
    [Parameter( Position = 0, Mandatory = $True )][String]$To,
    [Parameter( Position = 1, Mandatory = $True )][String]$Subject,
    [Parameter( Position = 2, Mandatory = $True )][String]$Body,
    [Parameter( Position = 3 )][Alias("ComputerName")][String]$SmtpServer = $PSEmailServer,
    [Parameter( Mandatory = $True )][String]$From,
    [String]$CC,
    [String]$BCC,
    [Switch]$BodyAsHtml,
    $Credential,
    [Int32]$Port = 25
  )

  Process {
    $SMTP     = New-Object MailKit.Net.Smtp.SmtpClient
    $Message  = New-Object MimeKit.MimeMessage

    If ($BodyAsHtml) {
      $TextPart = [MimeKit.TextPart]::new("html")
    } Else {
      $TextPart = [MimeKit.TextPart]::new("plain")
    }
    
    $TextPart.Text = $Body

    $Message.From.Add($From)
    $Message.To.Add($To)
    
    If ($CC) {
      $Message.CC.Add($CC)
    }
    
    If ($BCC) {
      $Message.BCC.Add($BCC)
    }

    $Message.Subject = $Subject
    $Message.Body    = $TextPart

    $SMTP.Connect($SmtpServer, $Port, $False)

    If ($Credential) {
      $SMTP.Authenticate($Credential.UserName, $Credential.GetNetworkCredential().Password)
    }

    If ($PSCmdlet.ShouldProcess('Send the mail message via MailKit.')) {
      $SMTP.Send($Message)
    }

    $SMTP.Disconnect($true)
    $SMTP.Dispose()
  }
}
```

Sending the actual message is as simple as calling the function that we just created and passing in the correct parameters.

```powershell
$Params = @{
  "To"         = 'myemail2@somewhereelse.com'
  "From"       = 'myemail1@gmail.com'
  "Subject"    = 'Test Email'
  "Body"       = 'This is a test.'
  "SmtpServer" = 'smtp.gmail.com'
  "Credential" = $Creds
  "Port"       = 587
}

Send-MailkitMessage @Params
```

## Direct Send

To follow-up the use of MailKit, and how it can be used in a more practical sense in a modern environment that uses Office 365, we can take advantage of the [Direct Send](https://docs.microsoft.com/en-us/exchange/mail-flow-best-practices/how-to-set-up-a-multifunction-device-or-application-to-send-email-using-microsoft-365-or-office-365) functionality available to users of Office 365. The original method using, `Send-MailMessage` can be [read in this article as well.](https://adamtheautomator.com/powershell-email/) There are a couple of caveats to this specific method of sending though.

*   No external recipients are allowed
*   Uses Port `25` instead of `587`
*   Sender does not need a valid mailbox, but should if NDRs or replies are needed

Similar to how we used MailKit to send to Gmail, we are going to make one change to the existing code. With the `Connect` method, we are adding the `[MailKit.Security.SecureSocketOptions]::StartTls` option to make sure that TLS is used.

```powershell
Add-Type -Path "C:\Program Files\PackageManagement\NuGet\Packages\MailKit.2.8.0\lib\netstandard2.0\MailKit.dll"
Add-Type -Path "C:\Program Files\PackageManagement\NuGet\Packages\MimeKit.2.9.1\lib\netstandard2.0\MimeKit.dll"

$SMTP     = New-Object MailKit.Net.Smtp.SmtpClient
$Message  = New-Object MimeKit.MimeMessage
$TextPart = [MimeKit.TextPart]::new("plain")
$TextPart.Text = "This is a test."

$Message.From.Add("user@mydomain.com")
$Message.To.Add("recipient@mydomain.com")
$Message.Subject = 'Test Message'
$Message.Body    = $TextPart

$SMTP.Connect('{tenant}.mail.protection.outlook.com', 25, [MailKit.Security.SecureSocketOptions]::StartTls, $False)
$SMTP.Authenticate('user@mydomain.com', 'mypassword' )

$SMTP.Send($Message)
$SMTP.Disconnect($true)
$SMTP.Dispose()
```

## Amazon SES

Another example of using MailKit to send emails is using [Amazon SES](https://aws.amazon.com/ses/) (Simple Email Service). To learn more about the overall setup and configuration, [read this article](https://adamtheautomator.com/aws-email-service/), but after that has been done you can see how simple it is to send an email via MailKit. By utilizing the correct endpoint and TLS, we can simply send emails via MailKit.

```powershell
Add-Type -Path "C:\Program Files\PackageManagement\NuGet\Packages\MailKit.2.8.0\lib\netstandard2.0\MailKit.dll"
Add-Type -Path "C:\Program Files\PackageManagement\NuGet\Packages\MimeKit.2.9.1\lib\netstandard2.0\MimeKit.dll"

$SMTP     = New-Object MailKit.Net.Smtp.SmtpClient
$Message  = New-Object MimeKit.MimeMessage
$TextPart = [MimeKit.TextPart]::new("plain")
$TextPart.Text = "This is a test."

$Message.From.Add("user@mydomain.com")
$Message.To.Add("recipient@mydomain.com")
$Message.Subject = 'Test Message'
$Message.Body    = $TextPart

$SMTP.Connect('email-smtp.ap-southeast-2.amazonaws.com', 587, [MailKit.Security.SecureSocketOptions]::StartTls, $False)
$SMTP.Authenticate('smtpuser@mydomain.com', 'mypassword' )

$SMTP.Send($Message)
$SMTP.Disconnect($true)
$SMTP.Dispose()
```

The .NET MailKit library is incredibly useful, but many modern services now allow you to send mail through a REST API as seen in the following examples.

## Microsoft Graph Email

The [Microsoft Graph REST API](https://docs.microsoft.com/en-us/graph/api/overview?view=graph-rest-1.0) is quickly becoming indispensable for Azure AD and Office 365 administrators. With that in mind, utilizing the `sendMail` [REST API](https://docs.microsoft.com/en-us/graph/api/user-sendmail?view=graph-rest-1.0&tabs=http) method, we can quickly send a message using the `Invoke-RestMethod` API.

> You will need the `Mail.Send` permission to send the email.

There are a few prerequisites to authenticating to the Microsoft Graph API, which you can [read about here](https://docs.microsoft.com/en-us/graph/auth/auth-concepts?view=graph-rest-1.0). Once you have your authentication token and the correct permissions assigned, see below as to how you can send in Powershell email.

```powershell
$Token = "tokencontent"

$Params = @{
  "URI"         = 'https://graph.microsoft.com/v1.0/me/sendMail'
  "Headers"     = @{
    "Authorization" = ("Bearer {0}" -F $Token)
  }
  "Method"      = "POST"
  "ContentType" = 'application/json'
  "Body" = (@{
    "message" = @{
      "subject" = 'This is a test message.'
      "body"    = @{
        "contentType" = 'Text'
        "content"     = 'This is a test email'
      }
      "toRecipients" = @(
        @{
          "emailAddress" = @{
            "address" = 'toemail@somedomain.com'
          }
        }
      )
    }
  }) | ConvertTo-JSON -Depth 10
}

Invoke-RestMethod @Params
```

## MailGun

Finally, let’s explore using another popular email service, [MailGun](https://www.mailgun.com/). Using a simple API call, we can send an email through here as well. After retrieving the Private API Key from the MailGun Account Settings → API Keys section, you can use that to send to the domain you have configured.

```powershell
$APIKey = 'key-asasdfd7as8fa8dfasdfasdff87sd8f8sa8sd'
 
$Params = @{
  "URI"            = 'https://api.mailgun.net/v3/mail.mydomain.com/messages'
  "Form"           = @{
    "from"    = 'user1@myexampledomain.com'
    "to"      = 'user2@myexampledomain.com'
    "subject" = 'Test API Sent Email'
    "text"    = 'Test Body Text'
  }
  "Authentication" = 'Basic'
  "Credential"     = (New-Object System.Management.Automation.PSCredential ("api", ($APIKey | ConvertTo-SecureString -AsPlainText)))
  "Method"         = 'POST'
}
 
Invoke-RestMethod @Params
```

## Conclusion

Creating `Send-MailKitMessage` to remove the underlying .NET technology `SmtpClient` from being used, allows for more secure PowerShell email sending. There are many easy to use and more powerful alternatives that can be made to work just as easily as the built-in functions. Depending on your needs and what your script or application may need to do, simply substitute for one of the many methods demonstrated above!

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fpowershell-email%2F&text=Send%20Secure%20PowerShell%20Emails%3A%205%20Alternative%20Methods)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fpowershell-email%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fpowershell-email%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/2026/06/26995-troubleshoot-dns-issues-powershell-codex.webp)

### [Troubleshoot DNS Issues with PowerShell](/troubleshoot-dns-issues-powershell/)

Troubleshoot DNS issues with PowerShell by testing name resolution, DNS client settings, cache entries, and network connectivity in a repeatable workflow.

![](https://adamtheautomator.com/wp-content/uploads/2025/10/image_2025-10-24_095322075.png)

### [Migrating from PowerShell 6 to 7.5: Breaking Changes/New Features](/migrating-powershell-6-to-7-5/)

Migrate from PowerShell Core 6 to 7.5: breaking changes, features, and testing tips.

![](https://adamtheautomator.com/wp-content/uploads/2025/06/featured-image-6.png)

### [How to Add Timeouts to Pester Tests with PowerShell Runspaces](/pester-test-timeout-runspaces/)

Prevent Pester tests from hanging indefinitely using PowerShell runspaces. Learn to handle variable scoping, module loading, TestDrive access, and stream capture challenges with timeout protection.

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
