Mailserver 10 von 10: SpamAssassin anlernen mit maillearn.phs

Jahrelang habe ich mich davor gedrückt, doch endlich ist es geschafft - die Einrichtung eines eigenen Mailservers. In einer kleinen Artikelserie möchte ich einmal meine Erfahrungen und Konfigurationsschritte festhalten. Diese Serie basiert auf zahllosen Tutorials, Best Practices, Gesprächen mit Mailserver-Betreibern, aus endlosem Dokumentationen lesen und dem Wissen der Bücher "Postfix" von Kyle D. Dent und "Postfix - Einrichtung, Betrieb und Wartung" von Ralf Hildebrandt und Patrick Ben Koetter. Vielleicht werden sie ja nützlich für andere Leute sein, die das gleiche erreichen wollen.

Doch eines vorab: Die Einrichtung und der Betrieb eines Mailservers ist eine komplexe Sache. Klar, die Software lässt sich schnell installieren, doch fertig ist man danach noch lange nicht, wenn man ernsthaft damit arbeiten möchte.

Der Fahrplan der Artikelserie:

  1. Einleitung
  2. Mailempfang und Mailversand mit Dovecot und Postfix
  3. Virenprüfung mit ClamAV
  4. Mailsignatur mit OpenDKIM
  5. Spamprüfung mit SpamAssassin
  6. Mailabruf mit Dovecot
  7. Mailboxen konfigurieren mit mailconf.phs
  8. Mails synchronisieren mit mailsync.phs
  9. Mailqueue überwachen mit mailqueue.phs
  10. SpamAssassin anlernen mit maillearn.phs

Mit dem heutigen und letzten Artikel neigt sich die Artikelserie zum Thema Mailservereinrichtung dem Ende zu. Wir werden uns nun einmal ansehen, wie wir den Spamfilter SpamAssassin ein wenig optimieren können.

Unser Mailserver ist bereits halbwegs gut gegen Spam gerüstet. Wir akzeptieren nur Mails für existierende Adressen, wir prüfen den absendenden Mailserver auf Herz und Nieren und SpamAssassin nutzt bereits ein paar Filter, die schon Spammails aussortieren, wenn sie allzu auffällig sein sollten.

Allerdings kann SpamAssassin noch mehr: Es beinhaltet ein Bayes Network - eine Art lernfähigen Filter - der relativ gut darin sein könnte, Spam zu erkennen. Könnte deshalb, da solch ein Bayes Network angelernt werden muss - man muss anhand von Beispielen vorführen, wie Gutfälle (Ham) und wie Schlechtfälle (Spam) aussehen. Anhand dieser Beispiele kann SpamAssassin dann eigene Entscheidungen treffen.

Eine Möglichkeit, die Gut- und Schlechtfälle zu erhalten, ist, vorgefertigte Pakete zu verwenden, die mit Spam angelernt werden - so ähnlich wie bei einem Virenscanner gibt es dann regelmäßig Updates, damit SpamAssassin auch neue Spamwellen zuverlässig erkennen kann.

Das ganze hat jedoch einen Haken: Durch diese Pakete erkennt SpamAssassin nur Spammails des Durchschnittsnutzers. Es kommt jedoch häufiger vor, dass man ganz spezifische Mails filtern will - z.B. E-Mail-Verteiler, die man nicht abbestellen kann oder Targeted Spam, den Verwalter solcher Pakete möglicherweise gar nicht zu Gesicht bekommen.

Aber wieso sollen wir uns darauf verlassen, dass jemand anderes unseren Spam kennt, wenn wir das selbst doch viel besser können? SpamAssassin bringt nämlich ein Tool - "sa-learn" - mit, mit dessen Hilfe wir SpamAssassin beibringen können, was für uns Gutfälle und was Schlechtfälle sind. Um das ganze ein wenig zu automatisieren, habe ich zwei Scripte geschrieben: maillearn-s.phs und maillearn-c.phs

maillearn-s.phs läuft regelmäßig auf dem Server, auf dem die E-Mails abgerufen werden können. Dort geht es die einzelnen Postfächer durch und schaut in den Unterordner, in dem die gelesenen Nachrichten des Posteingangs abgelegt sind. Diese E-Mails werden SpamAssassin als Gutfälle präsentiert. Zudem schaut es in den Unterordner, in dem die gelesenen Spammails abgelegt sind. Genau diese E-Mails sind natürlich dafür geeignet, als Schlechtfall zu dienen.

Dadurch, dass der Nutzer selber E-Mails in den Spamordner legen kann, kann er somit aktiv mitentscheiden, was als Spam gilt. Gleichzeitig kann er mit dem Verschieben und Löschen von Mails aus dem Spamordner entscheiden, was evtl. doch kein Spam ist und nur fälschlich dort einsortiert wurde. Der Filter entwickelt sich also mit den Anforderungen und Gewohnheiten der Benutzer mit. Mir persönlich gefällt dieser Ansatz sehr.

Wenn alle Mailboxen durchgearbeitet wurden, exportiert maillearn-s.phs die gesammelten Daten und überträgt sie per SSH an den Server, auf dem SpamAssassin tatsächlich läuft.

Dort kommt dann maillearn-c.phs zum Einsatz. Es prüft, ob ein neuer Export vorliegt und importiert die Daten in die lokale SpamAssassin-Installation.

Die Installation von maillearn-s.phs läuft so wie immer: Wir benötigen PHP und Mercurial und ziehen dann die entsprechenden Repositories heran:

1
2
3
4
5
6
sudo apt-get update
sudo apt-get install php5-cli php5-curl php5-ssh2 mercurial

sudo hg clone https://hg.nhg.name/maillearn-s/
sudo hg clone https://hg.nhg.name/pushinfo/
sudo hg clone https://hg.nhg.name/unchroot/

Schauen wir uns einmal die Konfigurationen ein wenig genauer an. Bei maillearn-s.phs ist die Konfiguration wieder zweigeteilt - es gibt die statische Konfiguration in der Datei "maillearn-s.conf.phs" und es gibt die serverspezifische Konfiguration in der Datei "maillearn-s.conf.<x>.phs". Genau wie bei mailsync.phs müssen wir ja potentiell mehrere E-Mail-Empfangsserver mit den Spaminformationen versorgen.

Ein Blick in die Datei "maillearn-s.conf.phs" offenbart wenig neues - der absolute Pfad zu den Postfächern (LOCAL_ABSOLUTE_PATH), der relative Pfad zum Posteingang (LOCAL_RELATIVE_PATH_CUR), der relative Pfad zum Spamordner (LOCAL_RELATIVE_PATH_SPAM_CUR) und die eigentlichen Aufrufe von "sa-learn" (SA_LEARN_*):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php

  # defines the local absolute path to the mail home
 # do not forget the trailing slash
 define("LOCAL_ABSOLUTE_PATH", "/srv/mailusers/");

  # defines the local relative path to the SPAM maildir cur
 # do not forget the leading and trailing slash
 define("LOCAL_RELATIVE_PATH_SPAM_CUR", "/Maildir/.Junk/cur/");

  # defines the local relative path to the maildir cur
 # do not forget the leading and trailing slash
 define("LOCAL_RELATIVE_PATH_CUR", "/Maildir/cur/");

  # defines the command to clear learned HAM and SPAM
 define("SA_LEARN_CLEAR", "sa-learn --clear");

  # defines the command to learn HAM
 define("SA_LEARN_HAM", "sa-learn --no-sync --local --ham");

  # defines the command to learn SPAM
 define("SA_LEARN_SPAM", "sa-learn --no-sync --local --spam");

  # defines the command to save learned HAM and SPAM
 define("SA_LEARN_SYNC", "sa-learn --sync");

  # defines the command to backup learned HAM and SPAM
 define("SA_LEARN_BACKUP", "sa-learn --backup >");

  # defines the push message
 define("PUSHINFO_MESSAGE_HAM",  " hams and ");
  define("PUSHINFO_MESSAGE_SPAM", " spams have been learned.");

?>

Auch die serverspezifische Konfiguration in der Datei "maillearn-s.conf.<x>.phs" ist einfach verständlich - wir verwenden wieder einmal Pushinfo für potentielle Statusnachrichten (PUSHINFO_PATH), wir müssen die Exportdatei irgendwo ablegen (STATUS_PATH), wir betreiben Locking (TIMEOUT), um Parallelaufrufe zu vermeiden und wir benötigen die SSH-Zugriffsdaten (REMOTE_*) für den anderen Server:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php

  # defines where the push notification is located
 define("PUSHINFO_PATH", "/srv/pushinfo/messages/maillearn-s.phs_example");

  # defines where the script stores its status
 define("STATUS_PATH", "/srv/maillearn-s/status/status.example");

  # define timeout for PHP execution (as int)
 # alternatively defines a lock file (as string)
 define("TIMEOUT", "/srv/maillearn-s/status/lock.example");

  # defines the remote absolute path to the exchanged file
 define("REMOTE_ABSOLUTE_PATH", "/home/maillearn/status");

  # defines the remote hostname
 define("REMOTE_HOSTNAME", "<REPLACE-ME>");

  # defines the remote port
 define("REMOTE_PORT", 22);

  # defines the remote user
 define("REMOTE_USERNAME", "<REPLACE-ME>");

  # defines the remote password
 define("REMOTE_PASSWORD", "<REPLACE-ME>");

?>

Beachtet, dass es sich beim STATUS_PATH und beim REMOTE_ABSOLUTE_PATH in diesem Fall - im Gegensatz zu mailsync.phs - nicht um Ordner sondern lediglich um einzelne Dateipfade handelt.

Der Aufruf von maillearn-s.phs funktioniert dann auf folgende Art, wobei die entsprechende Konfigurationsdatei "maillearn-s.conf.<server>.phs" für die Ausführung mit herangezogen wird:

