Saturday, May 11, 2013

Using ssmtp to send email notifications

I've been using ssmtp for a long time to send automatic notifications from all my embedded systems like routers or NASes and also to send anything from a command line to a desired email address. The program is only 8K (whereas mutt is 3.5M) but it can handle secure TLS/SSL connections to SMTP servers. Setup is very easy as only one file has to be adapted. Please read this tutorial to set the ssmtp up.

To make it easier to use I have written a bash script that handles email header creation and adds a simple command line interface:
alex@thinkpad:~$ cat bin/notifyemail.sh
#!/bin/sh

printUsage()
{
  echo "usage: $0 options"
  echo  
  echo "This script sends its standard input to the specified email address."
  echo  
  echo "OPTIONS:"
  echo " -e email@address to notify"
  echo " -s \"subject string\""
  echo " -a \"send as attachment\""
}

#default values
sendto="use_this_address_by_default@gmail.com"
subject="Notification"
from="thinkpad"
errorsfile=/tmp/ssmtp.error

while getopts 'ae:s:' option
do
  case $option in
    e) sendto=$OPTARG;;
    s) subject=$OPTARG;;
    a) doatt=1;;
    *) printUsage
       exit 1
       ;;
  esac
done

header="Subject: ${subject}\nFrom:${from}\nTo:${sendto}\n"
cmd=cat
attach="\n"
[ -n "$doatt" ] && {
  attach="Content-Type: multipart/mixed; boundary=012345\n\n--012345\n"
  attach="${attach}Content-Type: text/plain; charset=iso-8859-1\n\n\n\n--012345\n"
  attach="${attach}Content-Type: application/octet-stream; name=\"message.bin\"\n"
  attach="${attach}Content-Transfer-Encoding: base64\n"
  attach="${attach}Content-Disposition: attachment; filename=\"message.bin\"\n"
  attach="${attach}X-Attachment-Id: file0\n\n"
  ending="\n--012345--"

  if [ -n "$(which base64)" ]; then
    cmd=base64
  else
    cmd=openssl\ base64
  fi
}

# workaround for the 'sh echo' not handling -e
if [ -n "$(/bin/sh -c 'echo -ne')" ]; then
  echocmd=echo
else
  echocmd=echo\ -e
fi

$echocmd "${header}${attach}$($cmd)${ending}" | ssmtp "${sendto}" 2>>${errorsfile}
exit $?
 
To send a message as an attachment either base64 from coreutils or openssl shall be installed.

Below are some usage examples (check this post for the encrypt function):
# send a simple message to the default address address
echo -e "test\nmessage" | notifyemail.sh

# send a file as a plain text to the specified email address
cat ~/.vimrc | notifyemail.sh -e here@mail.com -s "Here is my .vimrc you asked for"

# send an encrypted file as an attachment
cat ~/classified.txt | encrypt | notifyemail.sh -a -s "top secret attach"

# same as above with the password been read from ~/mypass
cat ~/classified.txt | encrypt -pass file:~/mypass | notifyemail.sh -a -s "top secret attach"

2 comments:

Tegoeh Boediyanto said...

hi,

how to send images using this script? I already using the command like example but the recipient not get images but any character like result of command cat.

Thanks,
Teguh

alex said...

I'm not sure what's you problem. An attachment will be named as message.bin. Rename it or store it with a proper extension. Or maybe you haven't installed base64 or openssl?