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 user@putorius.net with a subject line of "Log File".
mailx -a backup.log -s "Log File" user@putorius.net < /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" user@putorius.net < 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?).