1
sudo php maillearn-s.phs <server>

Ihr könnt den Aufruf entweder nach Bedarf durchführen oder aber z.B. CRON regelmäßig laufen lassen. Zu oft sollte das jedoch nicht geschehen, da dabei sämtliche abgelegten E-Mails durchgearbeitet werden.

Die Installation von maillearn-c.phs auf dem E-Mail-Empfangsserver, auf dem auch SpamAssassin installiert ist, ist ähnlich einfach. Ich gehe dabei davon aus, dass ihr selbst einen Nutzer anlegt, den maillearn-s.phs für die Übertragung der Daten verwenden kann. Beachtet auch, dass dieses Mal das Repository "maillearn-c" verwendet wird, anstelle von "maillearn-s":

1
2
3
4
5
6
sudo apt-get update
sudo apt-get install php5-cli php5-curl mercurial

sudo hg clone https://hg.nhg.name/maillearn-c/
sudo hg clone https://hg.nhg.name/pushinfo/
sudo hg clone https://hg.nhg.name/unchroot/

Die Konfiguration ist bei maillearn-c.phs nicht geteilt, sie befindet sich in der Datei "maillearn-c.conf.phs". Ich zeige erst einmal den Inhalt der Datei und beschreibe sie anschließend etwas genauer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php

  # defines the local absolute path to the spamassassin backup
 define("LOCAL_ABSOLUTE_PATH", "/home/maillearn/status");

  # defines where the push notification is located
 define("PUSHINFO_PATH", "/srv/pushinfo/messages/maillearn-c.phs");

  # defines where the script stores its status
 define("STATUS_PATH", "/srv/maillearn-c/status/status");

  # define timeout for PHP execution (as int)
 # alternatively defines a lock file (as string)
 define("TIMEOUT", "/srv/maillearn-c/status/lock");

  # defines the command to restore learned HAM and SPAM
define("SA_LEARN_RESTORE", "sa-learn --restore");

  # defines the dbpath parameter
 define("DBPATH_PARAM", "--dbpath");

  # defines the relative dbpath
 # do not forget the leading slash
 define("DBPATH_RELATIVE", "/.spamassassin/bayes");

  # defines the prefspath parameter
 define("PREFSPATH_PARAM", "--prefspath");

  # defines the relative prefspath
 # do not forget the leading slash
 define("PREFSPATH_RELATIVE", "/.spamassassin/user_prefs");

  # defines the user the script shall run as
 define("PROCESS_USER", "debian-spamd");

  # defines the group the script shall run as
 define("PROCESS_GROUP", "debian-spamd");

  # defines the push message content
 define("PUSHINFO_MESSAGE", "new HAM and SPAM learned");

?>

Der LOCAL_ABSOLUTE_PATH gibt an, wohin die SpamAssassin-Daten hochladen wird. Dies entspricht also dem REMOTE_ABSOLUTE_PATH in der Konfiguration von maillearn-s.phs.
Auch maillearn-c.phs kann Pushnachrichten mit Hilfe von Pushinfo versenden (PUSHINFO_PATH) und es braucht ebenfalls eine Datei, in der es seinen aktuellen Status ablegen kann (STATUS_PATH).
Ebenfalls wird wieder Locking durch eine Datei verwendet, um parallele Starts zu vermeiden, da das zu Problemen mit der SpamAssassin-Datenbank führen kann (TIMEOUT).

Nun wird es jedoch etwas komplexer, wobei ich mich hier beispielhaft auf Debian beziehe. SpamAssassin (genauer gesagt spamd) wird als ein spezifischer Nutzer (in unserem Fall "debian-spamd") ausgeführt. In dessen Home-Verzeichnis müssen die Daten schlussendlich importiert werden. Um das zu erreichen, muss der PROCESS_USER und die PROCESS_GROUP auf den Nutzer und die Gruppe von spamd gesetzt werden.

Bei der Abarbeitung sucht sich maillearn-c.phs das Home-Verzeichnis des PROCESS_USER aus der Datei "/etc/passwd" heraus und parameterisiert "sa-learn" so, dass die Daten anschließend in das richtige Verzeichnis importiert werden. Diese Parameterisierung kann durch DBPATH_* und PREFSPATH_* beeinflusst werden. Im Normalfall sollte das jedoch nicht notwendig sein.

Der Aufruf von maillearn-c.phs erfolgt gänzlich ohne Parameter. Auch hier steht es euch frei, den Aufruf nach Bedarf zu tätigen oder regelmäßig z.B. per CRON durchzuführen. Denkt daran, dass ihr maillearn-c.phs nur starten braucht, wenn vorher maillearn-s.phs auf dem anderen Server verwendet wurde:

1
sudo php maillearn-c.phs

Die Arbeit, die durch die beiden Scripte maillearn-s.phs und maillearn-c.phs verrichtet wird, ist überschaubar. Natürlich kann sie auch manuell oder durch andere kleine Scripte realisiert werden. Es steht euch wie immer frei, eigene Implementierungen zu verwenden. Ich persönlich mag es jedoch, dass diese Prozesse automatisiert ablaufen und mir - dank Pushinfo - mitteillen, wie ihr Status ist. :)

Puuuuuuh...

An dieser Stelle endet dann auch unsere kleine Exkursion in die Welt der Mailserveradministration. Wir haben gesehen, welche Komponenten für solch ein Vorhaben benötigt werden, wie diese aufeinander abgestimmt konfiguriert werden, in welche Zwickmühle man gerät, wenn man ein System mit höherer Ausfallsicherheit etablieren will und deshalb Daten hin- und her synchronisieren muss und wir haben uns angesehen, welche Themen sonst noch interessant sind - wie die Überwachung der Mailqueue, weiterführende DNS-Einträge, Whitelisten, Blacklisten und dergleichen.

Auch von mir fällt nun eine Last ab. Ich hatte vor, diese Artikelserie und die parallele Einrichtung meiner Server noch vor meinem Jahresendurlaub zu beenden. Darin enthalten sind etwa 1 Monat Bücher lesen, 2 Monate Internetrecherche samt Aufbau der einzelnen Konfigurationen, das Schreiben der eigentlichen Artikel und das Entwickeln der einzelnen Scripte (mailsync, mailconf, mailqueue, maillearn-c und maillearn-s) - das alles natürlich neben dem Vollzeitjob.

Ich hoffe, dass ihr ein wenig Spaß an dieser Artikelserie hattet und, dass sie einigen von euch hilft, ihren eigenen Mailserver aufzusetzen oder ihre vorhandene Konfiguration zu verbessern. Solltet ihr Fehler, Anmerkungen, Verbesserungsvorschläge oder Rückfragen haben, zögert nicht, einen Kommentar zu schreiben. ;)

Lehrende Grüße, Kenny

Mailserver 9 von 10: Mailqueue überwachen mit mailqueue.phs

Jahrelang habe ich mich davor gedrückt, doch endlich ist es geschafft - die Einrichtung eines eigenen Mailservers. In einer kleinen Artikelserie möchte ich einmal meine Erfahrungen und Konfigurationsschritte festhalten. Diese Serie basiert auf zahllosen Tutorials, Best Practices, Gesprächen mit Mailserver-Betreibern, aus endlosem Dokumentationen lesen und dem Wissen der Bücher "Postfix" von Kyle D. Dent und "Postfix - Einrichtung, Betrieb und Wartung" von Ralf Hildebrandt und Patrick Ben Koetter. Vielleicht werden sie ja nützlich für andere Leute sein, die das gleiche erreichen wollen.

Doch eines vorab: Die Einrichtung und der Betrieb eines Mailservers ist eine komplexe Sache. Klar, die Software lässt sich schnell installieren, doch fertig ist man danach noch lange nicht, wenn man ernsthaft damit arbeiten möchte.

Der Fahrplan der Artikelserie:

  1. Einleitung
  2. Mailempfang und Mailversand mit Dovecot und Postfix
  3. Virenprüfung mit ClamAV
  4. Mailsignatur mit OpenDKIM
  5. Spamprüfung mit SpamAssassin
  6. Mailabruf mit Dovecot
  7. Mailboxen konfigurieren mit mailconf.phs
  8. Mails synchronisieren mit mailsync.phs
  9. Mailqueue überwachen mit mailqueue.phs
  10. SpamAssassin anlernen mit maillearn.phs

Jeder, der ernsthaftes Interesse daran hat, einen Mailserver zu betreiben, sollte sich darauf gefasst machen, dass dadurch auch wiederkehrender Verwaltungsaufwand entsteht. Einer der ersten Punkte, denen ich mich dabei zugewandt habe, ist das Monitoren von deferred Nachrichten.

Deferred Nachrichten sind E-Mails, die aus irgendeinem Grund nicht zugestellt werden konnten und deshalb im Mailserver festhängen. Das kann z.B. passieren, wenn eine Mail von extern zwar empfangen wurde, aber nun nicht abgeliefert werden kann. Eine andere Möglichkeit ist, dass eine Mail verschickt werden sollte, der Zielserver jedoch nicht erreichbar ist. Um solche E-Mails muss man sich kümmern und zusehen, dass die Deferred-Queue nicht unnötig anwächst.

Zum Betrachten der Mailqueue bietet Postfix das Tool "postqueue", mit dem man sich einen Status über die einzelnen aktuell verarbeiteten Nachrichten ausgeben lassen kann:

1
sudo postqueue -p

Jedoch wollen wir uns ja nicht regelmäßig auf den Servern einloggen und den Status aktiv prüfen. Stattdessen wollen wir lieber informiert werden, wenn etwas vorgefallen ist: Genau aus diesem Grund habe ich mir das Script "mailqueue.phs" geschrieben.

Die Installation ist wie immer recht einfach: Wir benötigen PHP - mit CURL-Unterstützung - und Mercurial, um das entsprechende Script zu laden:

