Guide
Send Email from PowerShell
PowerShell deprecated Send-MailMessage in version 7.0, and configuring raw SMTP from scripts means hardcoding credentials. Nylas CLI is a single Go binary that handles OAuth2, provider abstraction, and connection management. Install it, authenticate once, and send email from PowerShell with one command. Works with Gmail, Outlook, Exchange, Yahoo, iCloud, and IMAP.
Written by Qasim Muhammad Staff SRE
Reviewed by Nick Barraclough
Why not raw SMTP from PowerShell?
Raw SMTP from PowerShell is unreliable because the built-in Send-MailMessage cmdlet was deprecated and modern providers require OAuth2, not plaintext credentials. Microsoft marked the cmdlet obsolete in PowerShell 7.0 (released March 2020), and the .NET SmtpClient class it wraps has been deprecated since .NET 6. Nylas CLI replaces both with a single binary that handles OAuth2 token exchange for every provider.
PowerShell's Send-MailMessage was deprecated in PowerShell 7.0 because it cannot negotiate TLS securely. The alternatives -- System.Net.Mail.SmtpClient and direct socket connections -- require you to hardcode SMTP credentials, manage app passwords, and handle provider-specific quirks. Gmail requires OAuth2 or app passwords with 2FA. Outlook requires an app registration in Microsoft Entra ID. Every provider is different.
Nylas CLI abstracts all of this. One binary, one authentication flow, every provider.
1. Install Nylas CLI on Windows
Nylas CLI installs on Windows with a single PowerShell command that downloads a ~15 MB Go binary, verifies its SHA-256 checksum, and places it in your PATH. The install script auto-detects whether the system is x86_64 or ARM64, so the same command works on any Windows 10 or 11 machine. No admin privileges are required because the binary installs to a user-scoped directory.
The PowerShell install script fetches the latest release from GitHub, validates the checksum against the published manifest, and writes the binary to ~/.config/nylas/bin. Run this single command to install:
irm https://cli.nylas.com/install.ps1 | iexFor Homebrew, shell-script, and Go installs, see the getting started guide. After the script completes, the nylas command is available in any new PowerShell session. Verify the installation by checking the version number:
nylas --version2. Authenticate your mailbox
Nylas CLI authenticates against your email provider through the Nylas API, which manages OAuth2 tokens for Gmail, Outlook, Exchange, Yahoo, iCloud, and IMAP. Authentication takes about 2 minutes: create an application in the Nylas dashboard, connect your mailbox, then paste the API key into the CLI. After that one-time setup, the CLI refreshes tokens automatically -- no credentials are stored in scripts or environment variables.
Create an application at dashboard-v3.nylas.com, connect your mailbox, and then configure the CLI with your API key:
# Configure your API key
nylas auth config
# Paste your API key when prompted
# Verify it works
nylas auth whoami
# => Authenticated as you@company.com (Google Workspace)3. Build commands with PowerShell-native argument arrays
PowerShell argument splatting lets you define CLI flags as a named array and pass them with the @ operator, which avoids the quoting and escaping problems that break long single-line commands. According to the PowerShell splatting docs, this technique works in PowerShell 5.1 and 7+. A splatted array is easier to version-control because each flag sits on its own line, and diffs show exactly what changed.
$sendArgs = @(
"email", "send",
"--to", "colleague@company.com",
"--cc", "manager@company.com",
"--subject", "Quarterly report",
"--body", "Hi -- please review the Q4 numbers before Friday.",
"--yes"
)
& nylas @sendArgs4. HTML bodies, attachments, and file-backed content
Nylas CLI sends HTML email and file attachments by reading them from disk, which fits PowerShell's native file-handling strengths. Get-Content -Raw loads an entire HTML template into a single string variable, and the --attach flag accepts full Windows paths including UNC network shares. The CLI auto-detects HTML content and sets the MIME type to text/html, so no extra flags are needed.
Build the arguments in a splatted array and let PowerShell resolve the paths. This example loads an HTML template and attaches 2 PDF files:
$htmlBody = Get-Content -Path ".\email-template.html" -Raw
$attachments = @(
"C:\Users\you\Documents\invoice-march.pdf",
"C:\Users\you\Documents\terms.pdf"
)
$args = @(
"email", "send",
"--to", "client@example.com",
"--subject", "Invoice attached",
"--body", $htmlBody,
"--attach", $attachments[0],
"--attach", $attachments[1],
"--yes"
)
& nylas @args5. Send from PowerShell objects and CSV data
PowerShell's pipeline turns CSV rows into email sends with zero manual parsing. Import-Csv returns typed PSCustomObject rows, each with named properties that map directly to Nylas CLI flags. This pattern is common in Windows administration where input data comes from Active Directory exports, SCCM reports, or HR onboarding spreadsheets. A 500-row CSV processes in under 3 minutes on a standard connection because each nylas email send call completes in roughly 300-400 ms.
This example reads a CSV with Name and Email columns, builds a personalized body using PowerShell's here-string syntax (@"..."@), and sends one email per row:
Import-Csv -Path ".\contacts.csv" | ForEach-Object {
$body = @"
Hello $($_.Name),
Your account is ready.
"@
$args = @(
"email", "send",
"--to", $_.Email,
"--subject", "Hello $($_.Name)",
"--body", $body,
"--yes"
)
& nylas @args
}6. Schedule from Task Scheduler and scheduled jobs
Windows Task Scheduler runs PowerShell scripts unattended, which makes it the standard way to schedule recurring email sends on Windows Server and Windows 10/11. Nylas CLI works in non-interactive mode because authentication is stored locally after the initial nylas auth config step. Task Scheduler supports triggers at fixed times, intervals (every 15 minutes, hourly, daily), or on system events like startup and user logon.
When registering a scheduled task, specify the full path to pwsh.exe and use the -NoProfile flag to skip profile scripts that may add latency or prompt for input. Test the script under the same service account that Task Scheduler will use:
$action = New-ScheduledTaskAction -Execute "pwsh.exe" -Argument "-NoProfile -File C:\Scripts\Send-DailyReport.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At 8:00AM
Register-ScheduledTask -TaskName "Daily Email Report" -Action $action -Trigger $triggerNylas CLI also supports server-side scheduling with the --schedule flag. The email is queued on the Nylas API and delivered at the specified time, regardless of whether the local machine is running. This is useful for one-off scheduled sends that don't need a full Task Scheduler job:
# Or schedule delivery directly from the CLI
$scheduledArgs = @(
"email", "send",
"--to", "team@company.com",
"--subject", "Standup agenda",
"--body", "Please add your items.",
"--schedule", "tomorrow 9am",
"--yes"
)
& nylas @scheduledArgs7. JSON output and PowerShell objects
Every Nylas CLI command supports a --json flag that outputs structured JSON instead of human-readable text. PowerShell's ConvertFrom-Json cmdlet parses this output into PSCustomObject arrays, which can be filtered with Where-Object, sorted with Sort-Object, and exported with Export-Csv. This pipeline pattern replaces the jq + grep workflow used on Unix systems with native PowerShell object manipulation.
The --json output includes all fields returned by the Nylas API, including subject, from, date, unread, and id. Here are 4 common patterns:
# Count unread emails
$unread = nylas email list --unread --json | ConvertFrom-Json
Write-Host "Unread emails: $($unread.Count)"
# Get subjects of unread emails
$unread | ForEach-Object { Write-Host $_.subject }
# Find urgent emails
$urgent = nylas email list --unread --json |
ConvertFrom-Json |
Where-Object { $_.subject -match "urgent|asap" }
Write-Host "Urgent emails: $($urgent.Count)"
# Send results to a file
nylas email list --limit 50 --json |
ConvertFrom-Json |
Select-Object subject, from, date |
Export-Csv -Path ".inbox-report.csv" -NoTypeInformation8. PowerShell-native error handling
PowerShell uses structured try/catch blocks and the automatic $LASTEXITCODE variable for error handling, which gives scripts more control than bash's set -e approach. When Nylas CLI fails, it returns a non-zero exit code: 1 for authentication errors, 2 for invalid arguments, and higher codes for network or API failures. Wrapping sends in try/catch lets scheduled tasks log failures to the Windows Event Log or retry with exponential backoff.
This pattern catches send failures, writes the error to PowerShell's error stream, and exits with code 1 so that Task Scheduler marks the job as failed:
try {
$args = @(
"email", "send",
"--to", "alerts@company.com",
"--subject", "Windows service restart",
"--body", "The Print Spooler service was restarted on HOST-17.",
"--yes"
)
& nylas @args
if ($LASTEXITCODE -ne 0) {
throw "nylas email send failed with exit code $LASTEXITCODE"
}
}
catch {
Write-Error $_
Exit 1
}Frequently asked questions
Can I send email from PowerShell without Send-MailMessage?
Yes. Install Nylas CLI, authenticate once, and use nylas email send. It handles OAuth2 and TLS negotiation automatically -- no SMTP credentials, no deprecated cmdlets.
Does Nylas CLI work in PowerShell on Windows?
Yes. Nylas CLI is a Go binary that runs natively on Windows. It works in PowerShell 5.1, PowerShell 7+, Command Prompt, and Windows Terminal. All commands and flags are identical across shells.
How do I send HTML email from PowerShell?
Pass HTML in the --body flag or read it from a file with Get-Content -Raw. The CLI detects HTML content automatically and sets the correct MIME type.
Can I schedule emails from PowerShell?
Yes. Add --schedule "2h" or --schedule "tomorrow 9am" to any send command. Supports relative times and absolute dates.
Next steps
- 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 files
- Email and calendar automation in PowerShell -- check availability, create events, send reminders
- Automated email reports with PowerShell -- CSV reports, scheduled sends, template workflows
- PowerShell email monitoring and alerts -- disk space, service health, uptime notifications
- PowerShell email in CI/CD pipelines -- build notifications, deploy alerts, test results
- Gmail OAuth in PowerShell -- authenticate with Gmail using built-in OAuth
- Replace Send-MailMessage -- side-by-side migration from the deprecated cmdlet
- Replace Send-MgUserMessage -- migrating from Graph PowerShell cmdlets
- Full command reference -- every flag and subcommand documented