Wir setzen auf den meisten unserer Server qmail bzw. netqmail als MTA ein und erfreuen uns dabei an den vielen Vorzügen, die das Maildir-Format bietet. Zwar kommt dabei meistens ein zusätzliches Tool wie vpopmail oder vmailmgr zum Tragen, was virtualisierte Mailuser bietet; auf unserer Hosting-Plattform Uberspace.de bieten wir aber ganz offiziellen Support für ein „echtes“ Maildir des betreffenden Systemusers. Die netqmail-Dokumentation erläutert dazu in INSTALL.maildir:
The system administrator can set up Maildir as the default for everybody by creating a maildir in the new-user template directory and replacing ./Mailbox with ./Maildir/ in /var/qmail/rc.
Und so sieht das Setup bei uns dann auch aus: Ein /var/qmail/bin/maildirmake /etc/skel/Maildir
legt ein Standard-Maildir an, was beim Anlegen eines neuen Users automatisch in dessen Home-Verzeichnis übertragen wird, und qmail-local
stellt Mails, die an den Systemuser adressiert sind, dorthin zu.
Nicht völlig überraschend zeigt sich aber, dass traditionelle Mailboxen in einem zentralen Verzeichnis wie z.B. /var/spool/mail
derart fest im Betriebssystem verankert sind, dass es mehr als einen Klimmzug braucht, das System sauber an Maildirs anzupassen. Das fängt schon ganz vorne an:
useradd
Beim Anlegen von Benutzern wird standardmäßig eine (leere) Mailbox in /var/spool/mail/$USER
angelegt, bzw. in dem Verzeichnis, das in der /etc/login.defs
(siehe dort) via MAIL_DIR
angegeben ist. Maildirs werden aber nicht unterstützt; genausowenig Mailboxen, die nicht in einem zentralen Verzeichnis liegen, sondern im Home-Verzeichnis des Benutzers. Dieses Anlegen lässt sich nur über die Einstellung CREATE_MAIL_SPOOL=no
in der /etc/default/useradd
abschalten – was hier ja durchaus Sinn ergibt, denn durch das Anlegen eines Maildirs in /etc/skel
haben wir diesen Punkt ohnehin erledigt. (Mit herkömmlichen Mailboxen funktionierte das nicht, da /etc/skel
ja die Vorlage für das Home-Verzeichnis des Users ist, die herkömmlichen Mailboxen aber zentralisiert und damit außerhalb des Home-Verzeichnisses liegen.)
Diese Umgebungsvariable wird von verschiedenen Programmen benutzt, um zu identifizieren, wo denn die Mails eines Users liegen. Hier fackelt CentOS 5 nicht lange – in /etc/profile
steht hart kodiert:
if [ -x /usr/bin/id ]; then USER="`id -un`" LOGNAME=$USER MAIL="/var/spool/mail/$USER" fi
Das ist für unsere Zwecke ergo völlig unbrauchbar. Die /etc/profile
selbst anzupassen, empfiehlt sich nicht, weil die Änderungen sonst bei jedem Update des setup
-RPMs (zu dem diese Datei gehört) hinfällig wären. Stattdessen bietet sich ein Einzeiler in /etc/profile.d
an:
# cat /etc/profile.d/maildir.sh export MAIL=~/Maildir/
/etc/login.defs
Die man page der login.defs
erklärt offenherzig:
Much of the functionality that used to be provided by the shadow password suite is now handled by PAM. Thus, /etc/login.defs is no longer used by programs such as: login(1), passwd(1), su(1)
Trotzdem ist die Datei noch da und wird von einigen Programmen genutzt. Sie sieht im Kopf wie folgt aus:
# *REQUIRED* # Directory where mailboxes reside, _or_ name of file, relative to the # home directory. If you _do_ define both, MAIL_DIR takes precedence. # QMAIL_DIR is for Qmail # #QMAIL_DIR Maildir MAIL_DIR /var/spool/mail #MAIL_FILE .mail
Fängt man erstmal an, an dieser Datei – vermutlich erfolglos – herumzubasteln, bekommt man wirklich graue Haare. Die naheliegendste Variante, nämlich den Eintrag QMAIL_DIR
durch Entfernen des Rautenzeichens zu aktivieren, ist überraschenderweise keine gute Idee; dass die man page diese Einstellung gar nicht erwähnt, lässt schon tief blicken. So sieht’s dann nämlich aus:
# useradd dummy configuration error - unknown item 'QMAIL_DIR' (notify administrator)
Fan-tas-tisch. Die NEWS
-Datei der shadow-utils erklärt denn auch, dass die Einstellung aus der login.defs entfernt wurde – und zwar 2005. Interessanterweise kennt die man page auch die Einstellung MAIL_FILE
nicht, sondern ausschließlich MAIL_DIR
. Sie weiß aber auch gleich zu verkünden, dass nur usermod
und userdel
diese Einstellung benutzen – und useradd
sowieso nicht. Was aber sehen wir in src/useradd.c
?
if (strcasecmp (create_mail_spool, "yes") == 0) { spool = getdef_str ("MAIL_DIR") ? : "/var/mail"; file = alloca (strlen (spool) + strlen (user_name) + 2); sprintf (file, "%s/%s", spool, user_name); fd = open (file, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0); [...] }
Ist also glatt gelogen; useradd benutzt die Einstellung sehr wohl. Die man page von useradd
bekräftigt das auch und erwähnt nicht nur MAIL_DIR
, sondern auch MAIL_FILE
und behauptet:
The MAIL_DIR and MAIL_FILE variables are used by useradd, usermod, and userdel to create, move, or delete the user´s mail spool.
Das ist nun wiederum auch gelogen, denn wenn MAIL_FILE
statt MAIL_DIR
gesetzt ist, macht useradd
damit … überhaupt nichts. Und auch usermod
und userdel
, die beim Löschen eines Users dessen Mailbox aus dem zentralen mit MAIL_DIR
angegebenen Verzeichnis löschen, unternehmen in Bezug auf Mail schlicht gar nichts, wenn MAIL_FILE
gesetzt ist.
Nun, noch weiter in die Tiefe wollen wir hier nicht gehen. Belassen wir es dabei, dass das, was in der /etc/login.defs
steht, das, was in der zugehörigen man page steht, das, was in den man pages von useradd
, usermod
und userdel
steht, und schließlich das, was im Code der shadow-utils steht, erheblich voneinander abweicht und sich oftmals sogar widerspricht – kurz, das Ganze funktioniert nur dann sauber, wenn man exakt den traditionellen Standard benutzt: Mailboxen in einem zentralen Verzeichnis.
mailx
CentOS benutzt das mailx
-Paket, um den Befehl mail
bereitzustellen. Die meisten kennen den Befehl vornehmlich zu dem Zweck, um auf der Kommandozeile direkt Mails via Pipe versenden zu können (some-command | mail recipient@domain.tld
). Allerdings ist mail auch ein Mailreader, der auf die Umgebungsvariable MAIL
zurückgreift – was von daher erstaunlich ist, weil diese Variable gerade nicht zu denen gehört, die mail
laut man page konsultiert:
Mail utilizes the HOME, USER, SHELL, DEAD, PAGER, LISTER, EDITOR, VISUAL and MBOX environment variables.
Trotzdem wird sie benutzt und zeigt dann auch gleich, wieso hier ohnehin Hopfen und Malz verloren ist:
$ mail /home/jonas/Maildir/: Is a directory
Das mailx
-Paket von CentOS hat also schlicht keinen Maildir-Support. Mit dem aktualisierten Paket, das sich in CentOS 6 findet, wird das offenbar kein Problem mehr sein, aber darum soll es hier ja nicht gehen.
bash
Hier endlich mal ein Lichtblick: Die bash unterstützt die Umgebungsvariable MAIL
und kann auch korrekt mit Maildirs umgehen. Sie benutzt es, um standardmäßig alle 60 Sekunden nach neuen Mails zu suchen und den Benutzer zu informieren, und das klappt auch:
$ echo | mail $USER ; sleep 60 ; true You have new mail in /home/jonas/Maildir/
PAM
Möchte man auch direkt beim SSH-Login über neue Mails informiert werden, so kann dies zeitgemäß mit pam_mail.so
erledigt werden. Dazu braucht’s nur eine Zeile (danach sshd
-Neustart nicht vergessen, sonst wirkt es nicht):
$ tail -1 /etc/pam.d/sshd session optional pam_mail.so dir=~/Maildir
Die Angabe von dir ist nötig, weil pam_mail.so
ansonsten ganz traditionell in /var/mail
nach einer Mailbox oder einem Maildir sucht (mit anderen Worten: Überraschung! Dass evtl. ein anderes Verzeichnis als MAIL_DIR
in /etc/login.defs
definiert ist, spielt überhaupt keine Rolle). Es erkennt automatisch, ob es eine Mailbox oder ein Maildir ist, denn eine Mailbox wäre ja eine Datei, während ein Maildir ein Verzeichnis wäre. So sieht es dann in der Anwendung aus:
$ ssh jonas@helium.uberspace.de You have new mail in folder /home/jonas/Maildir.