BASH - Send mail with an Attachment


This requires uuencode, which is available in the package sharutils.

It uses the command line utility sendmail, and formats the smtp message as necessary to send an email and an attachment. We also have an article with just a basic bash sendmail script.
#!/bin/bash
#requires: basename,date,md5sum,sed,sendmail,uuencode
function fappend {
    echo "$2">>$1;
}
YYYYMMDD=`date +%Y%m%d`
 
# CHANGE THESE
TOEMAIL="recipient@email.com";
FREMAIL="crondaemon@65.244.254.144";
SUBJECT="Daily Backup - $YYYYMMDD";
MSGBODY="Hello this is the message body";
ATTACHMENT="/home/joeuser/Untitled.png"
MIMETYPE="image/png" #if not sure, use http://www.webmaster-toolkit.com/mime-types.shtml
 
# DON'T CHANGE ANYTHING BELOW
TMP="/tmp/tmpfil_123"$RANDOM;
BOUNDARY=`date +%s|md5sum`
BOUNDARY=${BOUNDARY:0:32}
FILENAME=`basename $ATTACHMENT`
 
rm -rf $TMP;
cat $ATTACHMENT|uuencode --base64 $FILENAME>$TMP;
sed -i -e '1,1d' -e '$d' $TMP;#removes first & last lines from $TMP
DATA=`cat $TMP`
 
rm -rf $TMP;
fappend $TMP "From: $FREMAIL";
fappend $TMP "To: $TOEMAIL";
fappend $TMP "Reply-To: $FREMAIL";
fappend $TMP "Subject: $SUBJECT";
fappend $TMP "Content-Type: multipart/mixed; boundary=\""$BOUNDARY"\"";
fappend $TMP "";
fappend $TMP "This is a MIME formatted message.  If you see this text it means that your";
fappend $TMP "email software does not support MIME formatted messages.";
fappend $TMP "";
fappend $TMP "--$BOUNDARY";
fappend $TMP "Content-Type: text/plain; charset=ISO-8859-1; format=flowed";
fappend $TMP "Content-Transfer-Encoding: 7bit";
fappend $TMP "Content-Disposition: inline";
fappend $TMP "";
fappend $TMP "$MSGBODY";
fappend $TMP "";
fappend $TMP "";
fappend $TMP "--$BOUNDARY";
fappend $TMP "Content-Type: $MIMETYPE; name=\"$FILENAME\"";
fappend $TMP "Content-Transfer-Encoding: base64";
fappend $TMP "Content-Disposition: attachment; filename=\"$FILENAME\";";
fappend $TMP "";
fappend $TMP "$DATA";
fappend $TMP "";
fappend $TMP "";
fappend $TMP "--$BOUNDARY--";
fappend $TMP "";
fappend $TMP "";
#cat $TMP>out.txt
cat $TMP|sendmail -t;
rm $TMP;


Note: when i put this in a cronjob I usually have to replace 'sendmail' above with '/usr/sbin/sendmail'. To find out where sendmail is on your system type:
[root@server /home] which sendmail


już nigdy nie usłyszę kochanych twych słów on 2010-01-19 05:46:00
BOUNDARY=`date +%s|md5sum|cut -b1-32` #probably the preferable way of parsing md5sum output, at least a shorthand or an alternative

już nigdy do mych ust nie przytulę cię znów on 2010-01-19 05:49:43
TMP=`mktemp`;
or
TMP=`tempfile`;

PM on 2010-02-16 01:55:13
Thanks for the script!

An alternativ for base64 coding:
... | openssl base64

This makes the cut-offs with sed obsolet .

Cheers PM



optimus on 2010-03-25 03:54:08
How to add multiple graph/image attachment with this script.

Thanks

Rob on 2010-03-25 23:14:45
Great script, the uuencode wouldn't work for me, but the openssl base64 worked great.

