Guide

Send iCloud Mail from the CLI

iCloud Mail has one programmatic entry point: SMTP on smtp.mail.me.com:587, guarded by an app-specific password. This guide covers sending from @icloud.com, iCloud+ custom domains, and Hide My Email relays without that setup.

Written by Qasim Muhammad Staff SRE

Reviewed by Nick Barraclough

VerifiedCLI 3.1.1 · iCloud · last tested April 11, 2026

Why iCloud Mail is awkward to send from the terminal

Apple requires an app-specific password for any third-party access to iCloud Mail, a policy bundled with mandatory two-factor authentication on Apple IDs. The only programmatic route is SMTP on smtp.mail.me.com:587, protected by one of those passwords generated at appleid.apple.com. Reset the Apple ID password or revoke the app-specific password and every script breaks at once.

The static-password model makes multi-account work painful. Each Apple ID needs its own 16-character password stored somewhere in plaintext. There's no refresh, no scope, and no rotation that doesn't force you to touch every downstream consumer.

The CLI talks to the Nylas API instead. Nylas handles the iCloud auth dance, manages refresh tokens, and pools connections. You authenticate once and sends work from the primary mailbox, iCloud+ custom domains, and Hide My Email relays through the same command.

1. Install

brew install nylas/nylas-cli/nylas

For shell script, PowerShell, and go install options, see the getting started guide.

2. Authenticate your iCloud account

Create a Nylas application at dashboard-v3.nylas.com, connect your iCloud mailbox, and copy the API key. Then:

nylas auth config
# paste API key when prompted
nylas auth whoami
# => Authenticated as you@icloud.com (iCloud)

The key lands in your system keyring. No plaintext credentials sit in your dotfiles or environment.

3. Send: basic, HTML, attachments, CC/BCC

The nylas email send command behaves the same across providers. See send email from the command line for full flag documentation. The short version:

# Basic send (use --yes in scripts to skip the confirmation prompt)
nylas email send \
  --to friend@example.com \
  --subject "Quick update" \
  --body "Hey, just wanted to share this link." \
  --yes

# HTML body
nylas email send --to subscriber@example.com \
  --subject "Weekly digest" \
  --html "<h1>This Week</h1><p>Here's what happened.</p>" \
  --yes

# Attachments (repeat --attach for multiple files)
nylas email send --to team@company.com \
  --subject "March report" \
  --body "Attached is the report." \
  --attach ./march-report.pdf --attach ./appendix.xlsx \
  --yes

# CC and BCC
nylas email send --to alice@team.com \
  --cc bob@team.com --bcc manager@team.com \
  --subject "Project status" \
  --body "All tasks on track for Friday." \
  --yes

iCloud Mail caps attachments at 20 MB per message. Apple's Mail Drop (which absorbs files up to 5 GB) runs only in Apple Mail and at iCloud.com. It isn't exposed through SMTP or any public API, so it isn't available from the terminal either.

4. Send from a custom domain or Hide My Email alias

This is the iCloud-specific feature that matters most. An iCloud+ subscription (starting at $0.99/month for the 50 GB tier) unlocks up to 5 custom email domains and unlimited Hide My Email relay addresses. Once a domain is verified in iCloud settings, you can send from any address on it with --from:

# Send from your custom domain
nylas email send \
  --to client@example.com \
  --from hello@yourdomain.com \
  --subject "Invoice #1042" \
  --body "Please find your invoice attached." \
  --attach ./invoice-1042.pdf \
  --yes

# Send from a Hide My Email relay
nylas email send \
  --to newsletter@service.com \
  --from abc123@privaterelay.appleid.com \
  --subject "Unsubscribe" \
  --body "Please remove me from your list." \
  --yes

Hide My Email relays forward incoming mail to your real inbox; recipients only see the relay address. The same mechanism powers Sign in with Apple's private relay.

Custom domain DNS setup

Before a domain can send, Apple requires three DNS records at your registrar. From Apple's iCloud custom domain docs:

