Sending an email with attachment by using Amazon SES Services

Amazon Simple Email Service (Amazon SES)

“sender.sh” script can send an email with an attachment by using Amazon SES services (Amazon Simple E-mail Services). It needs the AWS Cli tool.

Install

You have to just install the AWS CLI tool. There are many ways to install the Amazon Web Service Command Line Client (aka AWS Cli) including using pip package manager, homebrew package manager or just downloading the raw executables.(http://docs.aws.amazon.com/cli/latest/userguide/installing.html) As a Mac user, I prefer to use Homebrew ( https://brew.sh/ )

brew install awscli

or

pip3 install --upgrade --user awscli

After installing AWS Cli, you must configure the credential file. You can use this command:

aws configure

This command asks your aws access key and secret key and region.

AWS Access Key ID [None]: AKIAI44QH8DHBEXAMPLE
AWS Secret Access Key [None]: je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY
Default region name [None]: us-east-1

Normally you can use just aws command to send a simple email without any attachment.

aws ses send-email \
--from "cem@domain.com" \
--destination "ToAddresses=batur@domain.com" \
--message "Subject={Data=from ses,Charset=utf8},Body={Text={Data=ses says hi,Charset=utf8},Html={Data=,Charset=utf8}}"

But if you want to send an email with an attachment, you must use a raw message. AWS uses a JSON file format to prepare a raw message.

{
"Data": "From: {FROM}\nTo: {RECVS}\nSubject: {SUBJECT}\nMIME-Version: 1.0\nContent-type: Multipart/Mixed; boundary=\"NextPart\"\n\n--NextPart\nContent-Type: text/plain\nContent-Transfer-Encoding: base64\n\n{BODY}\n\n--NextPart\nContent-Type: text/plain;\nContent-Disposition: attachment; filename=\"{FILENAME}\"\nContent-Transfer-Encoding: base64\n\n{ATTACHMENT}\n\n--NextPart--"
}

I used some variables like {FROM}, {SUBJECT}, etc.. Because I am planning to change these variables with script arguments and create dynamic a raw message file.

Here it is…

function sendMail() {

if [[ -z ${ATTACHMENT} ]]; then
ATTACHMENT=$BODY
FILENAME="Message.txt"
else
FILENAME=$(basename "${ATTACHMENT%}")
ATTACHMENT=`base64 -i $ATTACHMENT`
fi

TEMPLATE="ses-email-template.json"

TMPFILE="/tmp/ses-$(date +%s)"

cp $TEMPLATE $TMPFILE

sed -i -e "s/{SUBJECT}/$SUBJECT/g" $TMPFILE
sed -i -e "s/{FROM}/$FROM/g" $TMPFILE
sed -i -e "s/{RECVS}/$RECVS/g" $TMPFILE
sed -i -e "s/{BODY}/$BODY/g" $TMPFILE
sed -i -e "s/{FILENAME}/$FILENAME/g" $TMPFILE
sed -i -e "s/{ATTACHMENT}/$ATTACHMENT/g" $TMPFILE

aws ses send-raw-email --raw-message file://$TMPFILE
}

You should use base64 encoding to send an email smoothly. After adding some checks and parsing command-line arguments and assigning values, our script is ready.

#!/bin/bash

function usage() {
echo "Usage: $0 [-h|--help ]
[-s|--subject <string> subject/title for email ]
[-f|--from <email> ]
[-r|--receiver|--receivers <emails> coma seperated emails ]
[-b|--body <string> ]
[-a|--attachment <filename> filepath ]
[--aws-region <string> Change Default AWS Region ]
[--aws_access_key_id <string> Change AWS Access Key ID ]
[--aws_secret_access_key <string> Change AWS Secret Access Key ]
" 1>&2;
exit 1;
}

function Error() {
echo "Error: $1"
exit
}

function checkRequirements() {

which aws
if [ $? -ne 0 ]; then
Error "AWS Cli tool is installed"
fi

which base64
if [ $? -ne 0 ]; then
Error "base64 tool is installed"
fi
}


function sendMail() {

if [[ -z ${ATTACHMENT} ]]; then
ATTACHMENT=$BODY
FILENAME="Message.txt"
else
FILENAME=$(basename "${ATTACHMENT%}")
ATTACHMENT=`base64 -i $ATTACHMENT`
fi

TEMPLATE="ses-email-template.json"

TMPFILE="/tmp/ses-$(date +%s)"

cp $TEMPLATE $TMPFILE

sed -i -e "s/{SUBJECT}/$SUBJECT/g" $TMPFILE
sed -i -e "s/{FROM}/$FROM/g" $TMPFILE
sed -i -e "s/{RECVS}/$RECVS/g" $TMPFILE
sed -i -e "s/{BODY}/$BODY/g" $TMPFILE
sed -i -e "s/{FILENAME}/$FILENAME/g" $TMPFILE
sed -i -e "s/{ATTACHMENT}/$ATTACHMENT/g" $TMPFILE

aws ses send-raw-email --raw-message file://$TMPFILE
}

while :; do
case $1 in
-h|-\?|--help)
usage
;;
-s|--subject)
SUBJECT=$2
shift
;;
-f|--from)
FROM=$2
shift
;;
-r|--receiver|--receivers)
RECVS=$2
shift
;;
-b|--body)
BODY=`echo "$2" | base64`
shift
;;
-a|--attachment)
ATTACHMENT=$2
shift
;;
--aws-region)
AWS_DEFAULT_REGION=$2
shift
;;
--aws_access_key_id)
AWS_ACCESS_KEY_ID=$2
shift
;;
--aws_secret_access_key)
AWS_SECRET_ACCESS_KEY=$2
shift
;;
*) # Default case: No more options, so break out of the loop.
break
esac

shift
done

checkRequirements

sendMail

Here it is a simple and easy use script. How can use it? The help is included :)

$ sh sender.sh -hUsage: sender.sh [-h|--help ]
[-s|--subject <string> subject/title for email ]
[-f|--from <email> ]
[-r|--receiver|--receivers <emails> coma seperated emails ]
[-b|--body <string> ]
[-a|--attachment <filename> filepath ]
[--aws-region <string> Change Default AWS Region ]
[--aws_access_key_id <string> Change AWS Access Key ID ]
[--aws_secret_access_key <string> Change AWS Secret Access Key ]

Example Usings

sh sender.sh -s test -f cem@domain.com -r batur@domain.com -b "mail content" -a ~/Documents/Projects/batur/test.htmlsh sender.sh -s test -f cem@domain.com -r batur@domain.com -b "mail content" -a ~/Documents/Projects/batur/test.html --aws-region us-east-1

GitHub

If you are lazy or have more important jobs, you can find this code on my Github repo. :)

DevOps & Software & Architect & Linux Geek — http://baturorkun.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store