Automatic email forwarding
Well I got fed up with email filter rules last week, and this is the rather bizarre result: autoforward, a Perl script and configuration file that will automatically generate Exim filter files (.forward files), mainly to be used on my University account. My email processing rules have become pretty complex and messy, making them difficult to control, and there’s a lack of uniformity about them. I decided there had to be a better way, so set about writing a configuration format and parser… and I think I succeeded.
The configuration file format is pretty simple. There are some global options that must be set, and then sections named after the directory to which they filter mail. These sections then contain some (optional) meta-actions (e.g. automatic archiving by date or automatic reply), one or more matching rules (i.e. how to decide if an email message should be processed by this rule) and then zero or more actions to be taken (the default being “save to the given folder and stop processing”). Let’s take a look at a (very simple) example:
[!GLOBAL!] mail-root = "IMAP" errors-to = "errors" vacation-level = 0 vacation-alias = [email protected] [email protected] vacation-msg = $home/vacation/message vacation-log = $home/vacation/log vacation-once = $home/vacation/once vacation-repeat = 2d archive-path = "IMAP/archive/$1/" [spam] group header X-Spam-Flag == "YES" header Subject =~ "^((my|new)s)?PH[a-z]*A?[a-z]*R[a-z]*MA" header Subject =~ "^ME[a-z]*DS" endgroup and !anydomain "my\.university\.ac\.uk" [!UNDELIVERED!] @ARCHIVE INBOX @VACATION 4 saveto .email
Wow. What the hell does that all mean? Allow me to explain.
The first part deals with global settings, including:
- The root directory that mail should be stored in
- The directory that error messages should be stored in
- The current “vacation level” and other settings related to it (see later)
- The directory that automatic archive copies should be stored in (see later)
After that follows a filter rule for email to be put into /spam. I first create a nested rule that checks if the X-Spam-Flag header is set to “YES” or the subject matches one of two patterns that came up very frequently for a while. It then also checks against bizarre false positives by ensuring that the “from” domain does not match my university’s domain (or any of its subdomains, like [email protected]). Sadly, Exim is very strange about its quoting rules, and that is the reason for the multiple backslashes. Maybe that will be tidied in a future release 🙂
The final rule deals with any email that hasn’t been delivered yet, and is a special rule (as evidenced by the exclamation marks and capital letters). This rule contains two meta-actions. The first tells it to automatically archive email by date to IMAP/archive/yyyy-mm/INBOX. The next meta-action says that if the “vacation-level” variable is 4 or higher and the email was sent directly to me, automatically reply to the sender. Finally, there’s an actual action that causes the email to be saved to my .email file.
For the curious, this turns out to be something like the following, when run through autoforward:
# Exim filter <<== do not edit or remove this line!if error_message then save IMAP/errors finish endif add 0 to n0 ############################################################ ## Dir: spam ############################################################ if ( $h_X-Spam-Flag: is "YES" or $h_Subject: matches "^((my|new)\s)?PH[a-z]*A?[a-z]*R[a-z]*MA" or $h_Subject: matches "^ME[a-z]*DS" ) and foranyaddress $h_From:,$h_Reply-To: ($thisaddress does not match "@([^@]+.)?my\\.university\\.ac\\.uk") then save IMAP/spam finish endif ########### ## INBOX ## ########### if not delivered then if $tod_log matches "^(....-..)" then save IMAP/archive/$1/INBOX endif if personal alias [email protected] alias [email protected] and $n0 is above 3 then mail to $reply_address subject "Re: $h_subject:" expand file $home/vacation/message log $home/vacation/log once $home/vacation/once once_repeat 2d endif save .email finish endif
So, if you want to try it, see the attached script and example files, as there’s much more you can do with it!
To run the script, you should type something like:
autoforward.pl < ~/autoforward.conf > ~/.forward
Leave a Reply