Procmail-FAQ

1. Zu diesem FAQ

Ich hatte lange Zeit das Problem, dass ich beim Ändern der Filter grundsätzlich entweder riesige Anleitungen oder nichtsnutzige Webseiten lesen musste. Das Problem ist, dass entweder jeder einzelne Parameter beschrieben wird (viel zu komplex) oder eben wichtige Regeln fehlen oder nicht ausreichend erklärt werden. Ich habe mir hier die Mühe gemacht, die wichtigsten Punkte in Deutsch zusammen zutragen. Mit diesen Informationen dürften die meisten Standard-Fälle lösbar sein.

Übrigens, ich wurde darauf hingewiesen, daß ich die Themen nicht in der korrekten Reihenfolge nenne. Ich möchte dazu sagen, daß ich dies als FAQ verstehe, nicht als Ersatz für eine vernünftige Anleitung.

2. Weitere Informationen

Sollten die Informationen in diesem FAQ nicht genügen, so stehen die MAN-Pages (man procmail, man procmailrc, man procmailex) zur Verfügung. Weiterhin gibt es eine Vielzahl von Websites, die sich mit dem Problem ProcMail beschäftigen.

3. Was ist ProcMail?

ProcMail ist ein eMail-Filter. Alle für Ihren Account ankommenden Nachrichten werden durch den Filter geschickt, sofern es installiert und korrekt konfiguriert ist. Hier lassen sich die Nachrichten entsprechend der Filterregeln weiterleiten, löschen, beantworten oder zustellen.

4. Was ist ein Receipe?

Ein Receipe definiert eine oder mehrere Bedingungen und eine oder mehrere Aktionen, die ausgeführt werden, wenn die Bedingung erfüllt ist. Als Beispiel sei genannt: „Wenn der Empfänger xyz@abc.de ist (=Bedingung), dann lösche diese Nachricht (=Aktion)“.

Werden mehrere Bedingungen angegeben, so wird die Aktion ausgeführt, wenn alle angegebenen Bedingungen erfüllt sind. Um jedoch nicht in eine für viele unverständliche Fachsprache zu verfallen, werde ich in diesem FAQ Receipes einfach als Filterregel bezeichnen.

5. In welcher Datei stehen die Filterregeln?

Im Home-Verzeichnis des entsprechenden Users muss die Datei .procmailrc angelegt werden. In dieser Datei werden die Filterregeln für diesen Benutzer angelegt. Damit dies funktionert, darf weder das Homeverzeichnis (in dem sich die .procmailrc befindet), noch die Datei .procmailrc selbst für andere (Group/Others) beschreibbar sein, sonst wird die Datei von Procmail abgelehnt. Schließlich kann eine von fremden editierbare Datei genutzt werden, um eMails abzufangen.

Haben Sie eine Domain mit Catch-All, so kommen also alle eMails in Ihr Postfach, damit sind die Filterregeln für alle gültig. Legen Sie jedoch weitere Benutzer an, so hat jeder Benutzer ein eigenes Home-Verzeichnis und ein eigenes Postfach. Damit gelten Ihre Regeln für den Benutzer nicht, da er selbst seine Regeln in der Datei .procmailrc in seinem Home-Verzeichnis festlegen muss.

Bei einigen Providers ist Procmail zwar installiert, doch läßt sich aufgrund des Umstands nicht nutzen, daß man nicht in die Home-Verzeichnisse der Mail-User kommt. Beispiel: Der Kunde hat einen Account mit dem Namen „kunde123“, während seine Mail-Accounts unter „kunde123p1“, „kunde123p2“, … gespeichert sind. Da der Kunde keinen direkten Zugang zum Home-Verzeichnis von kunde123p2 hat, kann er für diesen auch keine Filer
erstellen.

6. Kann ich meine Regeln kommentieren?

Alle Zeilen, die mit einer # beginnen werden von ProcMail ignoriert. Damit ist es möglich, Kommentare in der Regeldatei zu vermerken.

