Procmail Howto


Von Andreas Manser (amanser auf trash.net)


Was macht procmail?

Immer wenn ein Email erhalten wird, arbeitet procmail sämtliche Regeln in der Datei .procmailrc (oder anderen rc-files) durch. Es ist so möglich Emails zu sortieren, automatisch zu löschen oder auch automatisch zu beantworten.

Was braucht man dazu?

Procmail ist auf trash.net so eingerichtet, dass es genügt, wenn im eigenen home-directory eine Datei mit dem Namen .procmailrc und das Verzeichniss .procmail angelegt ist. Diese Datei enthält nun die oben erwähnten Regeln. Anlegen des Verzeichnisses: mkdir ~/.procmail Erzeugen der Datei: vi ~/.procmailrc

Grundeinstellungen

Auf den Mailservern sind für Procmail diese Einstellungen vorgegeben und sollten im eigenen .procmailrc nicht umdefiniert werden.

ORGMAIL=$HOME/Maildir/
DEFAULT=$ORGMAIL
MAILDIR=$HOME/Maildir/
VERBOSE=off
PMDIR=$HOME/.procmail
#LOGFILE=$PMDIR/log

So wird der korrekte Umgang auf der neuen Linux-Plattform (ab 30.7.2016) sichergestellt. Keinesfalls soll einfach ein Beispiel auf dem Internet kopiert werden. Für Debuggingzwecke empfiehlt sich diese Zeile zu aktivieren.

LOGFILE=$PMDIR/log

Mails in Ordner verschieben

Procmail kann viel mehr, als nur Spam auszusortieren. Es ist z.B. möglich, Mails in verschiedene Inboxen zu verteilen, nach Headern. Ein Setup, das sämtliche trash.net Listen richtig sortiert, dürfte ungefähr so aussehen. Die Bezeichnung der Mailboxen ist dabei am neuen Maildir Format (ab 30.7.2016) ausgerichtet. Mit dem Punkt am Anfang des Namens erscheinen die Ordner automatisch auch im Webmail.

# sort out pre-tagged listmails
:0
* ^List-Id:.*trash.net.*
* ^X-Spam-Status: Yes
$HOME/Maildir/.caughtspam/

:0
* ^List-Id:.*announce.trash.net.*
$HOME/Maildir/.announce/

:0
* ^List-Id:.*support.trash.net.*
$HOME/Maildir/.support/

:0
* ^List-Id:.*talk.trash.net.*
$HOME/Maildir/.talk/

Wie sind die Regeln aufgebaut?

Die Regeln (auch Filter oder receipe genannt) beginnen immer mit einer Zeile, die in etwa so aussieht:

:0


Der Doppelpunkt und die Null bedeuten nichts spezielles. Darauf folgen die sogenannten Flags (hier keine). Wenn ein weiterer Doppelpunkt folgt (:0 c: ) so heisst dies, dass ein Lockfile benutzt wird. (Das ist vorallem sinvoll, wenn die Regel etwas in eine Datei schreiben soll.)
Nach dieser sogenannten "Collon-Line" (sie beginnt mit einem Collon, sprich Doppelpunkt) folgen meist eine oder mehrere Linien mit Bedingungen. Diese beginnen immer mit einem *. Hier ein Beispiel:

* ^From: .*peter


Das bedeutet, dass für Emails, die den String "peter" im Absender aufweisen die Action-Zeile ausgeführt wird. Die Action-Zeile kann z. B. wie folgt aussehen:

 !hans@somewere.net

In diesem Beispiel werden also alle Emails, die von Peter kommen weitergeleitet zu Hans.

Welche Flags gibt es?

Es gibt folgende Flags: A, a, B, b, c, D, E, e, f, H, h, i, r, W, w Sie können in fünf Gruppen aufgeteilt werden.

So sind h und b dazu da festzulegen, in welchem Bereich der Nachricht die Bedingungszeilen angewandt werden sollen. So steht H für Header und B für Body. Wenn weder H noch B angegeben werden, so wird nur der Header untersucht.