1
2
sudo apt-get update
sudo apt-get install php5-cli php5-curl mercurial

Anschließend können die benötigten Repositories abgerufen werden:

1
2
3
sudo hg clone https://hg.nhg.name/mailqueue/
sudo hg clone https://hg.nhg.name/pushinfo/
sudo hg clone https://hg.nhg.name/unchroot/

Bei dem Benachrichtigungsweg habe ich mich wieder für Pushinfo und den tollen Service von PushOver.net entschieden. Sobald ihr Pushinfo installiert und konfiguriert habt, sagt uns die README von mailqueue.phs, was wir weiter zu tun haben:

1
2
3
4
5
6
7
8
README:

1.) Copy all mailqueue.* files to a location that can not be accessed remotely.
2.) Install https://hg.nhg.name/pushinfo/
3.) Install https://hg.nhg.name/unchroot/
4.) Configure mailqueue.conf.phs and make sure that all paths are accessible.
5.) Configure CRON to call mailqueue.phs regularly:
    */5 * * * * root php /path/to/mailqueue.phs >/dev/null 2>&1

Die Konfiguration in der Datei "mailqueue.conf.phs" ist sehr übersichtlich. Wir müssen definieren, in welchem Ordner die deferred Nachrichten von Postfix liegen, wo die Nachrichten für Pushinfo abgelegt werden müssen, wo mailqueue.phs seinen Status ablegen kann, wo die Lockdatei hingeschrieben wird, um mehrfache Ausführungen zu verhindern und als welcher Nutzer der Status und die Pushinfo-Nachrichten geschrieben werden sollen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php

  # defines where the deferred mails of postfix are located
  # do not forget the trailing slash
  define("POSTFIX_DEFERRED", "/var/spool/postfix/deferred/");

  # defines where the push notifications are located
  define("PUSHINFO_PATH", "/srv/pushinfo/messages/");

  # defines where the script stores its status
  define("STATUS_PATH", "/srv/mailqueue/status/status");

  # define timeout for PHP execution (as int)
  # alternatively defines a lock file (as string)
  define("TIMEOUT", "/srv/mailqueue/status/lock");

  # defines the user the script shall run as
  define("PROCESS_USER", "mailqueue");

  # defines the group the script shall run as
  define("PROCESS_GROUP", "mailqueue");

  # defines the push message content
  define("PUSHINFO_MESSAGE",      " deferred messages found: ");
  define("PUSHINFO_MESSAGE_NEW",  " new, ");
  define("PUSHINFO_MESSAGE_OLD",  " old, ");
  define("PUSHINFO_MESSAGE_GONE", " gone");

?>

Wenn man alles eingerichtet hat, erhält man bei einem potentiellen Problemfall wunderschöne Push Notifications direkt auf sein Handy und kann angemessen auf alles reagieren. :)

mailqueue.phs Push Notification via Pushinfo und PushOver.net

mailqueue.phs Push Notification via Pushinfo und PushOver.net

Da wir gerade beim Thema Pflege sind: Ihr solltet zusehen, dass ihr euch um die Reputation eures Mailservers kümmert. Ein paar Schritte dahin hatten wir bereits unternommen. Zwei weitere würde ich euch noch empfehlen:

  1. Registriert euren Server auf DNSWL.org. Dabei handelt es sich um einen Whitelisting-Dienst, was bedeutet, dass andere Mailserver euch potentiell mehr vertrauen, wenn euer Mailserver in deren Liste aufgeführt wird. Die Eintragung ist kostenlos.
  2. Prüft regelmäßig, ob euer Server auf eine Blacklist geraten ist. Das kann - sollte es nicht behoben werden - dazu führen, dass euer Server keine E-Mails an andere Empfänger zustellen darf. Auf DNSBL.info könnt ihr z.B. prüfen lassen, ob euer Server in einer von (derzeit) 67 Blacklists aufgeführt ist.

Haltet euren Mailserver sauber, dann werdet ihr lange Freude an ihm haben. :)

Monitorende Grüße, Kenny

Mailserver 8 von 10: Mails synchronisieren mit mailsync.phs

Jahrelang habe ich mich davor gedrückt, doch endlich ist es geschafft - die Einrichtung eines eigenen Mailservers. In einer kleinen Artikelserie möchte ich einmal meine Erfahrungen und Konfigurationsschritte festhalten. Diese Serie basiert auf zahllosen Tutorials, Best Practices, Gesprächen mit Mailserver-Betreibern, aus endlosem Dokumentationen lesen und dem Wissen der Bücher "Postfix" von Kyle D. Dent und "Postfix - Einrichtung, Betrieb und Wartung" von Ralf Hildebrandt und Patrick Ben Koetter. Vielleicht werden sie ja nützlich für andere Leute sein, die das gleiche erreichen wollen.

Doch eines vorab: Die Einrichtung und der Betrieb eines Mailservers ist eine komplexe Sache. Klar, die Software lässt sich schnell installieren, doch fertig ist man danach noch lange nicht, wenn man ernsthaft damit arbeiten möchte.

Der Fahrplan der Artikelserie:

  1. Einleitung
  2. Mailempfang und Mailversand mit Dovecot und Postfix
  3. Virenprüfung mit ClamAV
  4. Mailsignatur mit OpenDKIM
  5. Spamprüfung mit SpamAssassin
  6. Mailabruf mit Dovecot
  7. Mailboxen konfigurieren mit mailconf.phs
  8. Mails synchronisieren mit mailsync.phs
  9. Mailqueue überwachen mit mailqueue.phs
  10. SpamAssassin anlernen mit maillearn.phs

Diejenigen von euch, die den Mailempfang und den Mailabruf auf einem einzelnen Server bereitstellen, können sich dieses Mal zurücklehnen, denn im heutigen Artikel geht es darum, empfangene Mails auf den Server zu synchronisieren, von dem die Mails auch tatsächlich abgerufen werden.

Hierfür gibt es die unterschiedlichsten Varianten: In einem Rechenzentrum könntet ihr z.B. eine zentrale Dateiablage (NAS oder SAN) verwenden. Ihr könnt eine Weiterleitung per SMTP einrichten (out-of-scope). Ihr könnt die Dateien händisch umher kopieren (langsam). Ihr könnt rsync verwenden. Oder ihr könnt euch etwas völlig eigenes überlegen.

Ich jedenfalls habe mich dazu entschlossen, mir dafür ein eigenes PHP-Script - mailsync.phs - zu schreiben. Der Vorteil daran: Ich kann es nach meinen eigenen Vorstellungen gestalten, Checks einbauen, wie ich lustig bin und Sortierungen vornehmen. In diesem Artikel möchte ich das Script einfach einmal vorstellen. Ob ihr es schlussendlich nutzen wollt, bleibt eure Entscheidung.

Im Grunde, nimmt uns die Wahl der Mailablage den Großteil der Arbeit ab. Maildir arbeitet so, dass es für jeden Mailordner immer drei Systemordner gibt: "cur", "new" und "tmp". Im Ordner "new" befinden sich neue E-Mails, im Ordner "cur" befinden sich gelesene E-Mails und im Ordner "tmp" befinden sich temporäre Dateien - z.B. E-Mails die gerade empfangen werden.

Darüber hinaus kann man - seit IMAP - auch spezielle Ordner anlegen. Da wäre der Entwurfsordner (meist ".Drafts"), der Gesendet-Ordner (meist ".Sent"), der Papierkorb (meist ".Trash") und der Spamorder (meist ".Junk"). Auch diese haben wieder jeweils die Unterordner "cur", "new" und "tmp".

Die Idee dahinter ist, dass z.B. die Lesemarkierung einer E-Mail oder das Löschen einer Nachricht einfach durch das Verschieben der zugehörigen Datei in einen anderen Ordner realisiert wird. Es müssen keine Inhalte gelesen oder neue Dateien geschrieben werden. Das verringert das Risiko, Dinge kaputt zu machen. Das macht es uns natürlich auch bei einer Synchronisation ziemlich leicht. Im Endeffekt muss man nur alle Maildateien von dem einen Server nehmen und auf den anderen Server transferieren. Da zudem der Hostname des jeweiligen Servers in dessen Dateinamen enthalten ist, kann es nicht einmal zu Kollisionen bei den Dateinamen kommen.

Genau diese naive Herangehensweise macht sich auch mailsync.phs zunutze: Es wird auf dem Abrufserver gestartet, baut eine SSH-Verbindung zum Empfangsserver auf, holt sich die Liste der neuen E-Mails, liest die E-Mails nacheinander ein und schreibt sie lokal in Dateien. Zum Schluss werden die erfolgreich kopierten Dateien auf dem Empfangsserver entweder gelöscht oder dahin verschoben, wo sie bei der nächsten Synchronisation nicht mehr stören.

Natürlich werden währenddessen ein paar Checks durchgeführt - wir wollen ja schließlich keine Mails kaputt machen. So wird z.B. die Dateigröße vor dem Einlesen und nach dem Wegschreiben verglichen. Zudem werden die Dateien im Ordner "tmp" zwischengespeichert, sodass die Checks ohne die Beeinflussung des Betriebs ablaufen können.
Es werden nur Mails verarbeitet, die die maximale Mailgröße nicht überschreiten (siehe "message_size_limit"-Einstellung von Postfix) und es besteht die Möglichkeit, bereits während der Synchronisation E-Mails mit Viren- oder Spambefund in den Spamordner einzusortieren.

Um mailsync.phs zu installieren und zu nutzen, müssen erst einmal ein paar Vorbereitungen getroffen werden. Zuerst müssen PHP und Mercurial installiert werden, falls ihr das nicht sowieso schon getan habt. Wir brauchen auch das PHP-Modul "ssh2", um SSH-Verbindungen zu unterstützen:

1
2
sudo apt-get update
sudo apt-get install php5-cli php5-curl php5-ssh2 mercurial