7. Wie lege ich eine Filterregel an?

Eine Filterregel beginnt immer mit :0 eventuell gefolgt von Flags. Danach kann eine oder mehrere Bedingungszeilen folgen. Wird keine Bedingungszeile angegeben, so trifft diese Regel auf alle Nachrichten zu. Die letzte Zeile ist die sog. Action-Line, hier wird angegeben, was mit der Nachricht passieren soll, wenn die Regel auf diese Nachricht zutrifft.

8. Was sind Flags?

Nur die wichtigsten Flags werden hier genannt. Bitte beachten Sie, dass die Gross / Kleinschrift eine Rolle spielt.

  H
  Die Regeln gelten für den Header der Nachricht (Standart)

  B
  Die Regeln gelten für den Body (eigentliche Nachricht)

  D
  Unterscheide zwischen Gross- und Kleinschreibung

  c
  Erzeugt eine Kopie der Nachricht. Die Regel wird auf die
  Kopie der Nachricht angewendet, die Orginalnachricht wird
  zugestellt (sofern nicht eine folgende Regel dies
  verhindert).

9. Wie sehen Bedingungszeilen aus?

Enthält eine Filterregel keine Bedingungszeile, so gilt die Regel für alle Nachrichten. Andernfalls beginnt die Regel mit einem Stern. Danach folgt eine Bedingung. Hierbei gelten folgende Sonderzeichen:

^
Anfang der Zeile

$
Ende der Zeile

. (Punkt)
Ein beliebiges Zeichen, ausgenommen eine neue Zeile

*
Das vorhergehende Zeichen kommt 0 mal oder öfter vor. Beispiel:
x* heisst also, dass entweder kein Zeichen oder ein oder
mehrere x?en vorkommen dürfen.  

+
Wie der Stern, jedoch muss mindestens ein Zeichen vorkommen
(nicht keines). 

?
Wie der Stern, jedoch muss entweder ein oder kein Zeichen
vorkommen (nicht mehrere). 

[a-x]
Es darf ein Buchstabe zwischen a und x vorkommen. In
Kombination mit dem Pluszeichen [a-z]+ erwartet diese Bedingung
also ein oder mehrere Zeichen des Alphabetes.  

[a-z]*
Praxisbeispiel: Es dürfen beliebig viele Buchstaben vorkommen

[a-z]+
Praxisbeispiel: Es dürfen beliebig viele Buchstaben, mindestens
jedoch ein Buchstabe vorkommen

abc|de
Diese Bedingung besagt, dass entweder die Zeichenfolge abc oder
die Zeichenfolge de vorkommen muss. 

(abc)*
Besagt, dass keinmal, einmal oder mehrmals die Zeichenfolge abc
vorkommen muss (in der Praxis ein eher unübliches Beispiel). 

!
Ein Ausrufezeichen vor einer Bedingung kehrt diese um. Sie ist
also dann erfüllt, wenn die nachfolgende Bedingung nicht
erfüllt ist.

10. Wie wendet man diese Bedingungen in der Praxis an?

Sie prüfen üblicherweise den Header der Nachricht auf das Vorkommen bestimmter Zeilen. Möchten Sie also eine Bedingung erstellen die dann erfüllt sein soll, wenn der Absender xyz@abc.de war, so sehen sie sich erst einmal eine Nachricht an. Hier werden Sie eine Zeile im Kopf finden, der etwa so aussieht:

  From: Hans Mustermann <xyz@abc.de>

Damit sollte Ihre Bedingung klar sein. Sie suchen ein FROM am Zeilenanfang, dann beliebig viele Zeichen gefolgt von der gesuchten eMail-Adresse. Alle Zeichen nach der eMail-Adresse interessieren nicht mehr, da die Regel hier bereits erfüllt ist.

  Zeilenanfang: ^
  Was ist zu Suchen in der neuen Zeile: From
  Keines, eins oder mehrere beliebige Zeichen: .*
  Die gesuchte eMail-Adresse: xyz@abc.de

  Die fertige Regel: ^From.*xyz@abc.de