Die zweite Gruppe von Flags, die h und b enthält, gibt an, ob eine Aktionszeile den Header oder den Body der Nachricht als Input erhält. Hier ist der per Default h und b aktiv. Die Flags die zur Ablaufsteuerung eingesetzt werden sind: c, A, a, E, e. Um eine Nachricht zu duplizieren wird das c, für clone, verwenden. Das Flag A bedeutet, dass diese Regel nur angewandt wird, wenn alle Bedingungen der vorhergehenden Regel erfüllt waren. Wenn statt dessen das Flag a verwendet wird, so müssen zusätzlich die Aktionszeilen der vorhergehenden Regel erfolgreich abgeschlossen worden sein. Demgegenüber wird eine Regel mit dem Flag E nur ausgeführt, wenn die Bedingungen der letzten Regel nicht erfüllt wurden. Dann ist da noch e. Es bewirkt, dass die Regel, die es verwendet nur ausgeführt wird, wenn die Bedingungen der vorhergehenden Regel erfüllt wurden, die Aktionen jedoch nicht erfolgreich ausgeführt werden konnten.

Nun folgen die Flags, die Auswirkungen auf die Ausführung der Aktionszeilen haben: f, i, r, W, w. Wenn die Email z. B. an ein Skript übergeben werden soll, so geschieht dies über eine Pipe. Hierzu muss mit dem Flag f procmail mitgeteilt werden, dass es die Nachricht in die Pipe in der Aktions-Zeile "füttern" soll. Wenn man eventuelle Fehler hierbei unterdrücken möchte, so benutzt man dazu das i Flag. Das r Flag hat die Funktion, Verbesserungen die procmail im Normalfall automatisch vornimmt zu unterdrücken. (z. B. das anhängen eines Zeilenumbruches am Schluss der Nachricht.) Wenn man sicher sein möchte, dass eine Aktion abgeschlossen ist, bevor man weiterfährt, so kann man dazu das Flag w benutzen. W unterdrückt zusätzlich eventuelle Fehlermeldungen.

Zum Schluss noch das D Flag. Es teilt procmail mit, dass es grosse und kleine Buchstaben unterscheiden soll (A!=a)

Wie filtere ich Nachrichten einer Mailinglist?

Hierfür gibt es wohl 1001 Lösungen. Hier eine einfache Variante:

 cd ~
vi .procmailrc

das .procmailrc sollte am schluss etwa so aussehen:

 :0
*^TOmeine-mailliste # TO siehe auch "Makros"
$HOME/Maildir/.meine-mailliste/ # wird erstellt, falls noch nicht vorhanden

Beachte den führenden Punkt und den abschliessenden Slash im Namen für die Bezeichnung der Mailbox. Beides ist nötig, damit procmail die Mail im Maildir Format speichert und Dovecot (POP3/IMAP/Webmail) den Ordner anzeigen kann.

Hier ein Beispiel um die Mails der Liste "support@lists.trash.net" zu filtern:

 :0
*^TOsupport@lists.trash.net
$HOME/Maildir/.support/

Wie können mehrere Bedingungen logisch oder verknüpft werden?

Wenn es sich um "einfache" Bedingungen handelt ist dies so möglich:

 * Bedingung1|Bedingung2|Bedingung3

Da das z. B. bei negierten Bedingungen (* ! Bedingung) bereits nicht mehr geht wird wie folgt vorgegangen:

 * 1^0 Bedingung1
* 1^0 ! Bedingung2
* 1^0 Bedingung3

Hier wird die Aktion ausgeführt, wenn entweder Bedingung1 oder Bedingung3 erfüllt sind, oder wenn Bedingung2 nicht erfüllt ist.

Wie Kann ich eine Mail automatisch beantworten?

Hierbei ist grosse Vorsicht geboten, damit nicht Loops entstehen!

 SENDMAIL=/usr/lib/sendmail # Pfad des MTA angeben, wird anstelle von $SENDMAIL eingesetzt
:0 f # colon-line
* !^From +YOUR_USERNAME # verhindern von Schleifen
* !^Subject:.*Re: # nur auf "neue" Anfragen antworten
* !^FROM_DAEMON # siehe "Makros"
* ^Subject:.*retrieve_afile # wenn das Mail "retrive_afile" in der Betreff-Zeile hat:
| (formail -r ; cat afile) | $SENDMAIL -oi -t # afile zurücksenden

Ein weiteres Beispiel:

 FORMAIL=/usr/bin/formail
SENDMAIL=/usr/lib/sendmail

# send a vacation style mail

