Navigationshilfe

Hauptnavigation

Seiteninhalt

Exim Filter

Hier wird gezeigt, wie man ankommende Mails vor der Zustellung in Unterordner sortiert oder sonstwie bearbeitet. Verwendet wird das serverseitige Programm Exim Filter. AnfängerInnen sollten eMails jedoch besser im eigenen Mailprogramm oder serverseitig mit procmail filtern. Spam kann am Besten mit unserem Spamreport Verfahren gefiltert werden.

Obwohl Exim Filter komplizierter (programmiersprachenähnlicher) ist als procmail wird es hier aus zwei Gründen vorgestellt:

  • Exim Filter kann eMails verläßlich auf andere Adressen weiterleiten, während bei procmail unter Umständen Mailloops entstehen.

  • Exim Filter wird beim Spamreport Verfahren an der Uni benutzt. Wer seinen vorgegebenen Spamreport Filter von Hand anpassen will, muss auf procmail umstellen oder -- Exim Filter lernen.
Hinweis: Diese Seiten werden z.Z. (Juni 2004) geschrieben. Informationen können lückenhaft und fehlerhaft sein. Beachten Sie das, wenn Sie aufgrund dieser Seite einen eigenen Filter schreiben. Machen Sie Tests. Vergleichen Sie die offizielle Dokumentation.

Ein erster Filter

Der Exim Filter wird in der .forward Datei ("forward" mit einem Punkt davor) in Ihrem Homeverzeichnis im Cluster des Rechenzentrums konfiguriert. Hinweis: einloggen und "pico .forward" ausführen, um die Datei zu bearbeiten.

Für die weiteren Beispiele wird angenommen, dass in Ihrem Homeverzeichnis das Verzeichnis "mail" existiert. Prüfen können Sie das mit "ls -ld ~/mail". Anlegen können Sie das Verzeichnis mit "mkdir ~/mail". Evt haben Sie stattdessen ein Verzeichnis "Mail" großgeschrieben, das Sie verwenden wollen. Dann wäre es besser statt "mkdir ~/mail" mit "ln -s Mail mail" beide Verzeichnisse zu verlinken (mail ist dann ein Link/ Verweis auf Mail).

Achtung: Wenn Sie die Datei .forward mit Ihren ersten Filtergehversuchen abspeichern, dann arbeitet sie sofort als Filter für Ihre eingehenden Mails. Im Falle von Fehlern erhalten die Absender einen Fehler Report. Wenn Sie das nicht wollen, können sie eine Vorabversion schreiben: "pico forward_vorab" und erst mit "cp forward_vorab .forward" aktiv schalten.

Ein einfacher Filter, der nur eine Regel hat, die eMails mit dem Subject "test" in einen Mailordner verschiebt, sieht so aus:

# Exim Filter

# Filter "test"
if $header_Subject: contains "test"
then
  save $home/mail/test
endif

Erklärungen:

  • Der Filter muss immer mit "# Exim Filter" beginnen. Das ist kein Kommentar, sondern ein Hinweis an das Mailsystem, die .forward Datei als Filter zu interpretieren.
  • '# Filter "test"' ist ein Kommentar, der mit "#" eingeleitet wird.
  • "$header_Subject:" ist eine Variable, die den Inhalt des Subjects enthält. Der Doppelpunkt gehört zur Variable.
  • 'if $header_Subject: contains "test" then': 'Wenn das Subject "test" enthält, dann...'. Dies hier ist die eigentliche Filterbedingung.
  • "save $home/mail/test": die entsprechende Mail wird in den Mailordner "test" im Verzeichnis "mail" verschoben. "$home" ist eine Variable, die den Pfad zu Ihrem Homeverzeichnis enthält.
  • "endif": der mit "if" begonnene Filter wird beendet. Wenn irgendwo zu einem if das endif fehlen würde, dann würde der gesamte Exim Filter nicht funktionieren.
  • Alle Mails, die nicht vom Filter erfasst wurden, werden wie üblich behandelt, d.h. in die Inbox gespeichert.

Ein Mailordner ist eine einfache Datei, kein Verzeichnis. Mailordner werden vom Eximfilter angelegt, wenn noch nicht vorhanden.

Konzepte

Variablen

Variablen wie "$home" oder "$header_Subject:" beginnen mit "$" und sind Namen für den Text, den sie enthalten. Alle Variablen werden im Exim Filter vor Ausführung expandiert, d.h. anstatt ihrer selbst wird der Text eingetragen, für den sie stehen.

Es gibt zwei Gruppen von Variablen: Header Variablen, die die Inhalte von Headern enthalten und Variablen, die die Mailsoftware zur Verfügung stellt. Einige nützliche Variablen:

VariablennameErläuterung (falls nötig)
$header_From:Inhalt des From-Headers (Absender)
$header_Subject:ebenso
$header_To:ebenso
$header_List-Id:Ein von Listensoftware verwendeter Header
$header_X-MailScanner-SpamScore:"Unser" Spamscore Header
$header_Content-Type:hier können html-only Mails gefiltert werden
weitere Header Variablen bitte nach obigen Muster bilden. Ab hier Variablen der Mailsoftware
$homeDas Homeverzeichnis des Benutzers/ der Benutzerin
$local_partIhr Benutzername: Der Teil vorm "@" der Zustelladresse. Nicht immer identisch mit Ihrer eMailadresse.
$tod_logZeit und Datum der Zustellung im "log" Format.
$sender_addressDies ist die sogenannte envelope Absender Adresse, d.h. die echte Adresse und nicht der möglicherweise gefälschte From-Header.
$message_sizeGröße der eMail in Bytes
$message_bodyDie ersten 500 Zeichen des Mailbodies
$message_body_endDie letzten 500 Zeichen des Mailbodies

Variablen wie $home oder $tod_log eignen sich übrigens kaum zum eigentlichen Filtern, sondern werden für andere Dinge gebraucht.

Variablen, die nicht existieren, wie z.B. eine Headervariable die in der Mail gar nicht vorkommt oder ein Tippfehler im Variablennamen, werden als leerer Text expandiert. Folge ist normalerweise, dass der jeweilige Test nicht funktioniert (ein leerer String enthält ("contains") eben nichts).

Bedingungen

Die Bedingungen stellen die eigentlichen Filter dar: sie testen auf bestimmte Eingenschaften der eMail, meistens vergleichen sie ein Stück Text aus der Mail mit einem Suchtext. Bedingungen werden in if-Konstruktionen verwendet:

if Bedingung
  then Aktion

endif

Bedingungen können ein einzelnes Wort sein, wie error_message (prüft, ob die eMail ein Mail Delivery Failure Report ist) oder "personal" (testet, ob die eMail an einen persönlich ging, statt über Listen). Andere Bedingungen vergleichen einen Text aus der Mail mit einem Suchtext: contains (Der Text enhält den Suchtext), ends, begins (Der Text endet oder beginnt mit dem Suchtext), is (Text und Suchtext sind identisch), match (Der Suchtext als Regulärer Ausdruck trifft auf den Text zu).

# Beispiel
if header_Subject: contains "hallo"
   then save $HOME/mail/begruessung
endif

Bei obigem Beispiel müssen Sie beachten, dass diese Bedingung alle Mails herausfiltert, die "hallo" irgendwie im Subject enthalten. "Halloween" würde auch gefiltert werden. Wenn man statt "contains" "match" verwendet, vermeidet man dass. Meistens ist "contains" aber ausreichend.

Aktionen

Ob mit oder ohne if-Abfrage, kann man verschiedene Dinge in Bewegung setzen. Das einfachste ist, die eMails in extra Ordner zu verschieben, z.B. um eMails von Listen in extra Ordner zu sortieren (save). Andere Möglichkeiten sind, die Mails weiterzuleiten (deliver) oder an andere Programme weiterzugeben (pipe). Das Schreiben einer Logdatei (logfile + logwrite) und automatisierte Antworten (mail / vacation) sind weitere Möglichkeiten.

Aktionen bestehen aus einem Schlüsselwort und evt. weiteren Angaben, wie z.B. die Datei in die gespeichert werden soll.

Welche Aktionen sind signifikant

Es geht um die Frage, ob nach Abarbeitung des Exim Filters die eMail defaultmäßig in die Inbox gespeichert wird. Dies passiert nicht, wenn im Exim Filter eine "signifikante" Aktion gefunden wurde. Diese Aktionen sind deliver, save, pipe.

Nach einer solche Aktion wird zwar der Filter weiter abgearbeitet, aber die eMail wird danach nicht noch mal in der Inbox gespeichert.

Mit "seen" kann eine Aktion als signifikant markiert werden und mit "unseen" ist eine signifikante Aktion nicht mehr länger signifikant (Was das heißt wird vrmtl im Beispiel unten deutlicher). Wenn der Filter nach einem Fund nicht weiter abgearbeitet werden soll, dann verwendet man eine weitere Aktion finish.

Ein Beispiel

Hier ein kompletter Filter als Beispiel. Er zeigt, wie man Mail whitelisted bevor der Spamfilter tätig wird. Die beschriebenen Filter sind keine notwendigen Bestandteile, sondern Beispiele dafür, was man machen kann. Bitte nichts 1 zu 1 kopieren.

Die Kommentare stehen in der Zeile oberhalb dessen, was kommentiert werden soll.

# Exim Filter

# Zum Selbstschutz: Fehlermeldungen (die der eigene Filter erzeugt
#  haben koennte) nicht nochmal ueber den Filter schicken
if error_message
    # finish: beende Filter und speichere die Mail in der Inbox
    then finish