Suchen sie eine Bedingung für alle Nachrichten, die nicht an Sie (mustermann@provider.de) gesendet wurden, so benutzen Sie diese Bedingung: Am Zeilenanfang muss To stehen, dann beliebige Zeichen gefolgt von Ihrer eMail-Adresse, jedoch darf diese Regel NICHT zutreffen. Die Bedingung lautet also:

  !^To.*mustermann@provider.de

11. Besondere Zeichen in der Regel

Mit den Zeichen < und > können Sie prüfen, ob eine Nachricht grösser oder kleiner als die angegebene Zahl ist. Somit besteht zum Beispiel die Möglichkeit, dass alle Nachrichten grösser als 20 MB automatisch gelöscht werden und der Absender eine Nachricht zurück bekommt. Dies ist sinnvoll, wenn Ihr Plattenplatz begrenzt ist.

12. Was passiert nun mit meiner Nachricht weiter?

Das hängt davon ab, welche Action-Line Sie angeben. Die Action-Line ist die letzte Zeile einer Regel. Hier geben Sie an, was mit der Nachricht geschehen soll, natürlich nur, wenn die vorhergehende Regel zutrifft. Folgende Möglichkeiten ergeben sich hier:

  mailboxname
  Geben Sie einfach nur einen Mailboxnamen ein, so wird diese
  Nachricht in der betreffenden Mailbox abgelegt.

  /pfad/dateiname
  Die Nachricht wird in der angegebenen Datei gespeichert.
  Existiert die Datei schon, so wird die Nachricht an die Datei
  angehängt.  

  ! email@adresse.de
  Die Nachricht wird an die angegebene eMail-Adresse
  weitergeleitet. Beachten Sie aber, die Nachricht nicht an
  eine Adresse zu Ihrem Postfach zu leiten, sonst senden Sie
  die Nachricht dauerhaft im Kreis.   

  | Programmname
  Die Nachricht wird an das genannte Programm übergeben.
  Erläuterungen siehe nächste Frage.

  { ... }
  Alle Befehle zwischen den Klammern werden ausgeführt. Dies
  entspricht einem Unterprogramm.

13. Wozu andere Programme?

2 weitere, oft in diesem Zusammenhang benötigten Programme sind Formail und Sendmail. Formail dient zur Bearbeitung der Header einer Nachricht. Dadurch lassen sich Antwortnachrichten generieren. Sendmail dient zum Versenden von eMails. Ich möchte hier lediglich die allerwichtigsten Parameter nennen.

13.1. Formail

  -r
  Erstellt aus dem übergebenen Header einen Antwort-Header
  (Reply). 

  -t
  Formail vertraut dem Absender, dass seine eMail-Adresse im
  FROM-Feld richtig eingetragen ist. 

  -a Kopfzeile
  Die angegebene Kopfzeile wird der Nachricht angefügt, jedoch
  nur, wenn eine entsprechende Kopfzeile noch nicht existiert.

  -A Kopfzeile
  Die angegebene Kopfzeile wird der Nachricht angefügt, auch
  wenn eine entsprechende Kopfzeile bereits existiert.

  -i Kopfzeile
  Die angegebene Kopfzeile wird der Nachricht angefügt.
  Existiert eine entsprechende Kopfzeile schon, so wird Sie
  umbenannt in "Old-.....".  

  -I Kopfzeile
  Die angegebene Kopfzeile wird der Nachricht angefügt.
  Existiert eine entsprechende Kopfzeile schon, so wird Sie
  einfach gelöscht.

