Version und Aktualität

Dies ist Version vom 21.05.2007.

Vorbemerkungen

Dies ist ein Howto um unter Debian Etch ein Mailsystem basierend auf Exim 4 und Courier IMAP unter der Verwendung von PostgreSQL aufgesetzt. Dabei geschieht die komplette Kommunikation zum SMTP als auch zum IMAP-Server verschlüsselt mittels SMTP-TLS und IMAP-SSL.

Darüberhinaus kann man bei dieser Konfiguration eine Catch-All-Emaildresse definieren, zu der alle Mails geschickt werden, die sonst nicht zugestellt werden würden.

Debian-Etch sollte bereits installiert sind und die Standardtools, wie der präferierte Texteditor, sollten ebenfalls bereits installiert sein.

Basierend auf folgender Seite wurde die Installation versucht. Dabei wurde gleich von MySQL auf PostgreSQL umgestellt und nur auf Exim 4 eingegangen, sowie der Catch-All-Benutzer hinzugefügt.

Paketanforderungen

Es werden folgende Debian-Etch-Pakete benötigt:
  • exim4-daemon-heavy
  • courier-imap-ssl
  • courier-authlib-postgresql
  • postgresql-8.1

PostgreSQL konfigurieren

Ich habe eine PostgreSQL-Rolle mit dem Benutzername mail und Passwort mail erstellt und danach eine Datenbank mit dem Namen mail:

su - postgres
createuser -S -D -R -P -E mail
createdb -O mail -E UTF8 mail

Das Schema der PostgreSQL-Datenbank sieht folgendermaßen aus (Inhalt in eine Datei namens schema.sql schreiben):

CREATE TABLE users (
  id               varchar(128) DEFAULT '' NOT NULL,
  crypt            varchar(128) DEFAULT '' NOT NULL,
  clear            varchar(128) DEFAULT '' NOT NULL,
  name             varchar(128) DEFAULT '' NOT NULL,
  domain           varchar(128) DEFAULT '' NOT NULL,
  uid              int DEFAULT 100 NOT NULL,
  gid              int DEFAULT 65534 NOT NULL,
  home             varchar(255) DEFAULT '' NOT NULL,
  maildir          varchar(255) DEFAULT '' NOT NULL,
  defaultdelivery  varchar(255) DEFAULT '' NOT NULL,
  quota            varchar(255) DEFAULT '' NOT NULL,
  CONSTRAINT id PRIMARY KEY (id)
);

Die uid muß der System-Uid des Debian-Exim-Benutzers entsprechen. Um dies zu überprüfen, bitte folgendes Komanndo ausführen:

grep exim /etc/passwd | cut -d ":" -f 3

Mittels psql -h localhost -W mail mail < schema.sql wird die Datei in die Datenbank eingeladen.

Das Crypt-Feld ist ein normaler Crypt-Hash. Eine Datenbankzeile könnte wie folgt aussehen:

INSERT INTO users
  (id, domain, crypt, clear, name, home, maildir )
  VALUES (
    'andi@meinedomain.de','meinedomain.de',
    'egwe2OmCViJUI','andi','andi',
    '/Mail/meinedomain.de/andi',
    '/Mail/meinedomain.de/andi/Maildir'
  );

INSERT INTO users
  (id, domain, crypt, clear, name, home, maildir )
  VALUES (
    '*@meinedomain.de','meinedomain.de',
    'egwe2OmCViJUI','andi','all',
    '/Mail/meinedomain.de/all',
    '/Mail/meinedomain.de/all/Maildir'
  );

Danach muß nurnoch das Verzeichnis angelegt werden und die richtigen Rechte bekommen:

mkdir -p /Mail/meinedomain.de/andi
chown -R Debian-exim /Mail

Courier einrichten

Als nächstes wird courier eingerichtet. Dabei muß man in der Datei /etc/courier/authdaemonrc folgender Eintrag hinzugefügt oder geändert werden:

authmodulelist="authpgsql"

Danach wird die authpgsqlrc im selbigen Verzeichnis editiert und sieht danach wie folgt aus:

