# Send email from a PowerShell script

Source: https://developer.nylas.com/docs/cookbook/cli/send-email-powershell/

Windows admins and developers often need a script that fires off an email without standing up an SMTP relay or installing extra modules. PowerShell ships with `Invoke-RestMethod` on every supported version of Windows, so you can call the Nylas Email API directly over HTTPS. This recipe shows the full path: one authenticated send, secure key storage in Windows Credential Manager, and unattended scheduling with Task Scheduler.

If you work in Bash instead, the [Bash and cron version](/docs/cookbook/cli/send-email-bash-cron/) covers the same flow for Linux and macOS, and the [CI/CD pipeline guide](/docs/cookbook/cli/email-in-cicd/) shows how to send build notifications from a pipeline.

## How do you send email from a PowerShell script?

Call the Nylas send endpoint with `Invoke-RestMethod -Method Post`, passing a Bearer token in the headers and a JSON body built from a PowerShell hashtable. One HTTPS request delivers the message through the connected account, so no local SMTP server is involved. A typical send completes in under 2 seconds.

You need two values before you start: an API key from your dashboard and a `grant_id` that identifies the connected sending account. See [Nylas authentication](/docs/v3/auth/) for how to create a grant. The request below targets the US data region; swap the host for `api.eu.nylas.com` if your application lives in the EU. PowerShell converts the hashtable to JSON with `ConvertTo-Json`, and `-Depth 4` ensures the nested `to` array serializes correctly.

```powershell [psSend-Send email]
$apiKey  = $env:NYLAS_API_KEY
$grantId = $env:NYLAS_GRANT_ID

$payload = @{
  to      = @( @{ email = "recipient@example.com" } )
  subject = "Nightly report ready"
  body    = "The 02:00 batch finished successfully."
} | ConvertTo-Json -Depth 4

Invoke-RestMethod `
  -Method Post `
  -Uri "https://api.us.nylas.com/v3/grants/$grantId/messages/send" `
  -Headers @{
    "Authorization" = "Bearer $apiKey"
    "Content-Type"  = "application/json"
  } `
  -Body $payload
```

The body accepts `to`, `cc`, `bcc`, `reply_to`, `subject`, `body`, `attachments`, and `tracking_options`. For the full field reference and attachment encoding, see [Send email without SMTP](/docs/cookbook/use-cases/build/send-email-without-smtp/).

## How do you store the API key securely on Windows?

Never hardcode the key in the script file. Windows Credential Manager stores secrets in your Windows user account's encrypted vault, where `-Persist LocalMachine` keeps them available across logon sessions on that machine, and the `Get-StoredCredential` approach lets your script read the key at runtime without exposing it in source control or process arguments. The script reads the key at runtime and never writes it to disk, so the plaintext key stays out of source control entirely.

Install the `CredentialManager` module once, then save the key as a generic credential. The script reads it back at run time and never writes the plaintext to disk. For interactive testing you can also set a session-scoped environment variable, but Credential Manager is the better choice for scheduled tasks that run as a service account. The example reads the stored credential and assigns the password to the same `$apiKey` variable the send step expects, so the request code stays unchanged.

```powershell [psCred-Store and read key]
# Run once to store the key (prompts securely, no plaintext on disk)
Install-Module CredentialManager -Scope CurrentUser -Force
New-StoredCredential -Target "Nylas" -UserName "api" `
  -Password (Read-Host "API key" -AsSecureString) `
  -Persist LocalMachine

# In your script: read it back at run time
$cred   = Get-StoredCredential -Target "Nylas"
$apiKey = $cred.GetNetworkCredential().Password
```

## How do you schedule a PowerShell email send on Windows?

Use `schtasks` to register the script with Windows Task Scheduler so it runs unattended on a fixed schedule. Task Scheduler supports intervals from 1 minute to monthly, runs under a chosen account, and survives reboots, which makes it the Windows equivalent of cron for recurring sends.

Save your send logic to a `.ps1` file, then register it. The command below runs the script every day at 02:00. The `-ExecutionPolicy Bypass` flag lets the scheduler launch an unsigned local script without changing the machine-wide policy, and `-WindowStyle Hidden` keeps it from flashing a console window. Run the registration from an elevated PowerShell prompt so the task can be created under the system or a dedicated service account.

```powershell [psSchtasks-Schedule the task]
schtasks /Create `
  /TN "NightlyEmailJob" `
  /TR "powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -File C:\scripts\send-report.ps1" `
  /SC DAILY `
  /ST 02:00 `
  /RU "DOMAIN\svc-reports"
```

After registration, confirm the task with `schtasks /Query /TN "NightlyEmailJob"` and trigger a manual run with `schtasks /Run /TN "NightlyEmailJob"` to verify the first send before you rely on the schedule.

## What's next

- [Send email without SMTP](/docs/cookbook/use-cases/build/send-email-without-smtp/) for the full field reference, attachments, and reply threading
- [Send email from Bash and cron](/docs/cookbook/cli/send-email-bash-cron/) for the Linux and macOS equivalent
- [Send email in CI/CD pipelines](/docs/cookbook/cli/email-in-cicd/) for build and deploy notifications
- [Nylas authentication](/docs/v3/auth/) to create the grant your script sends from