E-mail as a System Console, Part II

by Michael Schwarz, Curtis

Editors' Note: The following is a chapter from the book Multitool Linux, written by Michael Schwarz, Jeremy Anderson, Peter Curtis and Steven Murphy. Consult the book's web site for links, updates and errata.

In Part I of this article, I described the impetus for this project, devising a way to remotely access my home system so I could control internet connection times. Now let's get into what this system involves.

Fetchmail

Fetchmail is one of those handy tools that makes using an operating system like Linux so much fun. It's easy to configure, has lots of functionality, and it does what you want, when you want, without much complaining. You can run it from cron or from the command line. If life could only be so easy.

For the e-mail console, you use fetchmail to retrieve e-mail from your ISP. This means you have to switch your current e-mail client from using POP/IMAP to picking up e-mail locally. Why do you have to do this? Well, when the MDA on your system wants to send e-mail to your account, it first checks to see if a file named .forward is in your home folder. If it is, all your mail is forwarded to the e-mail address in the .forward file. But wait! We don't want that to happen. What we want is the e-mail to be sent to procmail for processing. You'll learn how to do this in the next section. For now, remember the .forward file is the key.

Fetchmail Configuration

Configuring fetchmail is a breeze. All you need to do is create a .fetchmailrc file in your home folder. You can read the man page for fetchmail and write this file yourself, or you can use fetchmailconf and generate the .fetchmailrc file. I wrote my original configuration file by hand, but the fetchmailconf application is a much faster way to get things going.

Here's a screenshot where I'm adding a new remote e-mail server.

Figure 1. Fetchmail Config, New E-mail Server

Here's a screenshot where I'm setting up the server protocol and adding a new e-mail account.

Figure 2. Fetchmail Config, Protocol Setup

Finally, here's a screenshot where I'm configuring the e-mail account password and setting up the processing options.

Figure 3. Fetchmail Config, Account Setup

Once fetchmail is configured and working, you can run it from the command line or via cron.

Figure 4. Fetchmail Being Executed

This screen shows that fetchmail got a single e-mail from my ISP and then flushed (removed) it from my ISP. When you want to automate the fetchmail process, use cron to schedule a fetchmail call and make sure you use the silent (-s) command-line parameter; otherwise, you'll be getting lots of messages from cron each time fetchmail is run.

Crontab

In order to make the e-mail console work, you must run fetchmail at regular intervals. Cron is usually a good way to go about doing this. Here's a sample crontab entry:

  0,15,30,45 * * * * /usr/bin/fetchmail
Procmail

Here's where it really starts to gets interesting. Procmail is the tool that makes the e-mail console possible. It scans a text file (your e-mail file, which is one giant file when it comes from your MDA) looking for patterns you specify, and then it performs some kind of action that you specify on a particular e-mail within the file. You see, procmail understands how to read this giant e-mail file and can perform an action either on the text itself or an action in general. For instance, you might have procmail scan incoming e-mail, and for each subject line have it execute a text-to-speech program so it reads each subject to you when new e-mail arrives. Kind of cool, right?

Our use of procmail involves scanning the subject lines of each e-mail looking for a given pattern that indicates the body of the e-mail holds a command sequence to be executed and the output captured and sent back to the sender of the e-mail. You also could have procmail react to the sender's e-mail address, but this is not as flexible. There are better ways to lock things down, as you will see in a while. So the big question you should have now is, "How do I tell procmail to scan my e-mail and do something?" Easy! You create a recipe for procmail.

Recipes

A recipe is how you tell procmail what to search for and what to do when it finds something. A recipe is the heart of procmail. You create a recipe for each type of thing you want to search for or an action you want to perform. There are many good resources on the Internet for creating recipes, and your best bet is to start at the procmail web site.

So where do you put your recipes once they're created? You put them in your home folder in a file named .procmailrc, of course. Here is a beginning .procmailrc with two recipes:

     01 #---------------
     02 # my .procmailrc file
     03 #----------------
     04 SHELL=/bin/bash  # path to your sh (try "which sh" to find it)
     05 MAILDIR=${HOME}/Mail # e-mail goes here after your client gets it
     06 LOGFILE=${MAILDIR}/procmail.log
     07 LOG="--- Logging ${LOGFILE} for ${LOGNAME}, "
     08
     09 #-------------------------------------
     10 # Your recipes (the order is extremely important!!!!
     11 #-------------------------------------
     12 :0
     13 * ^Subject: test test test
     14 /dev/null
     15
     16 #------------------------------
     17 # Accept all the rest to your default mailbox
     18 #------------------------------
     19 :0:
     20 ${DEFAULT}