Anschließend müssen wir die entsprechenden Repositories abrufen:

1
2
3
sudo hg clone https://hg.nhg.name/mailsync/
sudo hg clone https://hg.nhg.name/pushinfo/
sudo hg clone https://hg.nhg.name/unchroot/

Die README gibt die ersten Schritte vor, die wir durchführen sollten:

1
2
3
4
5
6
7
8
9
10
11
12
README:

1.)  Copy all mailsync.* files to a location that can not be accessed remotely.
2.)  Install https://hg.nhg.name/pushinfo/
3.)  Install https://hg.nhg.name/unchroot/
4.)  Configure mailsync.conf.phs and make sure that all paths are accessible.
5.)  Configure mailsync.conf.example.phs and make sure that all paths are accessible.
6.)  mailsync.phs is called this way: sudo php mailsync.phs <user> <server>
6a.) mailsync.phs takes the configuration from mailsync.conf.<server>.phs
6b.) mailsync.phs copies the mail files via SFTP from /remote/path/<user> to /local/path/<user>
7.)  Configure CRON to call mailsync.phs regularly:
     */5 * * * * root php /path/to/mailsync.phs <user> <server> >/dev/null 2>&1

Mailsync.phs schickt euch Pushnachrichten auf's Handy, wenn während der Synchronisation einer E-Mail ein Fehler auftritt. Bei dem Benachrichtigungsweg habe ich mich für Pushinfo und den tollen Service von PushOver.net entschieden.

An dieser Stelle werde ich jedoch nur bzgl. der Konfiguration von mailsync.phs ins Detail gehen. Zuerst einmal: mailsync.phs ist so gestaltet, dass es prinzipiell die Synchronisation mehrerer Server unterstützt. Das ist so realisiert, dass die Konfiguration des Scripts in mehrere Dateien aufgebrochen werden kann. Per Default gibt es die beiden Dateien "mailsync.conf.phs" und "mailsync.conf.example.phs".

In der Datei "mailsync.conf.phs" befindet sich die Konfiguration, die für alle Synchronisationsvorgänge - egal mit welchem Server - identisch sein sollten. Das sind primär die ganzen lokalen Pfade, Header zum Erkennen von Spam und Viren, sowie die maximale Dateigröße. Beachtet, dass die synchronisierten Mails in den Speicher geladen werden. Das Memory-Limit für PHP-Prozesse sollte vorsichtshalber auf mindestens das ca. 2,5-fache der maximalen Mailgröße angehoben werden.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?php

  # defines the local absolute path to the mail home
 # do not forget the trailing slash
 define("LOCAL_ABSOLUTE_PATH", "/srv/mailusers/");

  # defines the local relative path to the SPAM maildir new
 # do not forget the leading and trailing slash
 define("LOCAL_RELATIVE_PATH_SPAM_NEW", "/Maildir/.Junk/new/");

  # defines the local relative path to the maildir new
 # do not forget the leading and trailing slash
 define("LOCAL_RELATIVE_PATH_NEW", "/Maildir/new/");

  # defines the local relative path to the maildir tmp
 # do not forget the leading and trailing slash
 define("LOCAL_RELATIVE_PATH_TMP", "/Maildir/tmp/");

  # defines if the retrieved mails are deleted or
 # moved to the remote ./cur folder
 define("DELETE_ON_SUCCESS", false);

  # defines if mails that failed to be synchronized
 # shall be synchronized again during the next
 # execution - if this is set to TRUE each failed
 # needs to be added to the RETRY_STATUS_PATH file
 # in order to be resynchronized - this helps to
 # prevent multiple retrievals and other problems
 # without prior handling by the administrator
 define("RETRY_ON_FAILURE", false);

  # defines the maximum mail size in bytes
 # should be bigger or equal to message_size_limit
 # of Postfix - remember to set memory_limit of PHP
 # to about 2.5 * MAX_MAIL_SIZE
 define("MAX_MAIL_SIZE", 52428800);

  # defines how mails containing spam are detected
 define("SPAM_HEADER_START", "X-Spam-Status: Yes");

  # defines how mails containing viruses are detected
 define("VIRUS_HEADER_START", "X-Virus-Status: Infected");

  # defines the push message content
 define("PUSHINFO_MESSAGE",      " mail synchronizations failed: ");
  define("PUSHINFO_MESSAGE_NEW",  " new, ");
  define("PUSHINFO_MESSAGE_OLD",  " old, ");
  define("PUSHINFO_MESSAGE_GONE", " gone");

?>

Die Dateien der Form "mailsync.conf.<x>.phs" wiederum enthalten die Konfigurationen der jeweiligen Server, mit denen die Synchronisation durchgeführt werden soll. Das sind primär die Verbindungsdaten, sowie die auf dem entfernten Server gültigen Pfade.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?php

  # define timeout for PHP execution (as int)
 # alternatively defines a lock file (as string)
 # lock file is relative to the LOCAL_ABSOLUTE_PATH
 # of the current user - do not forget leading slash
 define("TIMEOUT", "/lock.example");

  # defines where the script stores its status
 # status file is relative to the LOCAL_ABSOLUTE_PATH
 # of the current user - do not forget leading slash
 define("STATUS_PATH", "/status.example");

  # defines where the script looks for mails that
 # shall be synchronized again despite a previous
 # synchronization failure
 # retry status file is relative to the LOCAL_ABSOLUTE_PATH
 # of the current user - do not forget leading slash
 define("RETRY_STATUS_PATH", "/retry.example");

  # defines where the push notification is located
 define("PUSHINFO_PATH", "/srv/pushinfo/messages/mailsync.phs_example");

  # defines the remote absolute path to the mail home
 # do not forget the trailing slash
 define("REMOTE_ABSOLUTE_PATH", "/srv/mailusers/");

  # defines the remote relative path to the maildir cur
 # do not forget the leading and trailing slash
 define("REMOTE_RELATIVE_PATH_CUR", "/Maildir/cur/");

  # defines the remote relative path to the maildir new
 # do not forget the leading and trailing slash
 define("REMOTE_RELATIVE_PATH_NEW", "/Maildir/new/");

  # defines the remote hostname
 define("REMOTE_HOSTNAME", "<REPLACE-ME>");

  # defines the remote port
 define("REMOTE_PORT", 22);

  # defines the remote user
 define("REMOTE_USERNAME", "<REPLACE-ME>");

  # defines the remote password
 define("REMOTE_PASSWORD", "<REPLACE-ME>");

?>

Aufgerufen wird mailsync.phs immer wie folgt:

1
sudo php mailsync.phs <nutzer> <server>

Ich werde an dieser Stelle einmal versuchen, Schritt für Schritt zu erklären, wie mailsync.phs arbeitet, wenn es aufgerufen wird. Die angegebenen Pfade beziehen sich dabei auf die obige Beispielkonfiguration:

  1. Nachdem mailsync.phs gestartet wurde, prüft es, ob die Datei "mailsync.conf.<server>.conf" existiert. Falls das der Fall ist, wird sie eingebunden, um die serverspezifischen Konfigurationswerte zu erhalten.
  2. Es prüft, ob der Ordner "/srv/mailusers/<nutzer>" existiert. Zudem wird geprüft, ob die Ordner "/srv/mailusers/<nutzer>/Maildir/new", "/srv/mailusers/<nutzer>/Maildir/tmp" und "/srv/mailusers/<nutzer>/Maildir/.Junk/new" existieren.
  3. Falls das der Fall ist, liest das Script die Nutzer- und Gruppenberechtigung des Ordners "/srv/mailusers/<nutzer>" aus und verringert seine Prozessprivilegien auf diesen Nutzer und diese Gruppe.
  4. Anschließend wird die Lock-Datei "/srv/mailusers/<nutzer>/lock.<server>" erzeugt, um Mehrfachstarts des Scripts zu verhindern (beachtet den Parameter TIMEOUT!).
  5. Nun wird die SSH-Verbindung zum Remote-Host mit dem entsprechenden Benutzernamen und Passwort aufgebaut.
  6. Wenn das funktioniert hat, wird auf dem Remote-Host der Inhalt des Ordner "/srv/mailusers/<nutzer>/Maildir/new" ausgelesen. Jede Datei in diesem Ordner entspricht einer empfangenen E-Mail.
  7. Nun werden die E-Mails einzeln durchgearbeitet.
  8. Es wird geprüft, ob die E-Mails schon einmal synchronisiert werden sollten und dabei einen Fehler verursacht haben (was in der Datei STATUS_PATH festgehalten wird). An dieser Stelle gibt es die Möglichkeit, dass die Dateien erneut synchronisiert werden (wenn RETRY_ON_FAILURE auf true gesetzt ist). Alternativ werden die Dateien übersprungen, wenn sie nicht explizit in der Datei RETRY_STATUS_PATH aufgelistet sind. Das soll sich wiederholende Fehler bei der Synchronisation verhindern.
  9. Für die Dateien, die synchronisiert werden sollen, wird die Dateigröße abgerufen und geprüft, ob diese kleiner oder gleich dem Wert MAX_MAIL_SIZE sind.
  10. Die einzelnen Dateien werden eingelesen und in den Ordner "/srv/mailusers/<nutzer>/Maildir/tmp" geschrieben. Nach dem Schreiben wird zudem geprüft, ob die geschriebenen Dateien die gleiche Größe haben, wie die vormals eingelesenen Dateien.
  11. Nach diesem Schritt erfolgt die Einsortierung in den Posteingang oder aber in den Spamordner. E-Mails, die einen Header mit dem Inhalt von SPAM_HEADER_START oder VIRUS_HEADER_START enthalten, gelten als Spam. Alle anderen wandern in den Posteingang.
  12. Mails, die in den Posteingang gehören, werden in den Ordner "/srv/mailusers/<nutzer>/Maildir/new" verschoben. Mails, die als Spam einsortiert werden, gelangen stattdessen in den Ordner "/srv/mailusers/<nutzer>/Maildir/.Junk/new"
  13. Erfolgreich bearbeitete Dateien werden auf dem Remote-Host entweder gelöscht, oder aber dort in den Ordner "/srv/mailusers/<nutzer>/Maildir/cur" verschoben. Dies wird durch den Wert DELETE_ON_SUCCESS eingestellt.
  14. Wenn die Synchronisation beendet ist, wird abschließend die Lock-Datei "/srv/mailusers/<nutzer>/lock.<server>" wieder entfernt.

Nach dem Konfigurieren des Scripts müsst ihr nur noch dafür sorgen, dass es auch regelmäßig für alle eure Nutzer aufgerufen wird. Dafür könnt ihr z.B. einen Cronjob einrichten, der alle paar Minuten läuft. Je seltener das Script arbeitet, desto länger müsst ihr potentiell auf den Erhalt einer E-Mail warten:

1
*/5 * * * * root php /path/to/mailsync.phs <user> <server> >/dev/null 2>&1

Wie gesagt: Es ist ein einfaches Script, das sich die Ablageform der E-Mails stark zu Nutze macht und naiv seine Arbeit verrichtet. Das Thema der serverübergreifenden Synchronisation ist eines für sich, mit vielen Ansätzen und unendlich vielen Möglichkeiten. Welche Lösung ihr an dieser Stelle verwendet, bleibt am Ende ganz euch selbst überlassen. :)

Update:
mailsync.phs kann inzwischen Push Notifications mit Hilfe von Pushinfo und dem Dienst PushOver.net versenden. Zudem werden E-Mails, bei denen eine Synchronisation fehlgeschlagen ist, nicht mehr zwingend erneut synchronisiert. Das soll Mehrfachzustellungen und andere Probleme verhindern.

Synchronisierende Grüße, Kenny

Mailserver 7 von 10: Mailboxen konfigurieren mit mailconf.phs

Jahrelang habe ich mich davor gedrückt, doch endlich ist es geschafft - die Einrichtung eines eigenen Mailservers. In einer kleinen Artikelserie möchte ich einmal meine Erfahrungen und Konfigurationsschritte festhalten. Diese Serie basiert auf zahllosen Tutorials, Best Practices, Gesprächen mit Mailserver-Betreibern, aus endlosem Dokumentationen lesen und dem Wissen der Bücher "Postfix" von Kyle D. Dent und "Postfix - Einrichtung, Betrieb und Wartung" von Ralf Hildebrandt und Patrick Ben Koetter. Vielleicht werden sie ja nützlich für andere Leute sein, die das gleiche erreichen wollen.

Doch eines vorab: Die Einrichtung und der Betrieb eines Mailservers ist eine komplexe Sache. Klar, die Software lässt sich schnell installieren, doch fertig ist man danach noch lange nicht, wenn man ernsthaft damit arbeiten möchte.

Der Fahrplan der Artikelserie:

  1. Einleitung
  2. Mailempfang und Mailversand mit Dovecot und Postfix
  3. Virenprüfung mit ClamAV
  4. Mailsignatur mit OpenDKIM
  5. Spamprüfung mit SpamAssassin
  6. Mailabruf mit Dovecot
  7. Mailboxen konfigurieren mit mailconf.phs
  8. Mails synchronisieren mit mailsync.phs
  9. Mailqueue überwachen mit mailqueue.phs
  10. SpamAssassin anlernen mit maillearn.phs

Langsam aber sicher befinden wir uns auf der Zielgeraden unserer Mailservereinrichtung. Wir können inzwischen Mails empfangen (und auf Spam und Viren prüfen), Mails versenden (und signieren, sowie auf Spam und Viren prüfen) und wir können E-Mails abrufen. Nun wird es endlich Zeit, unsere Mailkonten einzurichten.

In den vorherigen Artikeln hatte ich jeweils beispielhaft die Inhalte der Konfigurationslisten gezeigt, die benötigt werden, um die einzelnen Komponenten (Postfix, Dovecot und OpenDKIM) startklar zu machen. Leider ist diese verteilte Einrichtung mit Hilfe von Listen sehr zeitraubend und fehleranfällig. Deshalb hatte ich mir überlegt, wie man das ganze etwas vereinfachen könnte: Dabei heraus gekommen ist "mailconf.phs".

mailconf.phs ist ein PHP-Script, das mit Hilfe einer einzigen Konfigurationdatei die ganzen Teillisten erzeugt. Mit einer relativ einfachen Syntax kann man so alles weitere abbilden und kann die Ausgangsinformationen zusammenhalten.

Um es nutzen zu können, sollte man es natürlich im ersten Schritt installieren. Es wird das PHP Commandline Interface (PHP-CLI) benötigt. Zudem solltet ihr euch Mercurial installieren, um mailconf.phs direkt aus dem Repository zu laden.

1
2
sudo apt-get update
sudo apt-get install php5-cli mercurial

Dann könnt ihr euch das Repository mit einem einfachen Clone-Befehl besorgen:

1
2
sudo hg clone https://hg.nhg.name/mailconf/
sudo hg clone https://hg.nhg.name/unchroot/

Danach solltet ihr euch als erstes natürlich die Datei "README" durchlesen. Schritt 1 und Schritt 2 sind bereits erledigt. Schritt 3 und Schritt 4 werde ich euch jetzt versuchen, etwas näher zu bringen.

1
2
3
4
5
6
README:

1.) Copy all mailconf.* files to a location that can not be accessed remotely
2.) Install https://hg.nhg.name/unchroot/
3.) Write configuration file which defines the content of the generated lists.
4.) Generate lists by calling: sudo php mailconf.phs <Configuration-File-Name>

Wie schon erwähnt, müsst ihr eine Konfigurationsdatei für mailconf.phs erstellen. Ich werde erst einmal versuchen, die Syntax zu erklären. Anschließend sehen wir uns dann das Beispiel aus der Datei "EXAMPLE" an.

Die Form der Konfigurationsdatei ist stark an "*.ini"-Dateien angelehnt. Es gibt immer einen Kopf, der mit eckigen Klammern eingeleitet wird und darunter die eigentlichen Einstellungen, wobei erst der Name der Einstellung, dann ein Gleichheitszeichen und dann der Wert folgt. Kommentare werden mit Rauten eingeleitet:

1
2
3
# Beispielkommentar
[bli]
bla = blub

Das erste, was wir konfigurieren sollten, sind natürlich die Domains, für die unser Mailserver zuständig sein soll. Dazu setzen wir einfach einen Kopf und schreiben dort den Namen der jeweiligen Domain hinein:

1
2
# definiert die Domain "example.com"
[example.com]

Wie wir im Artikel über Mailsignaturen mit OpenDKIM gesehen haben, kann einer Domain ein sogenannter Selektor zugewiesen sein, der angibt, welcher DKIM-Schlüssel für das Signieren von E-Mails verwendet werden soll. Diesen Selektor können wir an dieser Stelle den Domains zuweisen:

1
2
3
4
# definiert die Domain "example.com"
[example.com]
# definiert den Selektor der Domain "example.com"
selector = send2014

Neben den Domains müssen natürlich auch die eigentlichen E-Mail-Adressen definiert werden. Das machen wir, indem wir im Kopf einfach die Adresse selbst eintragen. Dabei stellt mailconf.phs automatisch sicher, dass nur Adressen verwendet werden, zu denen auch die entsprechende Domain definiert wurde:

1
2
3
4
5
6
7
# definiert die Domain "example.com"
[example.com]
# definiert den Selektor der Domain "example.com"
selector = send2014

# definiert die Addresse "root@example.com"
[root@example.com]

Mit einer Adresse kann man jedoch noch nicht allzu viel anfangen. Man muss sich entscheiden, ob es sich um eine Adresse handeln soll, die mit einer Mailbox verknüpft ist oder aber ob es eine reine Weiterleitung ist. Im folgenden Beispiel legen wir die Weiterleitung "root@example.com" an und die Mailbox "kenny@example.com". Mailboxen sind dadurch gekennzeichnet, dass sie ein Passwort besitzen:

1
2
3
4
5
6
7
8
9
10
11
12
# definiert die Domain "example.com"
[example.com]
# definiert den Selektor der Domain "example.com"
selector = send2014

# definiert die Weiterleitung "root@example.com"
[root@example.com]
inout = kenny@example.com

# definiert die Mailbox "kenny@example.com"
[kenny@example.com]
password = {SSHA256}/ZdbEwfJtC1fSkuVkisIHGnSNyqhSJwgQvu2Hb2JoeiBC+lw

Bei der Weiterleitung dürfte euch die Einstellung "inout" auffallen. Diese besagt, dass die dahinter stehende Mailbox zum einen die E-Mails der Weiterleitungsadresse empfängt und auch E-Mails im Namen der Weiterleitungsadresse versenden darf. Bei solchen Einstellungen prüft mailconf.phs automatisch, ob der Empfänger der Weiterleitung eine lokale Adresse ist. Falls das der Fall ist, wird zudem geprüft, ob die Empfängeradresse definiert wurde und ob es sich dabei um eine Mailbox handelt.
Anstelle von "inout" kann auch zwischen "in" und "out" getrennt werden. "in" heißt immer, dass Mails an den entsprechenden Account weitergeleitet werden. "out" heißt immer, dass Mails von dem entsprechenden Account verschickt werden dürfen. Es können pro Adresse auch mehrere "in", "out" und "inout" Angaben gemacht werden.

Was auch auffällig sein dürfte, ist die Form des Passworts des Accounts "kenny@example.com". Wir hatten uns in den letzten Artikeln dafür entschieden, dass Dovecot seine Passworte als Salted Hashes ablegt. Genau diese Schreibweise benötigen wir nun hier. Mit folgendem Befehl könnt ihr passende Passworte erzeugen:

1
doveadm pw -s SSHA256

Wir werden nun noch einen weiteren Account anlegen - und zwar einen reinen Versandaccount. Solche Accounts können nützlich sein, wenn z.B. technische Geräte E-Mails versenden sollen. Da diese Geräte keine Mails lesen können, sollten die Mails an solch eine Adresse natürlich an eine andere Mailbox weitergeleitet werden:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# definiert die Domain "example.com"
[example.com]
# definiert den Selektor der Domain "example.com"
selector = send2014

# definiert die Weiterleitung "root@example.com"
[root@example.com]
inout = kenny@example.com

# definiert die Mailbox "kenny@example.com"
[kenny@example.com]
password = {SSHA256}/ZdbEwfJtC1fSkuVkisIHGnSNyqhSJwgQvu2Hb2JoeiBC+lw

# definiert die Mailbox "submit@example.com"
[submit@example.com]
password = {SSHA256}gLNtzgEM6m6IacJ+goE8kARoUnx2WiviqXv9336/3lTfcY+y
in       = kenny@example.com

Die Mailboxen "kenny@example.com" und "submit@example.com" haben das gleiche Passwort - dank der Salted Hashes ist das jedoch nicht erkennbar. Zudem werden im Beispiel alle Mails für "submit@example.com" an "kenny@example.com" weitergeleitet.
Solltet ihr irgendwann wollen, dass die Mails für "submit@example.com" auch tatsächlich an diese Mailbox zugestellt werden, könnt ihr das mit einer Selbstreferenz ("in = *") erreichen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# definiert die Domain "example.com"
[example.com]
# definiert den Selektor der Domain "example.com"
selector = send2014

# definiert die Weiterleitung "root@example.com"
[root@example.com]
inout = kenny@example.com

# definiert die Mailbox "kenny@example.com"
[kenny@example.com]
password = {SSHA256}/ZdbEwfJtC1fSkuVkisIHGnSNyqhSJwgQvu2Hb2JoeiBC+lw

# definiert die Mailbox "submit@example.com"
[submit@example.com]
password = {SSHA256}gLNtzgEM6m6IacJ+goE8kARoUnx2WiviqXv9336/3lTfcY+y
in       = kenny@example.com
in       = *

Eine Selbstreferenz für das Versenden von E-Mails ("out = *") ist für Mailboxen jedoch nie nötig. Sie wird implit immer erstellt. Mit anderen Worten: Mailboxen dürfen immer E-Mails in ihrem eigenen Namen senden.

Nachdem wir nun also definiert haben, welche Adressen es gibt, stellt sich die Frage, wie wir bestimmen, welche Dateien erstellt werden und wohin sie geschrieben werden. Für dieses Thema gibt es den Konfigurationsblock. Er wird mit einem leeren Kopf gekennzeichnet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# definiert die Domain "example.com"
[example.com]
# definiert den Selektor der Domain "example.com"
selector = send2014

# definiert die Weiterleitung "root@example.com"
[root@example.com]
inout = kenny@example.com

# definiert die Mailbox "kenny@example.com"
[kenny@example.com]
password = {SSHA256}/ZdbEwfJtC1fSkuVkisIHGnSNyqhSJwgQvu2Hb2JoeiBC+lw

# definiert die Mailbox "submit@example.com"
[submit@example.com]
password = {SSHA256}gLNtzgEM6m6IacJ+goE8kARoUnx2WiviqXv9336/3lTfcY+y
in       = kenny@example.com
in       = *

# hier beginnt die Konfiguration:
[]

Dateien werden geschrieben, indem entsprechende Dateitrigger definiert werden. Dateitrigger beginnen immer mit dem Begriff "file.", gefolgt von dem Namen der Komponente, für die die Datei erstellt werden soll ("dovecot", "opendkim", "postfix") und der Einstellung, für die die Datei erzeugt werden soll. Die Liste der möglichen Trigger sieht aktuell wie folgt aus:

  • file.dovecot.passwdfile
  • file.opendkim.ExternalIgnoreList
  • file.opendkim.InternalHosts
  • file.opendkim.KeyTable
  • file.opendkim.SigningTable
  • file.postfix.smtpd_sender_login_maps
  • file.postfix.virtual_alias_maps
  • file.postfix.virtual_gid_maps
  • file.postfix.virtual_mailbox_domains
  • file.postfix.virtual_mailbox_maps
  • file.postfix.virtual_uid_maps

Zudem müssen wir immer eine User-ID und eine Group-ID angeben, mit der mailconf.phs laufen soll. Da wir hier Konfigurationsdateien schreiben, verhindern wir damit, dass wir uns wichtige Dateien zerschießen, bzw. nur Konfigurationsdateien schreiben, deren Schreibrechte wir entsprechend gesetzt haben.

Wenn wir also beispielsweise die Liste der Domains für Postfix erstellen lassen wollen, können wir das ganze so steuern (unter der Annahme, dass der Nutzer "mailconf" existiert und Schreibrechte für die Datei hat):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# definiert die Domain "example.com"
[example.com]
# definiert den Selektor der Domain "example.com"
selector = send2014

# definiert die Weiterleitung "root@example.com"
[root@example.com]
inout = kenny@example.com

# definiert die Mailbox "kenny@example.com"
[kenny@example.com]
password = {SSHA256}/ZdbEwfJtC1fSkuVkisIHGnSNyqhSJwgQvu2Hb2JoeiBC+lw

# definiert die Mailbox "submit@example.com"
[submit@example.com]
password = {SSHA256}gLNtzgEM6m6IacJ+goE8kARoUnx2WiviqXv9336/3lTfcY+y
in       = kenny@example.com
in       = *

# hier beginnt die Konfiguration:
[]
# wir schreiben die Postfix Domainliste
file.postfix.virtual_mailbox_domains = /etc/postfix/domains.conf

# wir arbeiten als Nutzer mailconf mit der Gruppe mailconf
uid = mailconf
gid = mailconf

Die Konfigurationsdateien lasst ihr dann mit folgendem Befehl erzeugen:

1
sudo php mailconf.phs <Dateiname>

Mit zwei weiteren Zeilen können wir die Liste der Mailboxen und die Liste der Aliasse schreiben lassen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# definiert die Domain "example.com"
[example.com]
# definiert den Selektor der Domain "example.com"
selector = send2014

# definiert die Weiterleitung "root@example.com"
[root@example.com]
inout = kenny@example.com

# definiert die Mailbox "kenny@example.com"
[kenny@example.com]
password = {SSHA256}/ZdbEwfJtC1fSkuVkisIHGnSNyqhSJwgQvu2Hb2JoeiBC+lw

# definiert die Mailbox "submit@example.com"
[submit@example.com]
password = {SSHA256}gLNtzgEM6m6IacJ+goE8kARoUnx2WiviqXv9336/3lTfcY+y
in       = kenny@example.com
in       = *

# hier beginnt die Konfiguration:
[]
# wir schreiben die Postfix Aliasliste
file.postfix.virtual_alias_maps      = /etc/postfix/aliases.conf
# wir schreiben die Postfix Domainliste
file.postfix.virtual_mailbox_domains = /etc/postfix/domains.conf
# wir schreiben die Postfix Mailboxliste
file.postfix.virtual_mailbox_maps    = /etc/postfix/mailboxes.conf

# wir arbeiten als Nutzer mailconf mit der Gruppe mailconf
uid = mailconf
gid = mailconf

Nunja. Zumindest fast. Einige der Dateitrigger benötigen weitere Parameter. Welche das sind, wird euch bei der Ausführung durch eine entsprechende Fehlermeldung mitgeteilt, wenn es sich um Pflichtparameter handelt. Parameter beginnen immer mit dem Begriff "param.", gefolgt von dem Namen der Komponente, für die die Datei erstellt werden soll ("dovecot", "opendkim", "postfix") und der Einstellung, für die die Datei erzeugt werden soll.

Im obigen Beispiel müssen wir dem Dateitrigger "file.postfix.virtual_mailbox_maps" mitteilen, wie der relative Pfad zum Maildir-Ordner heißt. Das machen wir über den Parameter "param.postfix.virtual_mailbox_maps":

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# definiert die Domain "example.com"
[example.com]
# definiert den Selektor der Domain "example.com"
selector = send2014

# definiert die Weiterleitung "root@example.com"
[root@example.com]
inout = kenny@example.com

# definiert die Mailbox "kenny@example.com"
[kenny@example.com]
password = {SSHA256}/ZdbEwfJtC1fSkuVkisIHGnSNyqhSJwgQvu2Hb2JoeiBC+lw

# definiert die Mailbox "submit@example.com"
[submit@example.com]
password = {SSHA256}gLNtzgEM6m6IacJ+goE8kARoUnx2WiviqXv9336/3lTfcY+y
in       = kenny@example.com
in       = *

# hier beginnt die Konfiguration:
[]
# wir schreiben die Postfix Aliasliste
file.postfix.virtual_alias_maps      = /etc/postfix/aliases.conf
# wir schreiben die Postfix Domainliste
file.postfix.virtual_mailbox_domains = /etc/postfix/domains.conf
# wir schreiben die Postfix Mailboxliste
file.postfix.virtual_mailbox_maps    = /etc/postfix/mailboxes.conf

# relativer Pfad zum Maildir einer Mailbox
param.postfix.virtual_mailbox_maps = Maildir/

# wir arbeiten als Nutzer mailconf mit der Gruppe mailconf
uid = mailconf
gid = mailconf

Nun könnt ihr die Konfigurationdateien erstellen lassen:

1
sudo php mailconf.phs <Dateiname>

