Guide

PowerShell Email: Every Method Compared

Send-MailMessage is deprecated. This hub guide compares every current method for sending email from PowerShell: Send-MgUserMail, Microsoft Graph REST, MailKit, and Nylas CLI. Includes a decision matrix so you pick the right tool for scripts, reports, and CI/CD pipelines.

Written by Qasim Muhammad Staff SRE

VerifiedCLI 3.1.1 · Outlook, Gmail · last tested May 21, 2026

Command references used in this guide: nylas email send for sending email, nylas auth login for OAuth authentication, nylas email list for reading email, and nylas email search for finding messages.

How do I send email from PowerShell in 2026?

PowerShell has 5 working methods for sending email, but only 4 are actively maintained. Microsoft deprecated Send-MailMessage in PowerShell 7.0 (March 2020) because its underlying System.Net.Mail.SmtpClient can't negotiate TLS 1.2+ securely. The choice between replacements comes down to provider lock-in, auth model, and how many lines of code you're willing to maintain.

The table below summarizes every option. Each row links to a deeper section or a dedicated guide with full code examples.

MethodStatusAuthProvidersSetup time
Send-MailMessageDeprecatedBasic Auth / SMTPAny SMTP server2 min
Send-MgUserMailActiveOAuth2 (Azure AD)Microsoft 365 only15-20 min
Invoke-RestMethod + GraphActiveOAuth2 (Azure AD)Microsoft 365 only20-30 min
MailKit (.NET)ActiveSMTP + OAuth2 or App PasswordAny SMTP server10-15 min
nylas email sendActiveOAuth2 (managed)Gmail, Outlook, Yahoo, iCloud, IMAP2 min

Why is Send-MailMessage deprecated?

Send-MailMessage is deprecated because it wraps .NET's System.Net.Mail.SmtpClient, which hardcodes TLS 1.0 and can't upgrade to TLS 1.2 or 1.3 at runtime. Microsoft's platform compatibility note DE0005 explains the root cause: the class "doesn't support many modern protocols" and the team won't fix it. PowerShell 7.0 added the obsolete warning in March 2020, and every release since prints "WARNING: The command 'Send-MailMessage' is obsolete." when you call it.

The other half of the problem is Basic Auth. Microsoft retired Basic Auth for Exchange Online in October 2022, Google disabled "Less Secure Apps" for Gmail in September 2024, and Yahoo dropped plain-password SMTP the same year. Scripts that pass -Credential to Send-MailMessage now fail against all three major providers. For a step-by-step migration, see the Send-MailMessage migration guide.

How do I use Send-MgUserMail in PowerShell?

Send-MgUserMail is Microsoft's official replacement for sending email from PowerShell in Microsoft 365 environments. It's part of the Microsoft Graph PowerShell SDK, which has over 9,000 cmdlets. The Mail.Send permission scope is required, and you need an Azure AD app registration before writing a single line of send logic. The full flow takes 15-20 minutes for a first-time setup.

Install the module, connect with the right scopes, build a message body hashtable, and call the cmdlet. Here's the minimum working example from the official Send-MgUserMail docs:

send-graph-email.ps1
# Install the Graph module (one-time, ~120 MB download)
Install-Module Microsoft.Graph.Users.Actions -Scope CurrentUser

# Authenticate with Mail.Send permission
Connect-MgGraph -Scopes "Mail.Send"

# Build the message
$message = @{
  Subject = "Monthly server report"
  Body    = @{
    ContentType = "HTML"
    Content     = "<p>CPU averaged 42% this month.</p>"
  }
  ToRecipients = @(
    @{ EmailAddress = @{ Address = "ops@example.com" } }
  )
}

# Send it
Send-MgUserMail -UserId "me" -Message $message

The catch: Send-MgUserMail works only with Microsoft 365 and Exchange Online accounts. If your scripts send through Gmail, Yahoo, or any IMAP server, Graph isn't an option. For the full Azure AD setup walkthrough, see the Office 365 PowerShell email guide.

How do I send email with Graph REST API from PowerShell?