:0 Whc : $HOME/.procmail/vacation.lock
* !^X-Loop: someone@somewhere.net
* !^FROM_DAEMON
| $FORMAIL -trD 2048 $HOME/.procmail/vacation.cache # save the sender to a cache

:0 ehc # if the sender was not in the cache
| ($FOREMAIL -trA"Precedence: junk" \
-A"From: Your Name (via the vacation program) " \
-A"X-Loop: someone@somewhere.net" \
-a"Subject: Re: your mail" ; \
cat $HOME/.procmail/vacation \
) | $SENDMAIL -oi -t -fsomeone@somewhere.net

der gewünschte Text kann nun in der Datei ~/.procmail/vacation gespeichert werden

Wie kann ich den Empfang doppelter Nachrichten verhindern?

:0 Wh : msgid.lock
| formail -D 8192 msgid.cache

Dieses Filter sollte ganz am Anfang von .procmailrc stehen.

Wofür sind denn die {} Klammern?

Die Klammer { kennzeichnet den Beginn eines Blocks. Sie muss von mindestens einem Leerschlag, einem Tab oder einem Zeilenumbruch gefolgt werden. Alles was nun folgt (bis zur nächsten schliessenden Klammer) folgt wird nur ausgeführt, wenn die Bedingungen dieses Filters erfüllt werden. Blocks können auch beliebig ineinander Verschachtelt werden.

Was bedeuten ^TO ,^TO_, ^FROM_DAEMON und ^FROM_MAILER?

:0
* ^Subject: send file [0-9a-z]
* !^X-Loop: yourname@your.main.mail.address
* !^Subject:.*Re:
* !^FROM_DAEMON
* !^Subject: send file .*[/.]\.
# Nur wenn alle Bedingungen erfüllt sind wird der Block abgearbeitet

:0 fhw # reverse mailheader and extract name
* ^Subject: send file \/[^ ]*
| formail -rA "X-Loop: yourname@your.main.mail.address"
FILE="$MATCH" # the requested filename
{
:0 ah
| cat - ./$FILE 2>&1 | $SENDMAIL -oi -t
}

Das sind so genannte Makros. Wenn sie vorkommen, so werden sie von procmail durch eine jeweils ziemlich lange regex ersetzt. Die Makros ^TO und ^TO_ dienen jeweils dazu eine spezifische Adresse (TO_) oder ein spezifisches Wort (TO) in den Zeilen, die den Empfänger angeben. Sie unterscheiden sich nur [^a-zA-Z] und [^-a-zA-Z0-9_.], was etwa heisst, dass bei TO im entsprechenden Teil nur Buchstaben nicht zugelassen sind, bei TO_ jedoch auch Zahlen, -, _ und Punkt. Das FROM_DAEMON Makro dient dazu, möglichst alle Nachrichten zu finden, die von einem Mail-Daemon (wie z. B. von Mailinglisten eingesetzt werden) stammen zu filtern. FROM_MAILER ist nur eine etwas verkleinerte version von FROM_DAEMON.

Wie kann ich Spam filtern?

Wenn Du einen Account auf trash.net hast, hilft der Artikel zu SPAM.

Wie teste ich mein .procmailrc ohne Emails zu verlieren?

Da gibts einen ganz netten Trick auf den mich Beat hingewiesen hat: Man speichere die zu Testenden recipes in einer Datei, die man z. B. testing.rc nennt. Sie kann in etwa so aussehen:

 MATCHFOLDER=$HOME/testing.matched # Hier werden die "erwünschten" mails gespeichert
DEFAULT=/dev/null # was nicht gespeichert wird, verwschwindet im Nix

:0
* ^From: .*peter # Alle Emails, die von peter kommen
$MATCHFOLDER # sollen hier gespeichert werden
# Hier folgen evtl. weitere Filter

nun kann in der Shell folgende Zeile eingegeben werden:

 formail -s procmail -m testing.rc < ~/a_mbox

Formail teilt nun die Mailbox (hier a_mbox) in einzelne Nachrichten auf und füttert diese an procmail, welches explizit die Datei testing.rc als "Filter-Datei" verwendet. Alle Mails, die vom einem recipe bearbeitet werden, sollten nun in den entsprechenden Dateien gelandet sein.

Weitere Infos: man procmailrc, man procmailex