When working with scripts, especially scheduled jobs, I often like to get an email with the output. This allows me to be alerted when a job completes, or if it fails. In this Linux quick tip we will discuss sending email from the command line. Specifically, how to send the contents of a file as an email attachment as well as sending contents of a file in an email body.

Before we get started, it is imperative that you have a correctly configured SMTP service running on your system. Postfix is the default SMTP server for most Linux systems. For information on configuring Postfix to send mail through your ISP SMTP (or any SMTP) server read "How to Send Mail Through ISP SMTP with Postfix".

Installing mailx Utility

The mailx utility is what we will be using to send mail from the command line. Any package manager is capable of easily installing the mailx.

Install mailx using Yum

sudo yum install mailx -y

Using dnf to install mailx

sudo dnf install mailx -y

Install mailx with apt-get

sudo apt-get update 
sudo apt-get install heirloom-mailx

Sending File as an Attachment from Command Line

To send an attachment with mailx we need to use the -a (attachment) option. The syntax is pretty straight forward. Let's look at an example, then we will break down each part of the command.

In the following example we will be sending "backup.log" as an attachment to [email protected] with a subject line of "Log File".

mailx -a backup.log -s "Log File" [email protected] < /dev/null
 Null message body; hope that's ok

First we call the mailx utility and pass it a few options. The -a option is followed by the filename of the attachment. This can include a path if it is not in the current working directory. Then we pass the -s option to set the subject line of the email. We then specify the email address to which the email is being sent. Lastly, we redirect /dev/null (nothing) as the body of the email. If we did not do this, mailx would wait for input from STDIN followed by a CTRL+D (end of file) signal. This is why you see the "Null message body" output. Mailx is telling us that we sent the email without any body text.

Sending a File Contents as Email Body from the Command Line

Conversely, if we wanted to send a file as the body of an email we would redirect the file into the mailx command and omit the attachment.

mailx -s "Log File" [email protected] < backup.log

This time we call the mailx utility to start the email. We pass the -s option to set the subject line. Then we supply the email address we are sending the email to. Now we redirect the file into the body of the email.

NOTE: Using this command you will no longer get the "Null message body" warning. This is because we now supplied text (via redirection) to be used as the body.

Working Around Carriage Returns

A file with carriage returns (^M) will often get encoded in such a way that it is sent as an attachment. I ran into this when I was running a script that used SCP to transfer files. The SCP command outputs transfer percentages on the same line, resulting in weird lines with carriage returns. If you come across this, it is easy enough to use the tr command to replace them with newline characters.

tr '\r' '\n' < backup.log > backup.log.clean

Now you can send the backup.log.clean as the body.

NOTE: To see if your file has carriage returns you can use cat with the -v option.

cat -v backup.log
1:30:18 ETA^Cdebug1: channel 0: free: client-session, nchannels 1^M^M
 debug1: fd 0 clearing O_NONBLOCK^M^M
 Killed by signal 2.^M^M

Conclusion

Sending mail from the command line is made simple with the mailx utility. Once you have postfix configured you are on your way. You can use mailx in conjunction with an exit trap in bash scripts to ensure you get notified no matter the outcome of the script (stopped in the middle?).

Resources and Links: