Für das ser­ver-sei­ti­ge Fil­tern bezie­hungs­wei­se Vor­sor­tie­ren von E‑Mails (zum Bei­spiel in ver­schie­de­ne Ord­ner) mit Hil­fe von Pro­c­mail oder Exim gibt es vie­le Anlei­tun­gen im Netz. Wenn aber kei­ne Sys­tem­kon­ten ver­wen­det wer­den, son­dern die E‑Mail-Adres­sen in einer (MyS­QL-) Daten­bank ver­wal­tet wer­den, gibt es zu den ein­zel­nen E‑Mail-Adres­sen kein pas­sen­des Home-Ver­zeich­nis. Ich beschrei­be in die­sem Bei­trag, wie man für die­sen Fall belie­bi­ge Fil­ter ein­rich­ten kann.

Sofern die E‑Mails mit Hil­fe eines Sys­tem­kon­tos zuge­stellt wer­den, genügt eine .for­ward-Datei im Home-Ver­zeich­nis (die Syn­tax die­ser Datei ist unter ande­rem in der Exim-Hil­fe erklärt). Mit fol­gen­dem Inhalt einer .for­ward-Datei kann man zum Bei­spiel alle E‑Mails, die in der Absen­der­adres­se die Zei­chen­ket­te bei­spiel ent­hal­ten, auto­ma­tisch in den E‑Mail-Ord­ner Bei­spiel ein­sor­tie­ren lassen.

# Exim filter
if $header_from: contains "beispiel" then
 save "/.../.Beispiel/"
endif

Nach der save-Anwei­sung muss der voll­stän­di­ge Pfad des Ziel­ver­zeich­ni­s­es ange­ge­ben wer­den. Das Ver­zeich­nis muss also bereits (durch ein E‑Mail-Pro­gramm) erstellt wor­den sein. Wo genau im Datei­sys­tem sich die­ses Ver­zeich­nis befin­det, kann man der Exim-Kon­fi­gu­ra­ti­ons­da­tei ent­neh­men. In der Datei kön­nen belie­big kom­ple­xe Fil­ter- bezie­hungs­wei­se Sor­tier­vor­gän­ge defi­niert werden.

Wenn man die E‑Mail-Adres­sen (vir­tu­ell) über eine (MyS­QL-) Daten­bank ver­wal­tet, kann man den Inhalt einer .for­ward-Datei eben­falls in der Daten­bank spei­chern und von Exim aus­wer­ten las­sen. Dazu muss man in der Kon­fi­gu­ra­ti­ons­da­tei in dem Abschnitt, der mit begin rou­ters beginnt, eine neue Regel wie folgt anle­gen. (Falls die Exim-Kon­fi­gu­ra­ti­on in meh­re­re Datei­en auf­ge­split­tet ist, befin­den sich die Rou­ting-Regeln womög­lich in einem Ver­zeich­nis wie /etc/exim4/conf.d/router. Dort muss dann der fol­gen­de Inhalt in eine neue Datei ein­ge­fügt wer­den, die vom Datei­na­mens­sche­ma zu den übrig­e­nen Datei­en passt.)

mysql_virtual_forward:
 driver = redirect
 allow_filter
 check_local_user = false
 data = ${lookup mysql {SELECT forward FROM Mailfilter WHERE email = '$local_part@$domain'}{$value}}
 no_verify
 no_expn
 check_ancestor
 file_transport = address_file
 pipe_transport = address_pipe
 reply_transport = address_reply
 directory_transport = address_directory
 user = Debian-exim
 group = Debian-exim

Als Wer­te unter user und group muss der Benut­zer­na­me bezie­hungs­wei­se der Grup­pen­na­me ein­ge­ge­ben wer­den, unter dem Exim auf dem Ser­ver läuft. Die Zei­le data ent­hält eine SQL-Abfra­ge, die als Rück­ga­be­wert den Inhalt von genau einer .for­ward-Datei zurück­lie­fern muss.

In mei­nem Fall hat die Tabel­le Mail­fil­ter eine sehr ein­fa­che Struktur:

CREATE TABLE IF NOT EXISTS `Mailfilter` (
`fid` int(11) NOT NULL auto_increment,
`email` varchar(255) NOT NULL,
`forward` text NOT NULL,
PRIMARY KEY  (`fid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Die Tabel­le ent­hält neben einer ID ein Feld für die voll­stän­di­ge E‑Mail-Adres­se, für die die in dem Feld for­ward ange­ge­be­ne „Fil­ter­da­tei” ange­wandt wer­den soll. Der Wert des Fel­des for­ward ent­spricht exakt dem Datei­in­halt wie zum Bei­spiel von obi­ger .for­ward-Datei.

Nun muss noch die geän­der­te Kon­fi­gu­ra­ti­on von Exim ein­ge­le­sen wer­den, und dann soll­te es gehen. Falls nicht, hilft even­tu­ell ein Blick in Exims main­log (even­tu­ell unter /var/log/exim4 zu finden).

Ein Dank geht an @MScDoc, der mich auf mei­ne Twit­ter-Nach­fra­ge hin auf den Bei­trag Exim w/virtual users and pro­c­mail hin­wies. Die in die­ser Dis­kus­si­on von Adam vor­ge­schla­ge­ne Lösung funk­tio­niert zwar mit dem aktu­el­len Exim4 nicht mehr, aber nach kur­zer Recher­che habe ich her­aus­ge­fun­den, dass ledig­lich die frü­her gül­ti­ge Anwei­sung fil­ter durch allow_filter ersetzt wer­den muss, damit es auch unter Exim4 funktioniert.

[1. Aktua­li­sie­rung, 8. Dezem­ber] Ich habe mir zur Erzeu­gung einer kor­rek­ten .for­ward-„Datei” das fol­gen­de Perl-Skript geschrie­ben, dass von Nut­zen ist für alle, die vie­le Mai­ling­lis­ten fil­tern und den Über­blick behal­ten wollen…

#!/usr/bin/perl -w

$maildir = '/-pfad-zum-mail-verzeichnis-auf-dem-server/';
@r = (
        ['-filterstring-im-to-oder-cc-feld-', '-verzeichnis/-unterverzeichnis-/'],
#       ['', ''],
#       ['', ''],
#       ['', ''],
     );

print "# Exim filter\n\n";
$i = 0;
$condstr = '';
foreach(@r) {
        $i++;
        if ($i == 1) {
                $condstr = 'if';
        } else {
                $condstr = 'elif';
        }

        print $condstr . ' $header_to: contains "' . @$_[0] . '" or $header_cc contains "' . @$_[0] . '" then' . "\n";
        print 'save "' . $maildir . @$_[1] . '"' . "\n\n";
}
print "endif\n\n";