PGSQL_HOST          localhost
PGSQL_PORT          5432
PGSQL_USERNAME      mail
PGSQL_PASSWORD      mail
PGSQL_DATABASE      mail
PGSQL_USER_TABLE    users
PGSQL_CRYPT_PWFIELD crypt
PGSQL_UID_FIELD     uid
PGSQL_GID_FIELD     gid
PGSQL_LOGIN_FIELD   id
PGSQL_HOME_FIELD    home
PGSQL_NAME_FIELD    name
PGSQL_MAILDIR_FIELD maildir
PGSQL_QUOTA_FIELD   quota

Achtung: Es sollten hinter den Konfigurationseinstellungen keine Leerzeichen existieren! Nach dem Eintragen und Verifizieren der Konfigurationsdatei sollte der Authentifizierungsdienst neugestartet werden:

/etc/init.d/courier-authdaemon restart

Ein Maildirverzeichnis sollte nun exemplarisch für einen Benutzer angelegt werden. Die sollte nach dem Zustellen der ersten Mail automatisch erledigt werden und muß nicht für jeden Nutzer manuell geschehen:

maildirmake.courier /Mail/meinedomain.de/andi/Maildir

Danach sollte man die Zugriffsrechter wieder neu setzen:

chown -R Debian-exim /Mail

Nun ist es an der Zeit zu überprüfen ob die Konfiguration funktioniert. Dies kann man mit einem Mailclient tun, der IMAP über SSL unterstützt: z.B. Mutt mit folgenden Einstellungen (~/.muttrc)

set imap_user="andi@meinedomain.de" 
set imap_authenticators="login" 
set imap_passive="YES" 
set imap_keepalive=600

set mbox=imaps://localhost/INBOX
set spoolfile=imaps://localhost/INBOX

Nun einfach mutt in die Konsole eingeben, danach das Passwort eingeben und schon sollte mutt ohne Fehlermeldung eine leere Mailbox zeigen.

Exim konfigurieren

Die Exim-Konfiguration liegt im Verzeichnis /etc/exim4/conf.d/. Zuerst muß man die Konfiguration auf “Verteilt” stellen mittels:

dpkg-reconfigure exim4-config

In dem erwähnten Konfigurationsdateizweig muß man nun einige Dateien ändern:

Authentifizierungseinstellungen in auth/30_exim4-config_examples wie folgt ändern:

  • Alle Einträge einkommentieren
  • Eintrag plain_courier_authdaemon und login_courier_authdaemon von Zeile 144 bis 172 auskommentieren, sodaß dies die einzigen “richtigen” Zeilen in der Konfigurationsdatei sind.

Hauptkonfigurationseinstellungen in main/01_exim4-config_listmacrosdefs eintragen:

  • Exim PostgreSQL/TLS-tauglich machen und folgende Zeilen am besten direkt oben einfügen und diese Datei nur für den Exim-Benutzer auf lesbar setzen:
#hide pgsql_servers = host/database/user/password
hide pgsql_servers = localhost/mail/mail/mail

MAIN_TLS_ENABLE = true
  • Danach muß man Exim anweisen, Mails für die in der Datenbank definierten Domains anzunehmen:
domainlist local_domains = @:localhost:\
    pgsql;SELECT DISTINCT domain FROM users where domain = '$domain'

Nun erstellt man eine neue Datei namens router/350_exim4-config_pgsql_aliases und fügt diese Zeilen ein:

pgsql_aliases:
    debug_print = "R: pgsql_aliases for $local_part@$domain" 
    driver = redirect
    allow_fail
    allow_defer
    domains = pgsql;SELECT DISTINCT domain FROM users
    data = ${lookup pgsql{ \
        SELECT maildir FROM users \
        WHERE id = '$local_part@$domain' OR \
              id = '*@$domain' ORDER BY maildir DESC \
        LIMIT 1 }}
    directory_transport = address_directory
    file_transport = pgsql_maildir_home
    cannot_route_message = Unknown user
    no_more

Als Abschluß wird nun noch ein Transport in der Datei transport/30_exim4-config_maildir_home hinzugefügt:

pgsql_maildir_home:
    driver = appendfile
    group = mail
    mode = 660
    mode_fail_narrower = false
    envelope_to_add = true
    return_path_add = true
    directory = ${lookup pgsql{\
      SELECT maildir FROM users WHERE \
      id = '$local_part@$domain' OR \
      id = '*@$domain' ORDER BY maildir DESC \
      LIMIT 1 }}
    maildir_format

Der Mailempfang sollte nun funktionieren. Das Verschicken von Mails via SMTP-TLS sollte ja auch funktionieren. Hierfür muss zuerst ein SSL-Zertifikat erstellt werden. Danach soll Exim neugestartet werden.

cd /etc/exim4
/usr/share/doc/exim4-base/examples/exim-gencert
/etc/init.d/exim4 restart

Danach muß noch der Courier-Authentifizierer so eingestellt werden, daß Exim (alle) darauf lesen kann:

chmod 755 /var/run/courier/authdaemon

Testen

Zum Debuggen des Routings einer Mailadresse kann man folgenden Befehl verwenden:

exim -bt -d 9 andi@meinedomain.de 2>&1 | less

Dieses Kommando wirft bei mir das richtige Verzeichnis aus:

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Considering /Mail/meinedomain.de/andi/Maildir
andi@meinedomain.de -> /Mail/meinedomain.de/andi/Maildir
  transport = pgsql_maildir_home
search_tidyup called
close PGSQL connection: localhost/mail/mail
>>>>>>>>>>>>>>>> Exim pid=5996 terminating with rc=2 >>>>>>>>>>>>>>>>

Eine Testmail können wir – wie eben – mit mutt erstellen und danach schauen, ob die Mail zugestellt wurde:

echo "Test" | mutt -s test andi@meinedomain.de && tail -n 3 /var/log/exim4/mainlog
2007-04-10 17:27:42 1HbIFy-0001Zq-DI => /Mail/meinedomain.de/andi/Maildir \
       <andi@meinedomain.de> R=pgsql_aliases T=pgsql_maildir_home
2007-04-10 17:27:42 1HbIFy-0001Zq-DI Completed
2007-04-10 17:27:46 1HbIG2-0001a4-Dg <= root@ U=root P=local S...

Das selbige sollte noch mit dem Catch-All-Benutzer funktionieren (stark verkürze Programmausgabe):

exim -bt -d 9 gibts-net@meinedomain.de
   gibts-net@meinedomain.de -> /Mail/meinedomain.de/all/Maildir
   transport = pgsql_maildir_home

Sowie mutt und der daraus resultierende Log-Eintrag:

echo "Test" | mutt -s test gibts-net@meinedomain.de
<= root@ U=root P=local ...
=> /Mail/meinedomain.de/all/Maildir <gibts-net@meinedomain.de> \
    R=pgsql_aliases T=pgsql_maildir_home

Abschluß

Im Prinzip sollte diese Anleitung perfekt funktionieren. Dies ist bereits die 2. Überarbeitung, die nun auch endlich mal funktionieren sollte. Jedoch machen Menschen Fehler – ja auch ich – und so kann es immer passieren, daß noch etwas falsch ist. Wie dem auch sei wäre es gut, wenn man mir die Fehler meldet und ich dieses How-To überarbeiten kann.

Nachtrag

Ich habe nun schon einige Meinungen – alle positiv – zu diesem HowTo bekommen. Jedoch hat der eine oder andere nach einem Programm gefragt, mit dessen Hilfe man die Passwörter für die Datenbank schreiben kann. Ich habe zum Erstellen meines verwendeten Passwortes das Skript der Quellseite verwendet. Es ist in Perl geschrieben und tut seinen Dienst. Hier eine stark verkürztes, aber dennoch lauffähigs Perl-Programm:

#!/usr/bin/perl
print crypt($ARGV[0], (join '', ('.', '/', 0..9,'A'..'Z', 'a'..'z')[rand 64, rand 64])) ."\n";

Es gibt ein Debian-Paket, mit dem man die Crypto-Funktionen in Postgresql nutzen kann postgresql-contrib-8.1. Danach sollte man die Readme-Datei studieren und die Crypto-Funktionen wie gewünscht in die Datenbank importieren.