RecordPurposeValue Apple provides
MXRoute inbound mail to iCloudmx01.mail.icloud.com and mx02.mail.icloud.com (priority 10)
TXT (SPF)Authorize Apple to send on your behalfv=spf1 include:icloud.com ~all
TXT (DKIM)Sign outbound messagesUnique per domain; Apple generates when you add the domain

Propagation usually finishes inside an hour but Apple can take up to 72 hours to verify. The CLI surfaces a clean "sender domain not verified" error until verification completes, so it's safe to queue sends before DNS finishes propagating.

5. JSON output for scripting

Add --json to any command for structured output. Useful when piping into jq, logging, or feeding another process.

nylas email send --to user@example.com \
  --subject "Automated alert" \
  --body "Build failed: see logs." \
  --yes --json | jq '.id'

iCloud SMTP vs the CLI

StepiCloud SMTPNylas CLI
Enable 2FA on Apple IDRequiredHandled by the Nylas OAuth flow
Generate app-specific passwordRequired per scriptNot used
SMTP host/portsmtp.mail.me.com:587 (STARTTLS)Not exposed
Token refreshNo (static password)Automatic
Custom domain sendingPer-domain SMTP config--from flag
Hide My Email sendNot possible via SMTP--from flag
Scheduled deliveryNot supported--schedule flag
JSON outputNot supported--json flag

Apple-specific sending details

Daily sending limits

Apple's iCloud system requirements page caps iCloud Mail at 1,000 outbound messages per day and 500 recipients per message (To + CC + BCC combined). The 24-hour window is rolling, not a calendar-day reset. Apple doesn't publish the short-burst throttle, so sustained bursts can trigger temporary delays before you hit the daily cap.

Hide My Email limits

Paid iCloud+ plans get unlimited Hide My Email addresses. Generate them from Settings > Apple ID > iCloud > Hide My Email on iOS, or from icloud.com/settings on the web. Once a relay is deactivated, new mail to that address stops forwarding.

Custom domain caps

iCloud+ permits 5 custom domains per account. Custom domains are included with iCloud+ features that can be shared through Family Sharing. If DNS records change after verification, Apple suspends outbound sending on that domain until the records match again.

Why Mail Drop doesn't work from the terminal

Apple's Mail Drop uploads attachments over 20 MB to iCloud servers and sends a download link instead of the file. The feature is bolted onto Apple Mail and the iCloud.com web client; it isn't exposed through SMTP or any public API. For large files from the terminal, upload to a shareable location and send the link in the body.

Troubleshooting iCloud sends

"Sender domain not verified" on custom-domain sends

Apple won't let a custom domain send until its MX, SPF, and DKIM records are all visible at the authoritative nameservers. Check propagation with dig MX yourdomain.com +short and dig TXT yourdomain.com +short. If the records look right but Apple still rejects, wait. Apple re-checks DNS periodically, and verification can take up to 72 hours.

"550 5.7.1 Message rejected due to local policy"

iCloud's outbound filter flagged the message. Common causes: the body contains URL shorteners (bit.ly, tinyurl), the subject is a single word, or the message went to a large BCC list with identical body text. Rewrite the body with the real destination URL and break up large BCC runs.

Sending suddenly stops after a batch run

You've tripped the 1,000-message daily cap. The block lasts 24 hours from the 1,001st message, not from midnight Pacific. For higher throughput, connect a second iCloud+ account or move bulk email to a dedicated transactional provider. iCloud Mail isn't designed for campaign traffic.

OAuth consent loop during the initial mailbox connection

If Apple's consent screen shows "Something went wrong" while connecting the mailbox in the Nylas dashboard, the Apple ID likely has a pending 2FA trust prompt on another device. Open Settings > Apple ID on any signed-in device, accept any pending prompts, then retry the mailbox connection.

Replies to a Hide My Email send bounce back

If replies are bouncing, check Settings > Apple ID > iCloud > Hide My Email and confirm the address isn't set to "Deactivate". The UI shows deactivated addresses greyed out but still lists them, so it's easy to miss that a relay was turned off earlier.

Next steps