You’d like your script to be able to send email, optionally with attachments.
These solutions depend on a compatible mailer such as mail, mailx, or mailto, an
Message Transfer Agent (MTA) being installed and running, and proper configuration of your email environment.
Unfortunately, you can’t always count on all of that, so these solutions must be well tested in your intended environment.
The first way to send mail from your script is to write some code to generate and send a message, as follows:
1 2 3 |
# Simple cat email_body | mail -s "Message subject" recipient1@example.com recipient2@example. com |
or:
1 2 3 |
# Attachment only $ uuencode /path/to/attachment_file attachment_name | mail -s "Message Subject" recipient1@example.com recipient2@example.com |
or:
1 2 3 |
# Attachment and body $ (cat email_body ; uuencode /path/to/attachment_file attachment_name) | mail -s "Message Subject" recipient1@example.com recipient2@example.com |
In practice, it’s not always that easy.
For one thing, while uuencode will probably be there, mail and friends may or may not, or their capabilities may vary.
In some cases mail and mailx are even the same program, hard- or soft-linked together.
In production, you will want to use some abstraction to allow for portability.
For example, mail works on Linux and the BSDs, but mailx is required for Solaris since its mail lacks support for -s. mailx works on some Linux distributions (e.g., Debian), but not others (e.g., Red Hat).
We’re choosing the mailer based on hostname here, but depending on your environment using uname -o might make more sense.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# cookbook filename: email_sample # Define some mail settings. Use a case statement with uname or hostname # to tweak settings as required for your environment. case $HOSTNAME in *.company.com )MAILER='mail' ;; # Linux and BSD host1.* )MAILER='mailx' ;; # Solaris, BSD and some Linux host2.* ) MAILER='mailto' ;; # Handy, if installed esac RECIPIENTS='recipient1@example.com recipient2@example.com' SUBJECT="Data from $0" [...] # Create the body as a file or variable using echo, printf, or a here-document # Create or modify $SUBJECT and/or $RECIPIENTS as needed [...] ( echo $email_body ; uuencode $attachment $(basename $attachment) ) \ | $MAILER -s "$SUBJECT" "$RECIPIENTS" |
We should also note that sending attachments in this way depends somewhat on the client you use to read the resulting message, too.
Modern clients like Thunderbird (and Outlook) will detect a uuencoded message and present it as an attachment.
Other clients may not.
You can always save the message and uudecode it (uudecode is smart enough to skip the message part and just handle the attachment part), but that’s a pain.
The second way to send mail from your scripts is to outsource the task to cron.
While the exact feature set of cron varies from system to system, one thing in common is that any output from a cron job is mailed to the job’s owner or the user defined using the MAILTO variable.
So you can take advantage of that fact to get emailing for free, assuming that your email infrastructure works.
The proper way to design a script intended to run from cron (and many would argue any script or Unix tool at all) is to make it silent unless it encounters a warning or error.
If necessary, use a -v argument to optionally allow a more verbose mode, but don’t run it that way from cron, at least after you’ve finished testing.
The reason for this is as noted: cron emails you all the output.
If you get an email message from cron every time your script runs, you’ll soon start ignoring them.
But if your script is silent except when there’s a problem, you’ll only get a notification when there is a problem, which is ideal.
Note that mailto is intended to be a multimedia and MIME-aware update to mail, and thus you could avoid using uuencode for sending attachments, but it’s not as widely available as mail or mailx.
If all else fails, elm or mutt may be used in place of mail, mailx, or mailto, thought they are even less likely to be installed by default than mail*.
Also, some versions of these programs support a -r option to supply a return address in case you want to supply one. mutt also has a -a option that makes sending attachments a breeze.
1 |
cat "$message_body" | mutt -s "$subject" -a "$attachment_file" "$recipients" |
mpack is another tool worth looking into, but it is very unlikely to be installed by default.
Check your system’s software repository or download the source from ftp:// ftp.andrew.cmu.edu/pub/mpack/.
From the manpage:
1 2 3 |
The mpack program encodes the named file in one or more MIME messages. The resulting messages are mailed to one or more recipients, written to a named file or set of files, or posted to a set of newsgroups. |
Another way to handle the various names and locations of mail clients is shown in Chapter 8 of Classic Shell Scripting by Nelson H.F.
Beebe and Arnold Robbins (O’Reilly):
1 2 3 4 5 6 7 |
# cookbook filename: email_sample_css # From Chapter 8 of Classic Shell Scripting for MAIL in /bin/mailx /usr/bin/mailx /usr/sbin/mailx /usr/ucb/mailx /bin/mail /usr/ bin/mail; do [ -x $MAIL ] && break done [ -x $MAIL ] || { echo 'Cannot find a mailer!' >&2; exit 1; } |
uuencode is an old method for translating binary data into ASCII text for transmission over links that could not support binary, which is to say most of the Internet before it became the Internet and the Web.
We have it on good authority that at least some such links still remain, but even if you never encounter one it’s still useful to be able to convert an attachment into an otherwise ASCII medium in such a way that modern mail clients will recognize it.
See also uudecode and mimencode.
Note that uuencoded files are about one-third larger than their binary equivalent, so you probably
want to compress the file before uuencoding it.
The problem with email, aside from the differing front-end Mail User Agent (MUA) programs like mail and mailx, is that there are a lot of moving parts that must all work together.
This is exacerbated by the spam problem because mail administrators have had to so severely lock down mail servers that it can easily affect your scripts.
All we can say here is to fully test your solution, and talk to your system and mail administrators if necessary.
One other problem you might see is that some workstation-oriented Linux distributions, such as Ubuntu, don’t install or run an MTA by default since they assume you will be using a full-featured GUI client such as Evolution or Thunderbird.
If that’s the case, command-line MUAs and email from cron won’t work either.
Consult your distribution’s support groups for help with this as needed.