I stuck the line numbers in so I can reference each important line for this example. You should not put line numbers in your file, because they would really hose things up. Lines 04 through 07 are fairly obvious, so just follow the comments. Lines 12 through 14 make up the first recipe, which searches for the string "Subject: test test test" at the beginning of a line.

Remember, all your e-mails get sent to procmail as one giant file, but procmail knows how to logically break up the file into each message and check for whatever pattern you provide. In this case, line 13 is the pattern you want to search for. The ^ at the beginning means the string of text you are looking for must be anchored at the beginning of the line. Line 14 directs procmail to send the matching e-mail to the digital garbage can, black hole or bit bucket, if you prefer. Each e-mail is passed from the first recipe to the next until a match is made.

If you haven't already figured it out, the search criteria is a regular expression. If you know regular expressions, then you already know how to enter a search string for any text you want to search for. If you don't know how to write regular expressions, then I highly recommend reading up on them. They are powerful and are used in many of the best tools available for Linux.

Line 14 instructs procmail to take the e-mail where the regular expression matches and sends it to the null device. In other words, it copies the text to null device and removes it from the e-mail file. Can you say, "spam filter"? I can think of a few rules to filter out unwanted e-mails. Of course, there are numerous examples on the Internet of spam filters for procmail--do a search on Google.com for them.

Another good use for procmail is to direct e-mail from various e-mail lists into their own e-mail subfolder in your e-mail folder. This is beyond the scope of this article, but you can experiment and read some FAQs to get the answers on how to achieve this functionality.

The next recipe is probably the most important recipe of them all. The second recipe on lines 19 and 20 is the catch all-recipe for any e-mail not already processed. When I wrote my first .procmailrc file, I neglected to include this recipe and my e-mail simply went away. Don't make this mistake.

This last recipe tells procmail to put all e-mail not caught by previous recipes into your normal mailbox location (/var/mail/your_account). Wait. I thought it was in my Mail folder in my home folder? Nope. You see, when fetchmail picks up the e-mail from your ISP and delivers it to your MDA. Your MDA looks for a .forward file before writing the e-mail to the /var/mail/your_account file. The .forward file tells your MDA to send the incoming e-mail to the address within. The neat thing is that you can also pipe the e-mail to a program such as procmail.

Procmail acts as a filter and has the ability to remove e-mail from the giant e-mail file. Once procmail is done with it, the e-mail not filtered out goes to /var/mail/your_account, where your normal e-mail client can pick it up.

I'll talk more about the contents of the .forward file in [Part III]. So what's all that other stuff, like :0, *, :0:>, and ${DEFAULT} all about? Here's a table that should sort it all out for you:

      __________________________________________________________________
     |__________________________________________________________________|
     |          |Begin a recipe and use a lock file. Use a lock file to |
     |          |prevent multiple procmails from trying to write to your|
     |:0:       |mail file at the same time. (From the procmail FAQ:    |
     |          |"Rule of thumb: Use file locking when delivering to a  |
     |          |file. Don't use file locking when delivering to /dev/  |
     |__________________________________________________________________|
     |__________________________________________________________________|
     |${DEFAULT}|This is your default e-mail location (/var/mail/        |
     |__________________________________________________________________|
     |__________________________________________________________________|

So filtering e-mail is great and all, but what about executing commands? No problem! Procmail has support for that too, and it even can execute scripts. The recipe I use for the e-mail console is as follows:

     :0
     * ^Subject: <console/>
     |/usr/bin/perl /home/stmurphy/bin/e-mail_console.pl

For our e-mail console recipe, we want to look for a pattern in the subject line that indicates the e-mail contains a command to be executed and its output returned to the sender. The best way to parse this e-mail and execute those commands is to write a Perl script and have procmail execute the Perl script, passing the entire e-mail to the script. It's important to do for security reasons. You should notice that I am putting the e-mail_console.pl script in a folder named "bin" in my home folder. This is a convenient place to put stuff I want executed by my account only.

In Part III, we'll take a look at the Perl script.

Copyright 2002 by Addison-Wesley. All rights reserved. Reproduced by permission of Pearson Education, Inc.

Load Disqus comments