Go to the previous section

Writing the Rules

The language for writing filter rules is pretty simple, actually. The fundamental structure is:
       if  (condition)  then  action
Where condition is constructed by an arbitrary number of individual conditions of the form "field relation value" (an optional further type of rule is of the form "always action" but should only be used as the last rule in the ruleset, for obvious rea sons). The field value can be:
       subject
       sender
       from
       to
       lines
For the field lines, the relation can be any of the standard relationships ('>', '<', '>=', '<=', '!=' and '='). contains is equivalent to the relation '=' or you can skip the relationship entirely (e.g. "subject = "joe"", "subject contains "joe"", and "subject "joe"" are all equivalent). The value is any quoted string that is to be matched against or a number if lines is the field being considered.

The relation matches (or '~') takes an egrep like regular expression as the value. The regular expression must be enclosed in pairs of '/'. If you need a '/' in your expression write it as "\/".

Individual conditions are joined together by using the word and, and the logic of a condition can be flipped by using not as the first word (e.g. "subject "fun" and not subject "games""). We'll see more examples of this later.

Note that the "or" logical conjunction isn't a valid part of the filter conditional statement.

Finally, action can be any of:

Action Description delete Deletes the message save < foldername > Saves a copy of the message in the specified foldername. savecopy < foldername > Does the same as save, but also puts a copy in your mailbox. forward < address > Sends the message to the specified address. forwardc < address > Sends the message to the specified address and leaves a copy in your mailbox. execute < command > Feeds the message to the specified command (or complex sequence of commands) as standard input. executec < command > Like execute but also leaves a copy in your mailbox. leave Leaves the message in your mailbox.

Note that the execute command assumes that you are doing something useful with incoming mail. The command does not automatically append the message to your mail spool. Use executec for that. A command such as:

       if (from = "dave") then execute "echo mail from dave > /dev/tty"
will result in losing your mail. A more suitable use for execute would be:
       if (from = "boss") then execute "vacation pat"

Foldernames can contain any of a number of macros, too, as we'll see in the example ruleset below. The macros available for the string fields are:

Macro Meaning %d day of the month %D day of the week (0-6) %h hour of the day (0-23) %m month of the year (1-12) %r return address of message %s subject of original message %S "Re: < subject of original message >" %t current hour and minute in HH:MM format %y year (last two digits) %& the string that matched the last regular expression %1-%9 the corresponding subexpression in the last regular expression that matched

If a message has a subject of "This is a test", and the rule is

        if (subject matches /([a-z]+) a ([a-z]+)/) then "echo %& %1 %2"
then %& expands to "is a test", %1 expands to "is" and %2 expands to "test". Foldernames may contain a leading "~/" which expands to your home directory. The rules file can also contain comments (any line starting with a '#') and blank lines. Metacharacters may be escaped by a preceding '\' to remove any special meaning. If you need a '%' character as part of an argument (such as an address), use "\%". If you need a double quote in a double quoted string, use "\"". If you need a single quote in a single quoted string, use "\'". If you need a backslash in any kind of string, use "\\". Unless you specify an alternate file via the -f option, the rules file needs to reside in your .elm directory off your home directory and be called .elm/filter-rules. Here's an example: # $HOME/.elm/filter-rules # # Filter rules for the Elm Filter program. Don't change without some # serious thought. (remember - order counts) # # (for Dave Taylor) # rule 1 if (from contains "!uucp") then delete # rule 2 to "postmaster" ? save "/tmp/postmaster-mail.%d" # rule 3 if (to "culture" and lines > 20) ? save "~/Mail/culture" # rule 4 subject = "filter test" ? forward "hpldat!test" # rule 5 if [ subject = "elm" ] savecopy "~/Mail/elm-incoming" # rule 6 subject = "display-to-console" ? execute "cat - > /dev/console" (Notice the loose syntax - there are lots of valid ways to specify a rule in the filter program!!)

To translate these into English:

  1. All messages from "uucp" should be summarily deleted.

  2. All mail to "postmaster" should be saved in a folder (file) called /tmp/postmaster-mail.n, where n is the numeric day-of-the-week.

  3. All mail addressed to "culture" with at least 20 lines should be automatically appended to the folder $HOME/Mail/culture.

  4. All messages that contain the subject "filter test" should be forwarded to me, but via the address "hpldat!test" (to force a non-user forward).

  5. All messages with a subject that contains the word "elm" should be saved in the folder $HOME/Mail/elm-incoming and also dropped into my mailbox.

  6. Any message with the subject "display-to-console" will be immediately written to the console.

Notice that the order of the rules is very important. If we, for example, were to get a message from "uucp" that had the subject "filter test", the filter program would match rule 1 and delete the message. It would never be forwarded to "hpldat!test". It is for this reason that great care should be taken with the ordering of the rules.

Go to the next section