The Graph REST approach uses Invoke-RestMethod to POST directly to the https://graph.microsoft.com/v1.0/me/sendMail endpoint. It avoids installing the 120 MB Microsoft.Graph module, which matters in CI/CD runners where disk and install time are constrained. The trade-off: you manage OAuth2 token acquisition yourself, which adds 10-15 lines of boilerplate per script.

The pattern below fetches an access token using client credentials, then sends a message. You still need an Azure AD app registration with the Mail.Send application permission.

send-graph-rest.ps1
# Fetch an OAuth2 token (client credentials flow)
$tokenBody = @{
  client_id     = $env:AZURE_CLIENT_ID
  client_secret = $env:AZURE_CLIENT_SECRET
  scope         = "https://graph.microsoft.com/.default"
  grant_type    = "client_credentials"
}
$tokenUrl = "https://login.microsoftonline.com/$env:AZURE_TENANT_ID/oauth2/v2.0/token"
$token = (Invoke-RestMethod -Uri $tokenUrl -Method POST -Body $tokenBody).access_token

# Build and send the message
$mail = @{
  message = @{
    subject = "Deploy complete"
    body    = @{ contentType = "Text"; content = "Build 847 deployed to prod." }
    toRecipients = @(
      @{ emailAddress = @{ address = "team@example.com" } }
    )
  }
} | ConvertTo-Json -Depth 5

$headers = @{ Authorization = "Bearer $token"; "Content-Type" = "application/json" }
Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/users/$env:SENDER_UPN/sendMail" `
  -Method POST -Headers $headers -Body $mail

That's 20 lines before you add error handling or attachments. Like Send-MgUserMail, this only works with Microsoft 365 mailboxes. For a complete walkthrough including delegated permissions and certificate auth, see the Office 365 PowerShell email guide.

How do I send email from PowerShell without Microsoft 365?

Nylas CLI sends email across Gmail, Outlook, Yahoo, iCloud, and IMAP from a single command. Authentication uses OAuth2 tokens stored in your system keyring, which refresh automatically every 3,600 seconds. One binary replaces the Graph module, Azure AD registration, and SMTP credential management. Setup takes under 2 minutes on Windows, macOS, or Linux.

Install the CLI with the PowerShell install script, authenticate once, and send. The three commands below are the complete workflow:

send-with-cli.ps1
# Install (one-time, ~12 MB binary)
irm https://cli.nylas.com/install.ps1 | iex

# Authenticate (opens browser, stores OAuth2 token)
nylas auth login

# Send an email
nylas email send --to "ops@example.com" --subject "Deploy complete" --body "Build 847 shipped."

That's 3 lines vs 20 for Graph REST. The CLI handles provider detection, token refresh, and TLS negotiation. For HTML bodies, attachments, and scheduled sends, see the full PowerShell email sending guide. For CI/CD pipelines on GitHub Actions or Azure DevOps, see the PowerShell CI/CD email guide.

Which method should I use?

The right method depends on 3 factors: which email provider your organization uses, whether you control Azure AD, and how many lines of plumbing you're willing to own. The table below maps 6 common scenarios to the best tool for each. Microsoft 365 admins with Azure AD access get the most options. Everyone else narrows to MailKit or the CLI.

ScenarioBest methodWhy
Microsoft 365 org with Azure ADSend-MgUserMailNative Graph integration, admin-approved permissions, audit logs in Entra
Quick script, any providernylas email send3 lines, no Azure AD, works with Gmail/Yahoo/iCloud/IMAP too
Multi-provider fleetnylas email sendOne auth model for 6 providers instead of per-provider plumbing
CI/CD pipeline notificationsnylas email send12 MB binary, no module install, runs on any runner OS
.NET app or library integrationMailKitNuGet package, full MIME control, maintained by a Microsoft employee
Legacy script maintenanceSend-MailMessageStill works on internal SMTP relays; plan migration before relay EOL

If you're building something new today and don't know which provider your users will have, start with the CLI. You can always swap to Send-MgUserMail later if the org standardizes on Microsoft 365.

Next steps