13.2. Sendmail

  -Btyp
  Typ kann 7BIT oder 8BITMIME sein. Hiermit wird der Typ der
  Nachricht festgelegt. 

  -hx
  Mit dem h-Parameter legen Sie die Anzahl der Hops fest, die
  eine Nachricht zurücklegen darf, bevor sie mit einer
  Fehlermeldung zurückkommt. X ist dabei die Anzahl der Hops.
  Damit lassen sich Loops (Nachrichten, die immer im Kreis
  geschickt werden) vermeiden.    

  -t
  Liesst die Header der übergebenen Nachricht und sucht dort
  nach dem Absender und dem Empfänger. BCC-Zeilen werden vor
  dem Absenden gelöscht.

14. Gibt es auch Beispiele?

Klar. Hier werden jetzt einige Regeln veröffentlicht, die wohl die meisten Probleme regeln dürfte. Vorweg muss ich sagen, dass ich keinerlei Garantie für diese Regeln übernehmen kann.

Beachten Sie bitte: In der Datei .procmailrc werden mehrere Regeln verarbeitet. Wird die Nachricht durch eine oben stehende Regel verarbeitet, so gelten weiter unten stehende Regeln natürlich nicht mehr für diese Nachricht.

Weiterleiten aller Nachrichten an xyz@abc.de

  :0
  ! xyz@abc.de

Weiterleiten aller Nachrichten an xyz@abc.de, wenn die Absenderadresse @web.de enthält

  :0
  * ^From.*@web.de
  ! xyz@abc.de

Weiterleiten aller Nachrichten an xyz@abc.de, wenn im Titel „TEST“ vorkommt

  :0
  * ^Subject.*TEST
  ! xyz@abc.de

Weiterleiten aller Nachrichten, wenn im Absender „Mailer-Daemon“ und wenn im Titel „Return“ vorkommt

  :0
  * ^From.*Mailer-Daemon
  * ^Subject.*Return
  ! xyz@abc.de

Alle Nachrichten, die im Empfänger nicht qwe@asd.de stehen haben sollten mit einer Fehlermeldung zurückgeschickt werden. Aber Vorsicht dabei, sowas kann bei Spam-Attacken grauenhaft sein, da der eigene Mailer so tausende Fehlermeldungen erzeugt.

  :0
  * !^To.*qwe@asd.de
  {
  EXITCODE=67
  HOST
  }

Alle Nachrichten, die an news@asd.de geschickt werden, in einer Datei speichern.

  :0
  * ^To.*news@asd.de
  ! /home/user/dateiname.txt

Alle Nachrichten an spam@asd.de und junk@asd.de sofort löschen

Möglichkeit 1:

  :0
  * ^To.*(spam|junk)@asd.de
  /dev/null

Möglichkeit 2:

  :0
  * ^To.*spam@asd.de
  /dev/null

  :0
  * ^To.*junk@asd.de
  /dev/null

Die Datei test.txt zurücksenden, wenn die Nachricht an
test@asd.de geht

  :0c
  * ^TO.*test@asd.de
  | (formail -r -t -I "Return-path: <test@asd.de>"
    -I "From: test@asd.de"
    -I "Subject: Titel der Nachricht";
    cat /home/user/test.txt) | $SENDMAIL -t

Alle Nachrichten, die an verteiler@asd.de gehen an 3
eMail-Adressen weiterleiten

  :0
  * ^TO.*verteiler@asd.de
  {
  :0c
  ! erste@adresse.de
  :0c
  ! zweite@adresse.de
  :0
  ! letzte@adresse.de
  }

Wichtig hierbei: Alle Adressen bekommen eine Kopie (:0c), nur der Letzte bekommt die originale Nachricht. Der Grund hierfür ist klar: Würde der Erste Empfänger die Originalnachricht bekommen, so wäre beim zweiten Empfänger keine Nachricht mehr da.

Alternativ kann man mehrere Adresse auch mit einem Leerzeichen getrennt eintragen:

  :0
  * ^TO.*verteiler@asd.de
  :0
  ! erste@adresse.de zweite@adresse.de letzte@adresse.de

Eine Kopie der Nachricht an xyz@abc.de senden, wenn im Titel „Re:“ vorkommt.

  :0c
  * ^Subject.*Re:
  ! xyz@abc.de