Optimus, you should be able to copy the sections on adding the file (make sure with the right type) and the part between the 2nd and 3rd boundary as often as you want.. adding multiple files.

#!/bin/bash
#requires: basename,date,md5sum,sed,sendmail,uuencode
function fappend {
echo "$2">>$1;
}
YYYYMMDD=`date +%Y%m%d`

# CHANGE THESE
TOEMAIL="recipient@email.com";
FREMAIL="crondaemon@65.244.254.144";
SUBJECT="Daily Backup - $YYYYMMDD";
MSGBODY="Hello this is the message body";
ATTACHMENT="/home/joeuser/Untitled.png"
MIMETYPE="image/png" #if not sure, use http://www.webmaster-toolkit.com/mime-types.shtml

rm -rf $TMP;
fappend $TMP "From: $FREMAIL";
fappend $TMP "To: $TOEMAIL";
fappend $TMP "Reply-To: $FREMAIL";
fappend $TMP "Subject: $SUBJECT";
fappend $TMP "Content-Type: multipart/mixed; boundary=""$BOUNDARY""";
fappend $TMP "";
fappend $TMP "This is a MIME formatted message. If you see this text it means that your";
fappend $TMP "email software does not support MIME formatted messages.";
fappend $TMP "";
fappend $TMP "--$BOUNDARY";
fappend $TMP "Content-Type: text/plain; charset=ISO-8859-1; format=flowed";
fappend $TMP "Content-Transfer-Encoding: 7bit";
fappend $TMP "Content-Disposition: inline";
fappend $TMP "";
fappend $TMP "$MSGBODY";
fappend $TMP "";
fappend $TMP "";

TMP="/tmp/tmpfil_123"$RANDOM;
BOUNDARY=`date +%s|md5sum`
BOUNDARY=${BOUNDARY:0:32}
FILENAME=`basename $ATTACHMENT`

rm -rf $TMP;
cat $ATTACHMENT|uuencode --base64 $FILENAME>$TMP;
sed -i -e '1,1d' -e '$d' $TMP;#removes first & last lines from $TMP
DATA=`cat $TMP`
#copy the below part for every attachement
fappend $TMP "--$BOUNDARY";
fappend $TMP "Content-Type: $MIMETYPE; name="$FILENAME"";
fappend $TMP "Content-Transfer-Encoding: base64";
fappend $TMP "Content-Disposition: attachment; filename="$FILENAME";";
fappend $TMP "";
fappend $TMP "$DATA";
fappend $TMP "";
fappend $TMP "";
fappend $TMP "--$BOUNDARY--";

#and then the send email and cleanup
fappend $TMP "";
fappend $TMP "";
#cat $TMP>out.txt
cat $TMP|sendmail -t;
rm $TMP;

Chris on 2011-03-18 08:45:59
Maybe this is useful for anyone:

If you want to use linebreaks in $MSGBODY, a simple n won't do (at least it didn't for me).

If you hardcode the variable in your script, just press Enter instead of inserting a n
->
MSGBODY="Hi there,

I just wanted to tell you...

bye"

If this doesn't satisfy your eyes because of the formatting of your script, there's another way:

MSGBODYTXT="Hi there,nnI just wanted to tell you...nnbye";
MSGBODY=`echo -e "$MSGBODYTXT"`

Of course this also works out well if you use a script's parameter instead of $MSGBODYTXT - e.g. in combination with a sort of signature:
(ran the script with 1st parameter "Hi therennblabla")
SIGTXT="nnConcernedly YoursnnSimona Silly"
MSGBODY=`echo -e "$1" "$SIGTXT"`


Chris on 2011-03-18 08:53:01
dang, the commenting module doesn't like linebreaks either ;o)
imagine any "n" or "nn" that doesn't make sense with an ESCAPE before it...
\ \


User on 2011-08-22 14:37:00
Can you also post the generated content as I have tried the same and view in Outlook 2007 and not been able to see the image.