Using cURL to send an e-mail with an attachment

TL;DR Version: You would think that sending an e-mail with an attachment using only cURL in a shell script would be a simple exercise, indeed it's a native feature of cURL. One day I was looking for a quick bit of info for a shell script I was writing and became frustrated at the lack of a fully working example. The documentation has a few ambiguities which made putting it all together not just a 5 minute exercise. So for those looking for a fully working example, check out the script I put together here: https://github.com/ambanmba/send-ses.

Longer version: I've been looking for a way to send quick transactional messages using Amazon SES via a shell script. There is the aws-cli which has built-in features for this and this technique works, as outlined here: https://github.com/ambanmba/aws-ses-sender. The problem with this approach, however; is that you need to have installed the aws-cli on the device (which isn't always possible/feasible) and it creates a dependency that I was looking to avoid. It also requires you to use Amazon SES as opposed to any SMTP server.

The cURL project (also see here) natively supports sending mail via SMTP and also has the benefit of being preinstalled on many systems include macOS, Linux/Unix and even more recent versions of Windows. This opens up the possibility of a completely cross-platform method of sending messages from the command line that contain attachments. 

If you Google around how to send e-mails with cURL they don't tend to include examples that include attachments for some reason. The other thing you see is that people build up an rfc5322 formatted file which is then sent via the cURL command. This to me was inelegant since cURL natively supports making the rfc5322 file on its own. 

So my goal became to create a way to 1) send an e-mail, 2) using an SMTP server, 3) with an attachment, 4) that has the correct MIME type associated with it, 5) without creating any interim temporary files. 

And voila! Here is my worked example (also on GitHub: https://github.com/ambanmba/send-ses) which uses Amazon SES, although you could use whatever SMTP server you like. 

It uses the native cURL functionality (-F and -H) to directly create and send the rfc5322 file without any interim steps.

To use this, you just run this script and provide filename to send.

#!/bin/bash 

sesAccess='AKIAXXXXXXXXXXXXXXXX' sesSecret='Bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
sesFromName="Joe McJones"
sesFromAddress="joe.mcjones@fakeaddress.net"
sesToName="Mary McMary"
sesToAddress="mary.mcmary@notmyrealmail.com"
sesSubject="Test Email from Script"
sesSMTP="email-smtp.us-east-1.amazonaws.com"
sesPort="465"
sesMessage=$'Test of line 1\nTest of line 2'
sesFile="$1"
sesMIMEType=`file --mime-type "$sesFile" | sed 's/.*: //'`

curl -v --url smtps://$sesSMTP:$sesPort --ssl-reqd  --mail-from $sesFromAddress --mail-rcpt $sesToAddress  --user $sesAccess:$sesSecret -F '=(;type=multipart/mixed' -F "=$sesMessage;type=text/plain" -F "file=@$sesFile;type=$sesMIMEType;encoder=base64" -F '=)' -H "Subject: $sesSubject" -H "From: $sesFromName <$sesFromAddress>" -H "To: $sesToName <$sesToAddress>"

No comments:

Post a Comment