<

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x

Using just Bash and Sendmail to send multiple input files and / or a pipe as attachments in an email

Published on
14,289 Points
7,789 Views
Last Modified:
Approved
Over the years I've spent many an hour playing on hardened, DMZ'd servers, with only a sub-set of the usual GNU toy's to keep me company; frequently I've needed to save and send log or data extracts from these server back to my PC, or to others, and more often than not, to do this on a regular basis.

Simple enough on an open box, just cron a script to extract and format the necessary data and either send it as a uuencoded / base 64 mmencoded attachment in an email, or simply copy / scp's the file to somewhere you can get at it e.g. a NFS or SMB mount. BUT if the server is in a DMZ you'll likely find access to any shared internal file systems and / or permission to store a private key to scp / ssh into your network not available to you, leaving email as the only practical method to send data to yourself or others being.

If the box is performing a non trivial function in the DMZ it's more than likely been hardened to some extent, and all non essential toys removed, so you'll probably find your lacking the likes of uuencode, mmencode, and perl, leaving you none of the standard mechanism to encode and to attach files to email.

You could take the quick and dirty option of just piping the data / log into an email body an hoping Outlook will treat your data kindly, and not assume it's a malicious script, or part of the email header, or in need of some character-set conversion. This approach kept me happy for a number of years, but while working with Rockroads several  year back, I was made aware of plain text mime attachments, and haven't looked back.

Plain text mime encoding attachments offer you the ability to:
Attach CSV, XML or TXT files to a mail,.

To Name the attachments, as they are appear to the recipient.

Allows you to add a BODY to the email, explaining the attachments

Offer a mechanism to specify the encoding bits and character set

Support multiple attachments in a single mail (multi-part mime)

Allow the recipient to simply save an attachments, rather than having to cut-n-paste the data out of the email.

Requires only shell and sendmail to be available to you on the box.

Anyway per the Wikipedia article, all you need to convert a plain old smtp email in to a mime encoded one is a few content type entries, in your message body, define a unique boundary separator (a string that won't appear in your data), and to add a separator and a few more content type entries between your message body and the attachments data, another separator and finally a couple of -- to mark the end of the mail.

So in a few minutes you can replace your boring old mail line in your existing script with something a bit more sophisticated, but as I've found I regularly need to send output to myself I have knocked out a few generic scripts over the years that provide a mechanism to send myself one or more file, or the output from a command.

Basically the script assumes all the command line argument along with any input piped or redirected in are files you want attached to a predefined email, to be sent to a predefined user. If you have a look through the script you'll obviously spot and realise you'll need to tweak some of the entries in the ---Tweak to suit--- block. Other than that the script is much ready to run.

One line possibly worth noting is the following line:

inputMethod=`stat -L -c %F /proc/$$/fd/0`

Open in new window


The output from the stat call, on the current processes standard input [/prod/$$/fd/0], will indicate if a file [regular file] or stream [fifo] have been piped / redirected into the script, then via a couple of additional if, then, fi blocks that input is ALSO attached to the email, permitting the script to be used in-line, anyway the script:
#!/bin/sh
# Purpose: email the parametrised list of files to a set user along with any content piped XOR redirected in.

# ========================
DT=`date '+%Y-%m-%d'`
TMP_FL="/tmp/$0.$$"
MAIL_FL=""
ATTACHMENT=""
MIMETYPE="text/plain"
BOUNDARY=`date +%s|md5sum`
BOUNDARY=${BOUNDARY:0:32}
#----- Tweak to suit -----
MAILTO="To: arober11@somehostorother.com"
FROM="doNotReply@somehostorother.com"
REPLY_TO="doNotReply@somehostorother.com"
SUBJECT_LINE="Files from `uname -a` on $DT"
MSGBODY="Files from `uname -a` on $DT"
#----- CMD locations  -----
sendmail="/usr/sbin/sendmail"
sendmailParms=""
readlinkCMD="/usr/bin/readlink"
statCMD="/usr/bin/stat"
basenameCMD="/usr/bin/basename"
#----- Tweak to suit ends-----

#----- Test if anything has been piped or directed at us -----
inputMethod=`$statCMD -L -c %F /proc/$$/fd/0`

# ========================
# Attach file to msg
# ========================
attach_file() {

  cat >> $TMP_FL << EOF

--$BOUNDARY
Content-Type: $MIMETYPE; name="$MAIL_FL"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="$MAIL_FL"

`cat $ATTACHMENT`
EOF
}

# ========================
# Create tmp msg file
# ========================
create_msg() {

  cat > $TMP_FL <<EOF
From: $FROM
`echo -e $MAILTO`
Reply-To: $REPLY_TO
Subject: $SUBJECT_LINE
Content-Type: multipart/mixed; boundary="$BOUNDARY"

This is a MIME formatted message.  If you see this text it means that your
email software does not support MIME formatted messages, but as plain text
encoded you should be ok, with a plain text file.

--$BOUNDARY
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 8bit
Content-Disposition: inline

$MSGBODY

EOF

  while [ $# -gt 0 ]
  do
    if [ -r $1 -a -f $1 -a -s $1 ]
    then
        MAIL_FL="`$basenameCMD $1`"
        ATTACHMENT="$1"
        attach_file
    fi
    shift
  done

  #See if anything has been piped in via STDIN, if it has add it as another attachment
  if [ "$inputMethod" = "fifo" ]
  then
    cat > "${TMP_FL}.from_pipe.stdin"
    MAIL_FL="STDIN_from_PIPE.txt"
    ATTACHMENT="${TMP_FL}.from_pipe.stdin"
    attach_file
  fi

  if [ "$inputMethod" = "regular file" ]
  then
    cat > "${TMP_FL}.from_fl.stdin"
    flName="`$readlinkCMD \`$statCMD  -L -c %n /proc/$$/fd/0\``"
    MAIL_FL="`$basenameCMD $flName`"
    ATTACHMENT="${TMP_FL}.from_fl.stdin"
    attach_file
  fi

  echo -e "\n--$BOUNDARY--\n" >> $TMP_FL
}

# ====
# Main
# ====
if [ $# -gt 0 -a -f "$1" -a -r "$1" ]
then
  create_msg $@
elif echo $inputMethod | egrep -q "character special"
then
  thisCMD=`$basenameCMD $0`
  echo
  echo "Error: No files passed as arguments, piped in, or re-directed in :("
  echo
  echo "usage:    [|]$thisCMD [<file1.txt> [<file2.txt>*]] [<]"
  echo "Purpose:  email the paramertised list of files, to a set user, along with any content piped XOR redirected in"
  echo "examples: cat file1.txt | $thisCMD"
  echo "                          $thisCMD file1.txt file2.txt"
  echo "                          $thisCMD                     < file1.txt"
  echo "          cat file1.txt | $thisCMD file2.txt"
  echo "                          $thisCMD file1.txt file2.txt < file3.txt"
  exit 1
else
  create_msg
fi

# =================
# Email the file(s)
# =================
$sendmail $sendmailParms -t <$TMP_FL
rm -f $TMP_FL*

Open in new window


Andrew Roberts, Oct 2011
0
Comment
Author:arober11
2 Comments
 

Administrative Comment

by:Eric AKA Netminder
Andrew,

Congratulations! Your article has been published.

ericpete
Page Editor
0
LVL 26

Author Comment

by:arober11
May also be of interest.
0

Featured Post

Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

Join & Write a Comment

Learn several ways to interact with files and get file information from the bash shell. ls lists the contents of a directory: Using the -a flag displays hidden files: Using the -l flag formats the output in a long list: The file command gives us mor…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month