endif

# Jetzt auf spamfreie Mailinglisten oder bekannte Absender filtern
# Dadurch werden diese Mails niemals vom Spamfilter erfasst (Whitelist).
if $header_List-Id: contains "liste@listenserver.org"
    then save $home/mail/listenmails
    # finish: beende Filter. Nicht in die Inbox speichern, weil schon
    #  "signifikant" zugestellt wurde.
    finsh
    # wem "signifikant zugestellt" zu wage ist, schreibt "seen finish"
endif

# Beispielsweise moechte man bestimmte Mails extra (zusaetzlich zur
# Inbox) archivieren.
if $header_From: contains "adresse@wertvolle-mails.de"
    # unseen save: nicht-signifikantes Speichern, damit zusaetz-
    # lich in die Mailbox gespeichert wird.
    then unseen save $home
endif

# Der Spamfilter fuer das Spamreportverfahren (Sie muessen immer noch
#  den Filter in webmail freischalten, um tatsaechlich den Report zu
#  bekommen):
if $header_X-MailScanner-SpamScore: contains "sssss"
    then save $home/spam_mail_cache
endif

# ab jetzt relativ spamfrei. Hier koennen z.B. Listen in eigene Ordner
# kopiert werden oder die eMails weitergeleitet werden.

Howtos

Den Filter testen

Sie sollten unbedingt überprüfen, ob der Filter syntaktisch richtig ist. "Syntaktisch" bedeuted, dass die endif's alle da sind, kein then vergessen usw. Für den Test brauchen Sie eine Testmail, die mitsamt Mailheadern in eine Datei gespeichert wird. Am einfachsten ist es wohl, wenn Sie sich in Ihrem Mailprogramm eine Mail in Quelltest/ Vollansicht anschauen und per Copy&Paste nach pico (oder einem anderen Testeditor) schleusen. Dateiname vorschlagshalber "message".

Speichern Sie Ihren Exim Filter vorher ab. Auf der Kommandozeile machen Sie dann:

# pico oeffen (und dann eine beliebige eMail Copy&Pasten)
pico message
# Abspeichern, pico beenden.

# Sie muessen sich auf den zentralen Mailserver einloggen. Dort haben
#  Sie dasselbe Homeverzeichnis und Zugriff auf die Mailsoftware.
ssh hermes.rz.uni-frankfurt.de
# Los geht's:
/usr/exim/bin/exim -bf ihre_filter_datei < message
# Hinweis: Vergewissern Sie sich, dass das <-Zeichen richtig
# herumsteht: Spitze nach links. Sonst wird "message" ueberschrieben
# (aber Sie wissen ja, wie Sie es neu erzeugen koennen).

# Tippen Sie bei langen Verzoegerungen Strg-C um abzubrechen.

Syntaxfehler werden jetzt mit "Filter Error:" ausgewiesen. Die Fehlermeldung ist allerdings nicht besonders clever, sondern weist meist auf eine Stelle hin, die ein zwei Zeilen unterhalb des tatsächlichen Problems steht. Achten Sie vor allem auf fehlende if's, endif's und then's.

Wenn es keinen "Filter Error" gibt, dann bekommen Sie gesagt, was mit der eMail geschehen wäre, wenn es nicht nur ein Test gewesen wäre. Auf diese Weise können Sie dann Ihre if-Bedingungen an bestimmte Subjects oder sonstige Header anpassen.

Testen Sie auch mit echten Mails! Sie müssen unbedingt überprüfen, dass der normale Mailverkehr noch funktioniert. Schicken Sie sich einfach eine Mail.

Eine Logdatei schreiben

Je nach Komplexität des Filters ist es angebracht, eine Logdatei zu schreiben:

# Exim Filter

# Die Logdatei sollte als allererstes geschrieben werden, damit nichts
# verloren geht.
logfile $home/eximfilter.log
logwrite "$tod_log $header_From: $header_Subject:" 

Die Logdatei, die jetzt geschrieben wird, hilft Ihnen herauszufinden, ob etwas schief gelaufen ist. Vor allem, wenn Sie Mails direkt löschen wollen, ist eine Logdatei eigentlich Pflicht, weil Sie sonst nicht einmal wissen können, dass etwas gelöscht worden ist.

Sie können mehrere logwrite Anweisungen benutzen, um die Logzeile erst zu schreiben, wenn die jeweiligen Filter zugetroffen haben. Das macht durchaus Sinn, weil erst zu dem Zeitpunkt eine ziemlich wichtige Information bekannt ist: Wohin die eMail gespeichert oder geschickt wird. Das sieht dann z.B. so aus:

# Exim Filter

# globale Logdatei
logfile $home/eximfilter.log

# Filterspezifisch Loganweisung.
if irgendeine Bedingung
    then save $home/mail/irgendwo
    logwrite "$tod_log $header_From: $header_Subject: --> irgendwo"