In der Datei "EXAMPLE" könnt ihr euch sämtliche Dateitrigger mit ihren Pflichtparametern und ihren optionalen Parametern ansehen. Auch die Funktionsweise des Konfigurationsblocks ist dort noch einmal ein wenig ausführlicher beschrieben:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# defines a domain
[example.com]

# defines the DKIM selector of that domain
selector = send2014

# defines an address
# defined addresses must be within a defined domain
[kenny@example.com]

# password of that address
# addresses with passwords are assumed to be mailboxes
password = test

# UID of that address
# only mailboxes need UIDs as these have to be owned by a system user
uid = mail_kenny

# implicitly a mailbox is always allowed to send and receive mails of itself
# inout = *

# GID of that address
# only mailboxes need GIDs as these have to be owned by a system user
gid = mail_kenny

# defines another address
[submit@example.com]

# password of that address
# addresses with passwords are assumed to be mailboxes
password = test

# mails sent to that address will be forwarded to an external address
in = submit@example.net

# mails sent to that address will also be forwarded to another internal mailbox
# that mailbox is also allowed to send mails on behalf of this address
inout = kenny@example.com

# whenver forwards are defined for a mailbox a forward to the mailbox itself
# has to be defined - this makes it possible to define send-only accounts
in = *

# implicitly a mailbox is always allowed to send mails on behalf of itself
# out = *

# defines yet another address
[postmaster@example.com]

# just a plain internal forward without send-privileges
in = kenny@example.com

# the empty bracket defines the configuration block
[]

# mailconf works as follows:
# Each file output format is implemented in a file
# "mailconf.<x>.phs". These files are triggered by
# defining the value "file.<x>" and assigning it an
# output file name. In addition these files may
# require additional configuration parameters which
# are defined with "param.<x>.<y>" whereby ".<y>" may
# be omitted depending on the output implementation
# (e.g. when only a single configuration parameter is
# required). Export files shall warn you when a
# mandatory configuration parameter has not been set.
#
# If you do not want to create a specific file then
# just comment out the corresponding "file.<x>" line.
# The corresponding "param.<x>.<y>" can stay intact.
# They will just be ignored.
#
# By specifying a "file.<x>" more that once that file
# will be generated several times (e.g. when one file
# is needed in different locations).

# dovecot configuration files
file.dovecot.passwdfile = /etc/dovecot/auth/accounts

# OpenDKIM configuration files
file.opendkim.ExternalIgnoreList = /etc/opendkim/trusted.conf
#file.opendkim.InternalHosts     = /etc/opendkim/trusted.conf
file.opendkim.KeyTable           = /etc/opendkim/keys.conf
file.opendkim.SigningTable       = /etc/opendkim/domains.conf

# Postfix configuration files
file.postfix.smtpd_sender_login_maps = /etc/postfix/logins.conf
file.postfix.virtual_alias_maps      = /etc/postfix/aliases.conf
file.postfix.virtual_gid_maps        = /etc/postfix/gids.conf
file.postfix.virtual_mailbox_domains = /etc/postfix/domains.conf
file.postfix.virtual_mailbox_maps    = /etc/postfix/mailboxes.conf
file.postfix.virtual_uid_maps        = /etc/postfix/uids.conf

# default uid for mailboxes (optional)
param.dovecot.passwdfile.uid = vmail

# default gid for mailboxes (optional)
param.dovecot.passwdfile.gid = vmail

# home path for mailboxes (optional)
# should match with Postfix virtual_mailbox_base
#param.dovecot.passwdfile.home = /srv/mailusers/

# value of userdb_mail (optional)
# default value: maildir:~/Maildir
#param.dovecot.passwdfile.userdb_mail = maildir:~/Maildir

# path to DKIM private keys (mandatory)
param.opendkim.KeyTable = /etc/opendkim/keys/

# value of Postfix home_mailbox (mandatory)
# default value: Maildir/
param.postfix.virtual_mailbox_maps = Maildir/

# default uid for mailboxes (mandatory)
param.postfix.virtual_uid_maps = vmail

# default gid for mailboxes (mandatory)
param.postfix.virtual_gid_maps = vmail

# UID and GID of mailconf.phs process (mandatory)
uid = mailconf
gid = mailconf

Auch wenn ich das Thema gern vermeiden würde, da es schwer zu vermitteln ist, muss ich es leider anschneiden: Auch Mailboxen haben eine User-ID und eine Group-ID. Das sind der Nutzer und die Gruppe, unter denen die Maildateien abgelegt werden.

Unser Setup sieht bisher vor, dass Postfix statisch den Nutzer "vmail" samt der Gruppe "vmail" verwendet, um die Maildateien zu schreiben und passende Ordner anzulegen. Im späteren Verlauf will man aber jedoch vielleicht, dass die Maildateien jeder Mailbox unter einem eigenen Account abgelegt werden. Dazu muss für jede definierte Mailbox ("kenny@example.com", "submit@example.com", etc.) eine UID und GID angegeben werden. Für Mailboxen, bei denen das vergessen wurde, wird die Default-UID und die Default-GID verwendet, die im Konfigurationsblock angegeben werden.

Ich habe es bei mir z.B. so gemacht, dass bei Mailadressen der Form "<name>@<domain>" der zugehörige Systemnutzer immer "mail_<name>" heißt (also bei "kenny@example.com" z.B. "mail_kenny").

Solltet ihr euch bei dem Thema Zugriffsrechte auf Nutzer- und Gruppenebene nicht auskennen, muss ich euch dringend anraten, euch mit diesem Thema auseinanderzusetzen. Damit steht und fällt die Sicherheit der von euch betriebenen Server.

Hoffentlich konnte ich euch die Funktionsweise und Notation von mailconf.phs ein wenig näher bringen. Sollte euch die Metasprache von mailconf.phs nicht zusagen, könnt ihr natürlich auch einfach wie bisher die Dateien einzeln per Hand erstellen. Jetzt bei den Beispielen mag es sehr überborden aussehen. Je mehr Domains und Mailadressen jedoch hinzukommen, desto nützlicher ist das Tool. Mir persönlich ist das Script jedenfalls eine große Hilfe bei anfallenden Änderungen im laufenden Betrieb.

Konfigurierende Grüße, Kenny

Mailserver 6 von 10: Mailabruf mit Dovecot

Jahrelang habe ich mich davor gedrückt, doch endlich ist es geschafft - die Einrichtung eines eigenen Mailservers. In einer kleinen Artikelserie möchte ich einmal meine Erfahrungen und Konfigurationsschritte festhalten. Diese Serie basiert auf zahllosen Tutorials, Best Practices, Gesprächen mit Mailserver-Betreibern, aus endlosem Dokumentationen lesen und dem Wissen der Bücher "Postfix" von Kyle D. Dent und "Postfix - Einrichtung, Betrieb und Wartung" von Ralf Hildebrandt und Patrick Ben Koetter. Vielleicht werden sie ja nützlich für andere Leute sein, die das gleiche erreichen wollen.

Doch eines vorab: Die Einrichtung und der Betrieb eines Mailservers ist eine komplexe Sache. Klar, die Software lässt sich schnell installieren, doch fertig ist man danach noch lange nicht, wenn man ernsthaft damit arbeiten möchte.

Der Fahrplan der Artikelserie:

  1. Einleitung
  2. Mailempfang und Mailversand mit Dovecot und Postfix
  3. Virenprüfung mit ClamAV
  4. Mailsignatur mit OpenDKIM
  5. Spamprüfung mit SpamAssassin
  6. Mailabruf mit Dovecot
  7. Mailboxen konfigurieren mit mailconf.phs
  8. Mails synchronisieren mit mailsync.phs
  9. Mailqueue überwachen mit mailqueue.phs
  10. SpamAssassin anlernen mit maillearn.phs

Nachdem wir im letzten Artikel das letzte Mal Hand an den Mailempfang und Mailversand gelegt haben, wird es dieses Mal Zeit, dass der Nutzer seine E-Mails auch tatsächlich abrufen kann. Dazu werden wir Dovecot verwenden, der bereits früher zum Einsatz kam.

In meinem Fall habe ich einen separaten Server, auf den empfangene Mails synchronisiert werden, daher muss ich Dovecot ein zweites Mal vollständig installieren. Solltet ihr Mailabruf und Mailempfang/Mailversand auf einem Server vereinen, braucht ich lediglich die Deltas übernehmen.

Wir beginnen also damit, dass wir Dovecot installieren und anschließend stoppen. Mit dabei sind auch die Anteile von Dovecot, die sich um das IMAP(S)- und das POP3(S)-Protokoll kümmern:

1
2
3
sudo apt-get install dovecot-common dovecot-imapd dovecot-pop3d

sudo /etc/init.d/dovecot stop

Anschließend entschlacken wir wieder die Default-Konfiguration, indem wir nicht benötigte Dateien und Ordner löschen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sudo rm /etc/dovecot/dovecot-db.conf.ext
sudo rm /etc/dovecot/dovecot-dict-sql.conf.ext
sudo rm /etc/dovecot/dovecot-ldap.conf.ext
sudo rm /etc/dovecot/dovecot.pem
sudo rm /etc/dovecot/dovecot-sql.conf.ext
sudo rm /etc/dovecot/README

sudo rm -R /etc/dovecot/private/

sudo rm /etc/dovecot/conf.d/auth-checkpassword.conf.ext
sudo rm /etc/dovecot/conf.d/auth-deny.conf.ext
sudo rm /etc/dovecot/conf.d/auth-ldap.conf.ext
sudo rm /etc/dovecot/conf.d/auth-master.conf.ext
sudo rm /etc/dovecot/conf.d/auth-sql.conf.ext
sudo rm /etc/dovecot/conf.d/auth-static.conf.ext
sudo rm /etc/dovecot/conf.d/auth-system.conf.ext
sudo rm /etc/dovecot/conf.d/auth-vpopmail.conf.ext