15. Gibt es auch eine komplette Datei zum runterladen?

Nein. Wozu auch? Filter müssen ja sowieso immer individuell eingestellt werden. Ich kann natürlich eine Beispiel-Datei veröffentlichen, doch die Filter müssen Sie schon selbst anpassen.

  #
  # Zuerst werden alle Nachrichten gefiltert, die wie Spam
  # aussehen. Für Nutzer, die eMail nur national nutzen, sind
  # englische Nachrichten mit "wichtigem" Inhalt meist Spam.
  # Hierbei wird nur die eigentliche Nachricht untersucht.
  #

  :0B
  * (important|do not delete|sale|advertise|brandnew)
  /home/dafit/couldbespam.txt

  #
  # Nun lösche ich alle Nachrichten, die von einem Absender
  # oder von einem Mailer kommen, von denen ich schon einmal
  # Spam erhalten habe
  #

  :0
  * ^Reply-to.*@juno.com
  /dev/null

  :0
  * ^Received.*63.36.154.196
  /dev/null

  :0B
  * gotours@techie.com
  /dev/null

  :0B
  * signin4@123india.com
  /dev/null

  #
  # Nachrichten von einem Mailer-Daemon umleiten
  #

  :0
  * ^From.*MAILER-DAEMON
  ! error@butschek.de

  #
  # Nachrichten an freunde@butschek.de werden an alle meine
  # Freunde weitergeleitet, jedoch nur, wenn Sie mit meinem
  # Mailprogramm geschrieben wurden und von meiner Adresse
  # kamen.
  #

  :0
  * ^To.*freunde@butschek.de
  * ^From.*(mail|webmaster)@butschek.de
  * ^X-Mailer.*The Bat
  {
  :0c
  ! freund1@xyz.de
  :0c
  ! freund2@xyz.de
  :0c
  ! freund3@xyz.de
  :0c
  ! freund4@xyz.de
  :0
  ! freund5@xyz.de
  }

  #
  # Eine Nachricht an pgp@butschek.de wird mit meinem PGP-
  # Schlüssel beantwortet. Dazu wird die Datei pgp.msg
  # an den Absender zurückgeschickt. Diese muss natürlich
  # zuvor erstellt werden.
  #
  # WICHTIG: Alles von "(formail" bis "$SENDMAIL -t" muss
  # in eine Zeile geschrieben werden!
  #

  :0c
  * ^TO.*pgp@butschek.de
  | (formail -r -t
  -I "Return-path: <pgp@dafit.de>"
  -I "From: pgp@dafit.de"
  -I "Subject: PGP-Key von webmaster@dafit.de"
  -I "X-Loop: dafit.de";
  cat /home/dafit/pgp.msg) | $SENDMAIL -t

  #
  # Um verschiedene Projekte mit verschiedenen eMail-Adressen
  # zu versorgen, hat mein Freund Bernd bei mir auch eine
  # Adresse, die alle Nachrichten an seinen Account bei
  # seinem Provider weiterleitet. Und zwar alle Adressen,
  # die mit bernd@butschek.de enden, also auch Adressen wie
  # test.bernd@butschek.de oder xyz.bernd@butschek.de
  #

  :0
  * ^TO.*bernd@butschek.de
  ! bernd@provider.de

  #
  # Zum Schluss werden alle noch nicht sortierten Nachrichten
  # und auch alle Nachrichten an unbekannte Adressen mit
  # einer Fehlermeldung zurückgesendet.
  #

  :0
  * !^TO.*(mail|webmaster|mike|michael|butschek)@butschek.de
  {
  EXITCODE = 67
  HOST
  }
  /home/user/.procmailrc

16. Kann ich auch externe Dateien einbinden?

Klar, mit dem Befehl INCLUDERC=/pfad/dateiname läßt sich eine externe Datei in die Filterdatei .procmailrc einbinden. Wichtig ist jedoch, daß Sie Leserechte auf die externe Datei besitzen.

