Send emails using Curl

Updated on

Emailing with Curl

curl is an amazing networking tool. It can even automate sending emails!

Email just a file

For most basic emails, we can stuff the headers into the email content file itself. Here’s a basic example:

# This line writes the content to a file called email.txt.
# Usually you should use a text editor to write to a file yourself.
cat <<EMAIL > email.txt
From: Emiliko Mirror <emiliko@cs.ox.ac.uk>
To: Emiliko Mirror <emiliko@gmail.com>
Subject: Sleep triggered on $(hostname)
Date: $(date)
 
Dear me,
 
The system went to sleep! I thought I should notify my gmail account when it
happened.
 
cheers,
Emiliko
EMAIL
 
# Sends the file called `email.txt` as an email, not an email attachment.
# Note that you need to replace <my-password-here> with your gmail password.
curl --silent --ssl-reqd \
  --url 'smtps://smtp.gmail.com:465' \
  --user 'emiliko@cs.ox.ac.uk:<my-password-here>' \
  --mail-from 'emiliko@cs.ox.ac.uk' \
  --mail-rcpt 'emiliko@gmail.com' \
  --upload-file email.txt

The From: - Date: headers at the top are very important. Gmail seems to insert them automatically if they’re missing, though other mail providers might not, so make sure to leave them in.

If you use 2fa, you won’t be able to use your account password to authenticate. Instead, you’ll need to obtain an app password for your account.

Email with attachments

We can also CC, BCC and attach files with our curl emails.

Attachments need a MIME type for the file, which is easiest obtained with the file command. In this example, we also remove the headers from the email file, opting to use the more explicit -H curl option.

# Setup variables for attachment file. Not necessary but much cleaner
declare -r attach_file=mirrors_house.png
declare -r mime_type="$(file --mime-type "$attach_file" | sed 's/.*: //')"
 
# Fill a file called `email.txt` with the email content
cat <<EMAIL > email.txt
Dear classmates,
 
I just bought a new house! Check out the picture I attached below
 
OMGOMGOMG, I'm so excited!
 
cheers,
Kate Mirror
EMAIL
 
# Sends email.txt as the email content and attaches mirrors_house.png
curl --silent --ssl-reqd \
  --url 'smtps://smtp.fastmail.com:465' \
  --user 'kate%40mirror.house:<my-password>' \
  --mail-from "kate@mirror.house" \
  --mail-rcpt 'emiliko@cs.ox.ac.uk' \
  --mail-rcpt 'lou@lou.me' \
  --mail-rcpt 'louis@louis.me' \
  -F '=(;type=multipart/mixed' \
  -F "=$(cat email.txt);type=text/plain" \
  -F "file=@${attach_file};filename=home.png;type=${mime_type};encoder=base64" \
  -F '=)' \
  -H "From: Kate Mirror <kate@mirror.house>" \
  -H "Subject: Check out my new place!" \
  -H "To: Emiliko Mirror <emiliko@cs.ox.ac.uk>" \
  -H "CC: Lou Mirror <lou@lou.me>" \
  -H "Date: $(date)"

Notice that for BCC the user isn’t mentioned in -H at all, though you’ll still need a --mail-rcpt line for them.

Oddly, some mail servers seem sensitive to the filename field. My university server would consistently bounce emails when I tried to have a filename field. Consider removing it to use the file’s actual name. In the example above, we’d use mirrors_house.png instead of home.png.

Further reading