Nun erstellen wir wieder die zusätzlich benötigten Dateien. Beachtet den Ordner "/etc/dovecot/tls/" - dieses Mal werden wir wieder ein TLS-Zertifikat benötigen. Die Webserver-Zertifikate von StartSSL leisten auch hier gute Dienste.

1
2
3
4
5
6
7
8
9
sudo mkdir /etc/dovecot/auth/
sudo touch /etc/dovecot/auth/accounts

sudo mkdir /etc/dovecot/tls/

sudo adduser vmail

sudo mkdir /srv/mailusers/
sudo chown vmail:vmail /srv/mailusers/

Kommen wir zu den Einstellungen in der Datei "/etc/dovecot/dovecot.conf". Hier aktivieren wir nun zusätzlich die Protokolle IMAP(S) und POP3(S). Beachtet auch, dass wir nun auf einer extern erreichbaren Adresse lauschen. Ihr müsst an dieser Stelle "<127.0.0.1>" und "<::1>" durch die IPv4- und IPv6-Adresse ersetzen, unter der euer Server erreichbar ist:

1
2
3
4
5
6
7
!include_try /usr/share/dovecot/protocols.d/*.protocol

listen = <127.0.0.1>, <::1>, 127.0.0.1, ::1

login_greeting = Mailserver welcomes you.

!include /etc/dovecot/conf.d/*.conf

Weiter geht es mit der Datei "/etc/dovecot/conf.d/10-auth.conf". Diese sieht genauso aus wie in unserem vorherigen Setup:

1
2
3
4
5
6
7
auth_default_realm = <example.com>

auth_username_chars = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@

auth_mechanisms = plain login

!include auth-passwdfile.conf.ext

Dieses Mal legen wir jedoch auch Hand an die Datei "/etc/dovecot/conf.d/10-mail.conf", in der wir festlegen, dass wir das Maildir-Format zur Ablage verwenden werden:

1
2
3
4
5
mail_location = maildir:~/Maildir

namespace inbox {
  inbox = yes
}

In der Datei "/etc/dovecot/conf.d/10-master.conf" wird es nun spannend. Dort aktivieren wir IMAPS und POP3S, deaktivieren aber das unverschlüsselte IMAP und POP3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
service imap-login {
  inet_listener imap {
    port = 0
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }
}

service pop3-login {
  inet_listener pop3 {
    port = 0
  }
  inet_listener pop3s {
    port = 995
    ssl = yes
  }
}

service lmtp {
}

service imap {
}

service pop3 {
}

service auth {
  chroot = /etc/dovecot/auth/
}

service auth-worker {
  user = $default_internal_user

  chroot = /etc/dovecot/auth/
}

service dict {
}

Solltet ihr den Mailversand und den Mailabruf über dieselbe Dovecot-Installation abwickeln wollen, müsst ihr beim "service auth {}"-Block aufpassen. Ihr wollt ja nicht, dass jemand von außen einfach die Logins durchtesten kann. Daher müsst ihr diesen wie folgt abändern, damit er nur noch vom lokalen Rechner aus erreichbar ist:

1
2
3
4
5
6
7
8
9
service auth {
  inet_listener {
    address = 127.0.0.1 ::1

    port = 10000
  }

  chroot = /etc/dovecot/auth/
}

Dieses Mal aktivieren wir auch endlich TLS in der Datei "/etc/dovecot/conf.d/10-ssl.conf". Dabei deaktivieren wir SSLv2 sowie SSLv3 und beschränken die unterstützten Ciphersuits:

1
2
3
4
5
6
7
8
ssl = yes

ssl_cert = </etc/dovecot/tls/<receive_example_com>.crt
ssl_key  = </etc/dovecot/tls/<receive_example_com>.key

ssl_protocols = !SSLv2 !SSLv3

ssl_cipher_list = HIGH:!aNULL:!eNULL:!3DES:!MD5:!RC4:@STRENGTH

Das IMAP-Protokoll gibt dem Nutzer die Möglichkeit, seine Mails in verschiedenen Ordnern zu organisieren. Dabei gibt es ein paar spezielle Ordner (z.B. die Inbox, den Gesendet-Ordner, den Papierkorb, etc.). Diese speziellen Ordner definieren wir nun in der Datei "/etc/dovecot/conf.d/15-mailboxes.conf":

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
namespace inbox {
  mailbox Drafts {
    auto = subscribe

    special_use = \Drafts
  }
  mailbox Junk {
    auto = subscribe

    special_use = \Junk
  }
  mailbox Trash {
    auto = subscribe

    special_use = \Trash
  }
  mailbox Sent {
    auto = subscribe

    special_use = \Sent
  }
  mailbox "Sent Messages" {
    special_use = \Sent
  }
}

Abschließend definieren wir in der "/etc/dovecot/conf.d/auth-passwdfile.conf.ext" wieder, dass die Nutzercredentials aus der Datei "/etc/dovecot/auth/accounts" stammen und woher die E-Mails abgerufen werden sollen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
valid_chroot_dirs = /srv/mailusers/

passdb {
  driver = passwd-file
  args = scheme=SSHA256 username_format=%u /accounts
}

userdb {
  driver = passwd-file
  args = username_format=%u /accounts

  default_fields  = uid=vmail gid=vmail
  override_fields = home=/srv/mailusers/%n/./
}

Im Gegensatz zum letzten Mal verwenden wir für die "userdb" nun ebenfalls die Passwd-Datei. Aus dieser lesen wir z.B. die User-ID und die Group-ID, unter der die Maildateien abgelegt sind. Natürlich setzen wir sinnvolle Default-Werte, falls die entsprechenden Angaben in der Passwd-Datei fehlen sollten.

Nun muss die Passwd-Datei noch mit Inhalten befüllt werden. Werte, die in der Datei fehlen, werden durch die Werte in "default_fields" ergänzt, bzw. durch die Werte in "override_fields" ersetzt:

1
2
3
# username:password:uid:gid::home::userdb_mail=maildir:~/Maildir

kenny@example.com:{SSHA256}lsj7m9rKhS/T7Onyu2hSFZnGFNfG9erhNbNK6XNcftLiv1wk

Da zwischen dem Mailempfang und dem Mailabruf eine Synchronisation liegen wird, werden wir in diesem Synchronisierungsschritt die Zugriffsrechte für die Maildateien anpassen. Solltet ihr jedoch beides auf dem gleichen Server ausführen, wäre es unsinnig, dort extra eine Synchronisation vorzunehmen.

In dem Fall habt ihr zwei Möglichkeiten: Entweder, ihr verwendet weiterhin die userdb-Einstellungen vom letzten Mal (mit dem "static"-Driver) und "vmail" als Standard-Maildateibesitzer, oder aber ihr gebt Postfix ebenfalls diese Besitzerinformationen in Form einer UID- und GID-Liste.

Solltet ihr die UID- und GID-Liste bevorzugen, könnt ihr wie folgt vorgehen. Erst einmal muss in der Datei "/etc/postfix/main.cf" folgende Änderung vorgenommen werden:

1
2
virtual_uid_maps = hash:/etc/postfix/uids.conf
virtual_gid_maps = hash:/etc/postfix/gids.conf

Diese Dateien müsst ihr natürlich erstellen und anschließend mit Inhalt füllen:

1
2
sudo touch /etc/postfix/uids.conf
sudo touch /etc/postfix/gids.conf

In der Datei "/etc/postfix/uids.conf" wird jeder Mailbox-Addresse eine UID zugewiesen, während in der Datei "/etc/postfix/gids.conf" jeder Mailbox-Adresse eine GID zugewiesen wird.

Nehmen wir beispielsweise an, wie erzeugen für die Mailbox-Adresse "kenny@example.com" einen neuen Systemnutzer mit dem Namen "mail_kenny". Dann müssen wir uns von diesem die UID und die GID besorgen:

1
2
3
4
sudo adduser mail_kenny

id -u mail_kenny
id -g mail_kenny

Die Zuweisung der UID zur Mailbox-Adresse nehmen wir dann in der Datei "/etc/postfix/uids.conf" vor:

1
2
3
# address -> UID

kenny@example.com <UID>

Die Zuweisung der GID zur Mailbox-Adresse nehmen wir hingegen in der Datei "/etc/postfix/gids.conf" vor:

1
2
3
# address -> GID

kenny@example.com <GID>

Aus den beiden Dateien müssen nach jeder Änderung wieder "*.db"-Dateien erzeugen, damit Postfix sie verwenden kann. Zudem muss anschließend die Postfix-Konfiguration neu eingelesen werden:

1
2
3
4
sudo postmap /etc/postfix/uids.conf
sudo postmap /etc/postfix/gids.conf

sudo /etc/init.d/postfix reload

Wenn ihr das alles umgesetzt habt, wird es Zeit, Dovecot wieder zu starten:

1
sudo /etc/init.d/dovecot start

Damit haben wir alles entscheidende soweit eingerichtet, dass man prinzipiell damit arbeiten könnte. Was fehlt, ist bei einem Setup mit mehreren Servern die Synchronisation, damit empfangene Mails auch tatsächlich abgerufen werden können. Dieses Thema werden wir in einem späteren Artikel betrachten.

Bevor man jedoch E-Mails senden, empfangen und abrufen kann, muss man erst einmal die Listendateien mit den entsprechenden Domains, Adressen, Passwörtern, DKIM-Schlüssel, etc. anlegen. Leider kommen dabei unterschiedlichste Formate zum Einsatz, mit oft redundanten Inhalten.
Um diese gesamte Konfiguration ein wenig zu vereinfachen und fehlerfreier zu gestalten, habe ich "mailconf" geschrieben, was einem die meiste Arbeit abnimmt. Dieses Script werde ich beim nächsten Mal etwas genauer vorstellen.

Empfangene Grüße, Kenny

Seite 1 von 84123...Letzte »