Sinnvoll ist dieser Befehl, wenn Sie zum Beispiel eine Spam-Datei für mehrere Benutzer anlegen möchten. Jeder Benutzer bindet die öffentliche Spam-Filter-Datei ein, wodurch sich diese Datei leicht administrieren läßt. Leider ist dies aufgrund des hohen Spam-Aufkommens heutzutage kaum noch möglich.

17. Kann ich ein Logfile erstellen lassen?

Zur Fehlersuche ist ein Logfile immer gut. Mit dem Befehl LOGFILE=procmail.log, möglichst am Anfang der Datei, läßt sich die Datei definieren, in der geloggt wird, in diesem Fall procmail.log im Home-Verzeichnis.

Die Logfiles sollten jedoch nicht im regulärbetrieb mitlaufen, zu groß ist die Gefahr, daß bei dem heutigen Spam-Aufkommen irgendwann die Platte mit Log-Daten voll ist.

18. Weitere Links zum Thema Procmail?

Etwas dreist, aber dennoch ein guter Tipp:
http://www.google.com/search?q=procmail

19. Ich habe noch Fragen, an wen kann ich mich wenden?

Keine Ahnung :-) Aber fragen Sie doch einfach mich, sofern ich
helfen kann, mache ich das gerne.

20. Virenschutz

Um ausführbare Dateien (meist eh nur Viren) auszufiltern nutze selbst Spamassassin und prüfe danach mit Procmail einfach auf den Spamassassin-Header, welcher die Tests enthält. Ausführbare Dateien werden mit dem Test „MICROSOFT_EXECUTABLE“ getaggt.

Klappt bisher Prima, seitdem habe ich absolut keine Viren mehr erhalten. Nachteil: Mir kann auch niemand mehr ausführbare Dateien oder Bildschirmschoner schicken. Aber gut, damit lebe ist, meine Bekannten kennen ZIP, womit das Problem wieder gelöst wäre.

21. Mail an ein Script weiterleiten

Manchmal wünscht man sich, bestimmte Mails an ein Script weiterzuleiten, um irgendwelche Dinge auszuführen (Mailingliste, etc). Dies ist nicht schwer, zuerst müssen wir Procmail sagen, daß die Mail an ein Script geht:

  :0
  * ^To.*script@butschek.de
  | /home/butschek/mailscript.php

Nun müssen sie noch ein passendes Script schreiben, das die Mail von Standardeingabe liest und weder eine Ausgabe erzeugt noch mit einem Exitcode <> 0 endet.

Im Beispiel hier ein PHP-Script, da auch diese Frage schon aufkam, wie man bei PHP die Standardeingabe liest. Daher hier ein kleines Beispiel:

  #! /usr/bin/php4 -q
  <?
   # Standardeingabe öffnen
   $stdin = fopen("php://stdin","r");

   /*
   Innerhalb dieses Scripts steht $stdin als
   normales Dateihandle (read only) zur
   Verfügung.
   */

   # Standardeingabe schliessen
   fclose($stdin);
  ?>

Für alle, die noch nie ein Shell-Script in PHP geschrieben haben: Die erste Zeile gibt Linux den Pfad des PHP-Interpreters an (unbedingt nötig, evtl Pfad anpassen), die Option q bedeutet, daß PHP der Ausgabe keine Header hinzufügen kann.

22. Darf ich dieses FAQ kopieren?

Ja. Ich habe diese FAQ nicht aus kommerziellem Hintergrund erstellt. Für mich war es einfach wichtig, alles übersichtlich zu haben. Ich selbst blicke oft auf diese Seite, wenn ich was ändern muß und mal wieder 1/4 Jahr nichts damit gemacht habe.

Wer will, darf sich die Seite gern kopieren. Ich würde nur gerne als Autor genannt werden. Da das Procmail-FAQ von mir gelegentlich überarbeitet wird, empfehle ich, entweder regelmäßig auf die Seite zu gucken, oder einen Link darauf anzubieten.