endif

Die Logdatei wird ab jetzt immer größer und größer. Man kann sie mit "rm ~/eximfilter.log" löschen - was auf Dauer aber keine Lösung ist. Eine dauerhafte Lösung dieses Problems steht noch aus. Festplatten sind geduldig.

Speichern in die Inbox

Whitegelistete Mails sollen meist ganz normal in die Inbox. Wo ist die? Sie liegt im Verzeichnis "/var/spool/mail/" und lautet auf Ihren Benutzernamen. Statt Benutzername können Sie die Variable $local_part verwenden:

if $header_From: contains "freundliche Adresse"
    then save /var/spool/mail/$local_part
endif
Besser ist aber, Sie schreiben Ihren eigenen Benutzernamen (das ist der, den Sie beim Einloggen verwendet haben - in Kleinbuchstaben).

Mehrere Absender in einem Filter testen

Wie whitelisted man all die Leute in seinem Adressbuch? Man könnte "match" verwenden und einen Regular Expression bauen - aber dadurch wird es nicht einfacher. Besser ist vrmtl die Tests mit "or" aneinanderzuhängen:

if $header_From: contains Name@server.de or
   $header_From: contains Name2@server.de or
   $header_From: contains Name3@server.de
   then save /var/spool/mail/$local_part
   finish
endif

Das ist immer noch recht viel Tipparbeit; etwas für Copy & Paste. Wenn Sie unbedingt Reguläre Ausdrücke verwenden wollen: Exim Filter verwendet die Hochleistungsbibliothek pcre.

Mehrere Bedingungen verschachteln

Angenommen, eine Mailingliste verschickt ansonsten ganz brauchbare Mails, aber manchmal große Dinger mit langweiligen Attachments. Dann starten Sie gleich nach "then" eine Größenprüfung:

if $header_List-Id: contains "traffic@listenserver.org"
    then
    if $message_size is above 50k
        # so grosse Mails nicht weiter bearbeiten. Mit seen wird
        #  finish zu einer signifikanten Aktion (-> kein default
        #  delivery)
        # seen finish: Beende und speichere nicht in der Inbox.
        #              MaW: loesche die Mail
        then seen finish
    else save $home/mail/listenmails
    endif
endif

Die Größe kann direkt in Bytes angegeben werden. mit "k" werden Kilobytes, mit "M" Megabytes angegeben. 50k reicht für Text-eMails, wenn sie keine Romane umfassen.

eMails weiterleiten

Sie können eMails an eine andere Adresse weiterleiten, bei uns oder woanders. Hier ein Beispiel, bei dem alle Mails an einen anderen Account geschickt werden (evt nachdem Spam aussortiert wurde):

# Exim Filter

# Keine Bedingung, einfach die Aktion
deliver adresse@server.de

Mögliche Schreibweisen

Wo muss das if, das then, die Aktion hin? Antwort ist, dass es dafür keine zwingende Vorschrift gibt, nur die Reihenfolge muss stimmen.

Folgende Filter sind identisch und Sie können machen, was Ihnen am Besten passt:

# Exim Filter

# alles auf eine Zeile
if error_message then finish endif

# Extra Zeile fuer then und Aktion
if error_message
   then finish
endif

# Die Aktion auf eine Zeile fuer sich
if error_message
then
   finish
endif

# Die Einrueckungen koennen nach Belieben gemacht werden

Weitere Dokumentation

Die offizielle Dokumentation finden Sie hier für die Version 4.10. Diese Dokumentation ist zwar auf Englisch, aber sehr klar geschrieben. Sie erfahren dort exakte Details zur Syntax und weitere Möglichkeiten.

Es wird zunächst die allgemeine Syntax, Installation und Testen sowie Variablen und "Significant Deliveries" vorgestellt. Danach werden die Aktionen ("Filter commands") beschrieben und erst ab Abschnitt 22 "Obeying commands conditionally" die if-Bedingungen.

[Ignorieren Sie Abschnitt 30 "Multiple personal mailboxes" und alles über $local_part_prefix und -suffix. Das haben wir hier nicht.]

Probleme

Mails werden doppelt abgespeichert

Wenn Mails in mehreren Ordnern abgespeichert werden oder an anderer Stelle wieder auftauchen, dann muss vrmlt irgendwo ein "finish" eingefügt werden, um den Filter zu beenden, nachdem er die Mail das erste Mal bearbeitet hat.

 

geändert am 27. Oktober 2007  E-Mail: mailadminmailadmin@uni-frankfurt.de

|

| Zur Navigationshilfe
empty

Seitenabschlussleiste


Druckversion: 27. Oktober 2007, 22:19
http://www.uni-frankfurt.de/org/hrz/internet/mail/Support/FAQ/Howtos/eximfilter.html