Send email with curl over SMTP from a shell script

One-liner and scripted examples of sending mail with curl's SMTP support: STARTTLS on 587 (--ssl-reqd), authentication, a message file with headers, and the msmtp alternative for cron jobs.

Install

shell
# curl is already installed; alternative: sudo apt install msmtp

Complete example

curl / Bash — STARTTLS on 587, credentials from the environment
# message.txt
From: Your App <hello@yourdomain.com>
To: customer@example.com
Subject: Backup finished

The nightly backup completed at $(date).

# send (STARTTLS on 587)
curl --ssl-reqd --url "smtp://smtp.queensmtp.com:587" \
  --user "$SMTP_USER:$SMTP_PASS" \
  --mail-from "hello@yourdomain.com" \
  --mail-rcpt "customer@example.com" \
  --upload-file message.txt

# implicit TLS on 465
curl --url "smtps://smtp.queensmtp.com:465" --user "$SMTP_USER:$SMTP_PASS" \
  --mail-from hello@yourdomain.com --mail-rcpt customer@example.com --upload-file message.txt

# msmtp for cron/mail(1) users — ~/.msmtprc (chmod 600)
defaults
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
account default
host smtp.queensmtp.com
port 587
user your-smtp-username
password your-smtp-password
from hello@yourdomain.com
# then:  echo "body" | msmtp -s "subject" customer@example.com

What to know

  • --ssl-reqd forces STARTTLS and fails rather than sending plaintext; smtps:// on 465 is implicit TLS.
  • The uploaded file must contain the headers (From/To/Subject) and a blank line before the body — curl sends it verbatim.
  • Add -v to see the SMTP conversation and the exact reply code when something fails.

Same code, different provider

Only the host, port and credentials change. The rules per provider are on the SMTP settings hub.

ProviderHostPortUsernamePasswordNote
QueenSMTP smtp.queensmtp.com587 (STARTTLS) / 465 (SSL) / 2525SMTP username from the dashboardSMTP password$5/year + $0.10 per 1,000; 100 free/day
Gmail smtp.gmail.com587 / 465you@gmail.comApp Password500/day, From must be the account
Amazon SES email-smtp.<region>.amazonaws.com587 / 465 / 2587SES SMTP usernameSES SMTP passwordsandbox 200/day until approved
Office 365 smtp.office365.com587user@yourdomain.commailbox passwordSMTP AUTH must be enabled; 30/min
SendGrid smtp.sendgrid.net587 / 465 / 2525apikeyAPI keyno free plan since 2025

Credentials for the example above

Create a free account, verify your sending domain (SPF + DKIM shown in the dashboard), add an SMTP credential, and paste it into the code. 100 emails a day free; $5/year plus $0.10 per 1,000 after that. Prefer HTTPS? The same account has a REST email API.

Get SMTP credentials Test your settings first

Other languages and frameworks

Examples tested 2026-08-30. If a library changed its API, tell us.

curl / Bash SMTP — questions

Authentication failed — wrong user/password for this host, or you connected on 25 where the server does not offer AUTH.