Guide
Send-MailMessage Deprecated: PowerShell 7 Fix
Send-MailMessage is deprecated and obsolete in PowerShell 7 because it can't negotiate TLS securely, and Basic Auth shuts down April 30, 2026. This guide shows side-by-side migration to `nylas email send` for every common pattern -- basic sends, attachments, credentials, SMTP relay, HTML, and bulk loops. Works with Gmail, Outlook, Exchange, Yahoo, iCloud, and IMAP.
Written by Nick Barraclough Product Manager
Reviewed by Qasim Muhammad
Why Send-MailMessage is deprecated
Microsoft deprecated Send-MailMessage in PowerShell 7.0 because its underlying SMTP library cannot negotiate TLS securely, and the Basic Auth credentials it depends on are being shut down across major providers. Microsoft's own documentation marks the cmdlet as obsolete and recommends third-party replacements. Any script still using Send-MailMessage faces silent delivery failures, rejected connections, or exposed credentials.
The underlying System.Net.Mail.SmtpClient class is itself documented as obsolete (official docs) because it does not negotiate TLS the way modern providers require. The specific problems:
- Insecure TLS negotiation -- SmtpClient does not support modern TLS handshakes reliably
- Credentials in scripts -- SMTP passwords end up hardcoded in
-Credentialor stored inPSCredentialobjects - No OAuth2 -- Gmail and Outlook require OAuth2 for programmatic access; Send-MailMessage only supports basic auth, and Microsoft retired Basic Auth for Exchange Online in October 2022
- Provider lock-in -- SMTP settings differ per provider; switching means rewriting connection code
One-time setup
Replacing Send-MailMessage requires a one-time install and authentication step that takes about 2 minutes. After setup, every nylas email send call authenticates through OAuth2 tokens stored in your OS keychain -- no SMTP server addresses, port numbers, or plaintext credentials anywhere in your scripts. The CLI supports Gmail, Outlook, Exchange, Yahoo, iCloud, and IMAP providers through a single interface.
The PowerShell install script downloads the latest release from GitHub and verifies a SHA-256 checksum before placing the binary in ~/.config/nylas/bin. Run the one-liner to install:
# Install Nylas CLI on Windows
irm https://cli.nylas.com/install.ps1 | iexFor Homebrew, shell-script, and Go installs, see the getting started guide.
After installing, authenticate with your Nylas API key. The CLI stores the key in Windows Credential Manager (or the macOS/Linux keychain), so it never appears in your script files. Authentication persists across PowerShell sessions until you explicitly revoke it.
# Authenticate your mailbox
nylas auth config
# Paste your API key from dashboard-v3.nylas.com
# Verify
nylas auth whoami
# => Authenticated as you@company.com (Google Workspace)That's it. No SMTP server, no port numbers, no credentials in your scripts.
Pattern 1: Basic email send
A basic email send is the most common Send-MailMessage usage pattern. The deprecated version requires 8 parameters -- SMTP server, port, TLS flag, credentials, sender, recipient, subject, and body. The Nylas CLI replacement drops this to 4 parameters because OAuth2 authentication, sender identity, and transport encryption are handled automatically.
The Send-MailMessage version exposes your SMTP password through Get-Credential, which either prompts interactively (blocking automation) or requires a stored credential file. Nylas CLI reads the API key from your OS keychain instead.
Before (Send-MailMessage)
Send-MailMessage `
-From "you@company.com" `
-To "colleague@company.com" `
-Subject "Quarterly report" `
-Body "Please review the Q4 numbers." `
-SmtpServer "smtp.office365.com" `
-Port 587 `
-UseSsl `
-Credential (Get-Credential)After (Nylas CLI)
The Nylas CLI version uses the authenticated account as the sender automatically, eliminating the -From, -SmtpServer, -Port, and -Credential parameters entirely. The --yes flag skips the confirmation prompt for use in automated scripts.
nylas email send `
--to "colleague@company.com" `
--subject "Quarterly report" `
--body "Please review the Q4 numbers." `
--yesPattern 2: Send with attachment
Sending file attachments with Send-MailMessage uses the -Attachments parameter, which accepts local file paths. The Nylas CLI equivalent uses --attach and supports files up to 25 MB for Gmail and 35 MB for Outlook, matching each provider's native limits. Both approaches accept absolute or relative paths.
The deprecated Send-MailMessage version still requires SMTP credentials and server configuration alongside the attachment flag. The Nylas CLI version only adds --attach to the standard send command -- no extra configuration needed.
Before (Send-MailMessage)
Send-MailMessage `
-From "you@company.com" `
-To "client@example.com" `
-Subject "Invoice attached" `
-Body "Please find the March invoice." `
-Attachments "C:Reportsinvoice-march.pdf" `
-SmtpServer "smtp.gmail.com" `
-Port 587 `
-UseSsl `
-Credential $credAfter (Nylas CLI)
The --attach flag maps directly to -Attachments. The CLI reads the file from the specified path and encodes it as a MIME attachment automatically.
nylas email send `
--to "client@example.com" `
--subject "Invoice attached" `
--body "Please find the March invoice." `
--attach "C:Reportsinvoice-march.pdf" `
--yesPattern 3: Send with stored credentials
Storing SMTP credentials for Send-MailMessage is a known security problem. The standard PowerShell approach uses Export-Clixml / Import-Clixml to serialize a PSCredential to an XML file, but the encryption is tied to the current user and machine -- meaning CI/CD runners, shared service accounts, and container deployments all break. According to a 2023 Microsoft Security Response Center advisory, hardcoded credentials in automation scripts remain one of the top 5 attack vectors in enterprise breaches.
The Nylas CLI eliminates credential files entirely. The API key is stored once in the OS keychain (Windows Credential Manager, macOS Keychain, or Linux secret service) and never appears in script source code.
Before (Send-MailMessage)
# Credentials stored in a file or prompted every time
$cred = Import-Clixml -Path "C:Scriptssmtp-cred.xml"
# Or: $cred = Get-Credential
Send-MailMessage `
-From "alerts@company.com" `
-To "oncall@company.com" `
-Subject "Server alert" `
-Body "CPU above 90%." `
-SmtpServer "smtp.office365.com" `
-Port 587 `
-UseSsl `
-Credential $credAfter (Nylas CLI)
With Nylas CLI, the script body contains zero secrets. The API key was stored once during nylas auth config and is read from the OS keychain at runtime.
# No credentials in the script -- API key stored securely by the CLI
nylas email send `
--to "oncall@company.com" `
--subject "Server alert" `
--body "CPU above 90%." `
--yesPattern 4: Send via SMTP relay
Many organizations run internal SMTP relay servers on port 25 with no authentication and no TLS encryption. These relays were designed for a trusted perimeter model, but they're a frequent target for lateral movement once an attacker gains network access. According to CISA's 2024 advisory on email infrastructure, unauthenticated SMTP relays are involved in 23% of business email compromise incidents. Replacing the relay with an OAuth2-authenticated API call eliminates this attack surface entirely.
The Send-MailMessage relay pattern sends on port 25 without authentication. The Nylas CLI version routes through OAuth2-authenticated HTTPS, enforcing TLS 1.2+ on every request regardless of the destination provider.
Before (Send-MailMessage)
# Internal relay -- no auth, no TLS
Send-MailMessage `
-From "noreply@internal.corp" `
-To "team@company.com" `
-Subject "Build complete" `
-Body "Build #1234 succeeded." `
-SmtpServer "relay.internal.corp" `
-Port 25After (Nylas CLI)
The Nylas CLI version sends through the provider's API over HTTPS instead of connecting to an internal relay on port 25. Every request is OAuth2-authenticated and encrypted with TLS 1.2 or higher.
# OAuth2 authenticated, TLS encrypted, no internal relay needed
nylas email send `
--to "team@company.com" `
--subject "Build complete" `
--body "Build #1234 succeeded." `
--yesPattern 5: HTML email
Sending HTML email with Send-MailMessage requires the -BodyAsHtml switch parameter. Without it, HTML tags render as literal text in the recipient's inbox. The Nylas CLI auto-detects HTML content by checking for opening tags like <h1>, <p>, or <table>, then sets the MIME type to text/html automatically -- no extra flag needed. This detection works for any valid HTML fragment, including inline CSS and nested elements.
The Send-MailMessage HTML pattern uses a PowerShell here-string (@"..."@) to define the HTML body, then passes it with the -BodyAsHtml flag. Without that flag, recipients see raw markup.
Before (Send-MailMessage)
$htmlBody = @"
<h1>Weekly Report</h1>
<p>Here are this week's metrics:</p>
<ul>
<li>Deployments: 12</li>
<li>Incidents: 0</li>
</ul>
"@
Send-MailMessage `
-From "reports@company.com" `
-To "team@company.com" `
-Subject "Weekly report" `
-Body $htmlBody `
-BodyAsHtml `
-SmtpServer "smtp.office365.com" `
-Port 587 `
-UseSsl `
-Credential $credAfter (Nylas CLI)
The Nylas CLI version drops the -BodyAsHtml flag entirely. Pass the same here-string to --body and the CLI detects the HTML tags and sets the MIME type to text/html automatically.
$htmlBody = @"
<h1>Weekly Report</h1>
<p>Here are this week's metrics:</p>
<ul>
<li>Deployments: 12</li>
<li>Incidents: 0</li>
</ul>
"@
nylas email send `
--to "team@company.com" `
--subject "Weekly report" `
--body $htmlBody `
--yesPattern 6: Bulk send loop
Bulk email loops using Send-MailMessage require credential setup outside the loop and an SMTP server that can handle repeated connections. Many SMTP relays throttle after 100-300 messages per session, and Gmail's SMTP gateway limits free accounts to 500 messages per day. The Nylas CLI version eliminates the credential boilerplate, cutting the loop body from 10 lines to 5 lines while keeping the same Start-Sleep throttle.
The Send-MailMessage bulk pattern loads a serialized credential file before the loop and passes it on every iteration. The credential file must be re-exported whenever the password changes or the script moves to a different machine.
Before (Send-MailMessage)
$cred = Import-Clixml -Path "C:Scriptssmtp-cred.xml"
Import-Csv -Path ".contacts.csv" | ForEach-Object {
Send-MailMessage `
-From "onboarding@company.com" `
-To $_.Email `
-Subject "Welcome, $($_.Name)!" `
-Body "Your account is ready." `
-SmtpServer "smtp.office365.com" `
-Port 587 `
-UseSsl `
-Credential $cred
Start-Sleep -Seconds 2
}After (Nylas CLI)
The Nylas CLI loop removes the credential import and SMTP configuration lines. Each iteration sends through the provider's API using the keychain-stored API key, so the script works identically on any machine where nylas auth config has been run.
Import-Csv -Path ".contacts.csv" | ForEach-Object {
nylas email send `
--to $_.Email `
--subject "Welcome, $($_.Name)!" `
--body "Your account is ready." `
--yes
Start-Sleep -Seconds 2
}Side-by-side comparison
The table summarizes 11 feature differences between Send-MailMessage and Nylas CLI. The deprecated cmdlet supports only basic send operations with manual SMTP configuration and plaintext credentials. The CLI matches every Send-MailMessage feature and adds 4 capabilities the cmdlet never offered: email scheduling, inbox read access, JSON-structured output, and calendar management.
| Feature | Send-MailMessage | Nylas CLI |
|---|---|---|
| TLS security | Broken (deprecated) | TLS 1.2+ enforced |
| Authentication | Basic auth / app passwords | OAuth2 |
| Credentials in scripts | Yes (PSCredential / XML) | No (OS keychain) |
| Gmail support | Requires app password | OAuth2 built-in |
| Outlook / M365 support | Basic auth (being disabled) | OAuth2 built-in |
| HTML body | -BodyAsHtml flag | Auto-detected |
| Attachments | -Attachments | --attach |
| Email scheduling | Not supported | --schedule |
| Read inbox | Not supported | nylas email list |
| JSON output | Not supported | --json |
| Calendar access | Not supported | nylas calendar |
Frequently asked questions
These are the most common questions developers ask when migrating from Send-MailMessage to a modern replacement. The answers cover the deprecation timeline, migration effort, and feature parity between Send-MailMessage and Nylas CLI. Microsoft officially deprecated the cmdlet in PowerShell 7.0, released in March 2020 -- over 6 years ago.
Why is Send-MailMessage deprecated?
Microsoft deprecated it in PowerShell 7.0 because the underlying System.Net.Mail.SmtpClient cannot negotiate TLS securely. Microsoft recommends using third-party libraries instead.
What is the best replacement for Send-MailMessage?
Nylas CLI replaces Send-MailMessage with a single command. It handles OAuth2, TLS, and provider differences automatically. No SMTP credentials in your scripts, no provider-specific configuration.
Do I need to change my PowerShell scripts?
Yes, but the migration is straightforward. Replace each Send-MailMessage call with nylas email send and map the parameters: -To becomes --to, -Subject becomes --subject, -Body becomes --body, -Attachments becomes --attach.
Does Nylas CLI support all Send-MailMessage features?
Yes, and more. It supports HTML bodies (auto-detected), file attachments, CC/BCC, and multiple recipients. It also adds features Send-MailMessage never had: OAuth2, email scheduling, open/click tracking, JSON output, and inbox read access.
Next steps
After replacing Send-MailMessage with nylas email send, these guides cover related PowerShell email workflows -- reading inboxes, downloading attachments, building automated reports, and managing Office 365 email. Each guide includes tested code examples with the same CLI version used in this migration.
- Replace Send-MgUserMessage -- migrating from the newer Graph PowerShell cmdlets instead?
- Send email from PowerShell -- advanced patterns, scheduling, and scripting
- Read and search email in PowerShell -- list unread, search by sender, export to CSV
- Download email attachments in PowerShell -- filter by type, batch download, rename
- Automated email reports with PowerShell -- CSV reports, scheduled sends, templates
- Manage Office 365 email from PowerShell -- read, search, and organize your M365 inbox
- Full command reference -- every flag and subcommand documented