Utilisez Postfix

La machine utilisée pour tester la configuration décrite ici tourne sous le système d'exploitation Debian GNU / Linux, version slink régulièrement mise à jour. La distribution a peu d'importance. Qu'il s'agisse d'une Red Hat, d'une Slackware, d'une SuSE, ou de tout autre distribution, ce qui est décrit ci-après devrait s'appliquer à peu de modification près (pour peu même qu'il y en ait). Notons que des paquetages précompilés existent : la Debian, notamment, permet d'installer directement le programme via dpkg. Le problème, avec ces paquetages, est qu'ils ne permettent pas de suivre les fréquents changements du logiciel. Or, celui-ci étant en phase de développement, les nouvelles versions ajoutent de nouvelles fonctionnalités souvent fort intéressantes ...

Concernant les autres Unix, il n'y a aucune raison pour que le fonctionnement soit différent : la documentation cite d'ailleurs une liste de tous les systèmes supportés. Je n'ai personnellement vu aucune différence entre l'installation sous Linux et sous FreeBSD (si ce n'est la différence de gestion des scripts d'initialisation sur ces deux systèmes). La distribution officielle de Postfix peut être récupérée sur son site officiel, www.postfix.org ou sur l'un des sites mirroirs français.

Il ne sera pas traité ici de la récupération du courrier venant de l'extérieur (du serveur de courrier de son fournisseur d'accès si l'on est, comme moi, relié via une connexion téléphonique). Pour cela, d'autres documentations existent, consultez notamment le site www.linux-france.org.

Installation de Postfix

Compilation

Le logiciel se récupère sous la forme d'un fichier .tar.gz que l'on décompresse dans un répertoire d'installation :

# tar xvzf postfix-19990906-pl02.tar.gz -C /tmp
# cd /tmp/postfix-19990906-pl02/

Dans ce répertoire se trouve un fichier INSTALL fort clair (mais en anglais) qu'il suffit de suivre pas à pas pour installer et configurer Postfix. La première étape consiste à générer les exécutables :

# make

Puis, il reste à déplacer les fichiers binaires, de configuration et les pages de manuel dans les répertoires adéquats de votre système. Sous le répertoire d'installation, vous devez normalement avoir les répertoires conf, bin, libexec, html et man (les autres répertoires sont ceux contenant les sources, des exemples et les fichiers objets générés par la compilation).

Installation de la documentation

Pour installer les pages de manuel, il suffit de déplacer le contenu des répertoires /tmp/postfix-19990906-pl02/man/man* dans les répertoires correspondants sur votre système (/usr/man/man*, sur une machine Linux). Puis, vous pouvez installer le reste de la documentation. Pour rester compatible avec les autres documentations des autres logiciels de mon système Linux, j'ai créé un répertoire /usr/doc/postfix dans lequel j'ai déplacé tous les fichiers de documentation du répertoire d'installation (leurs noms sont en majuscules). J'ai également créé le répertoire /usr/doc/postfix/html et y ait déplacé le contenu du répertoire html de l'installation.

Installation des fichiers de configuration

Sous Linux, tous ces fichiers vont dans un seul emplacement : /etc/postfix. Je me bornerai ici à suivre ce qui est indiqué dans INSTALL :

# mkdir /etc/postfix
# chmod 0755 /etc/postfix
# mv /tmp/postfix-19990906-pl02/conf/* /etc/postfix
# chmod 0644 /etc/postfix/*
# chmod 0755 /etc/postfix/postfix-script*

Création des files d'attentes

Postfix utilise une arborescence beaucoup plus élaborée que celle de ses prédécesseurs pour placer les messages en attente de délivrance. Il suffit ici d'en indiquer la racine (/var/spool/postfix/, généralement) car tous les autres sous-répertoires y seront créés lors du premier démarrage de Postfix.

# mkdir /var/spool/postfix
# chmod 0755 /var/spool/postfix

Vous pouvez choisir un autre emplacement : celui-ci devra être indiqué lors de la configuration que nous étudions plus loin.

Installation des exécutables

Là encore, vous êtes libres de choisir l'emplacement qui vous convient car il suffira ensuite de l'indiquer lors de la configuration. La méthode généralement pratiquée consiste à séparer les commandes des démons : les premières sont initialement dans le répertoire bin et iront dans /usr/sbin (ou /usr/local/sbin avec des liens de /usr/sbin vers eux), les seconds sont initialement dans libexec /usr/libexec/postfix (ou /usr/local/libexec/postfix).

# cd /tmp/postfix-19990906-pl02/bin
# cp post* sendmail /usr/local/sbin
# mkdir /usr/local/libexec/postfix
# cp `ls *|egrep -v `post|fsstone|smtp|sendmail' `/usr/local/libexec/postfix

Droits d'accès à la file d'attente

Il s'agit ici de permettre l'accès des utilisateurs locaux au répertoire /var/spool/postfix/maildrop. Par défaut, tous les sous-répertoires de /var/spool/postfix appartiennent au groupe root. Or, lorsque les utilisateurs postent un courrier, celui-ci transite d'abord par le répertoire maildrop. Avec les droits actuels, ces courriers seraient refusés.

Plusieurs possibilités, décrites dans le fichier INSTALL, sont permises : rendre le répertoire maildrop accessible à tout le monde ou utiliser la commande postdrop en sgid. C'est la première solution que nous avons retenue. Pour ce faire, il suffit de modifier les droits d'accès du répertoire maildrop :

# chmod 1733 /var/spool/postfix/maildrop

Cette solution suppose que vous ayez confiance en vos utilisateurs locaux ... Si ce n'est pas le cas, préférez-lui la solution du postdrop en sgid (décrite dans le fichier INSTALL). L'invocation de la commande postdrop lors de l'envoi d'un message est réalisée automatiquement via l'appel du script postfix-script qu'il s'agit donc de rendre accessible à tout le monde :

# cp /etc/postfix/postfix-script-nosgid /etc/postfix/postfix-script

Première configuration

Oublier Sendmail !

Pour que Postfix devienne votre agent de transport de courrier, vous devrez probablement désactiver Sendmail. Même si vous ne l'avez jamais activé ou configuré, il y a fort à parier que ce dernier ait été installé par votre distribution Linux !

Pour cela, il suffit de suivre ce que propose le fichier INSTALL :

# cd /usr/bin
# mv sendmail sendmail.OFF
# ./sendmail.OFF -q
# mv /usr/bin/newaliases /usr/bin/newaliases.OFF
# mv /usr/bin/mailq /usr/bin/mailq.OFF
# chmod 0 /usr/sbin/sendmail.OFF
/usr/bin/newaliases.OFF \
        /usr/bin/mailq.OFF
# ln -s /usr/local/sbin/sendmail /usr/sbin/sendmail
# ln -s /usr/local/sbin/sendmail /usr/sbin/mailq
# ln -s /usr/local/sbin/sendmail /usr/sbin/newaliases

Et c'en est fini ...

Ces quelques lignes se bornent à sauvegarder les exécutables originaux de Sendmail, à vider sa file d'attente, à ôter toutes les permissions pour les protéger et à créer des liens symboliques ayant les mêmes noms que les originaux vers la commande sendmail de Postfix.

Small is beautiful ...

La première chose qui frappe, quand on se plonge dans la documentation fournie avec Postfix est son apparente simplicité ... Finie la syntaxe ésotérique du sendmail.cf, finie la nécessité de passer par un ensemble de macros pour oser espérer comprendre un tant soit peu ce que l'on est en train de configurer : avec Postfix tout se passe par l'adaptation d'un seul fichier, main.cf, normalement placé, comme tous ses autres fichiers de configuration, dans le répertoire /etc/postfix/. Enfin, presque ... nous verrons plus tard que d'autres fichiers doivent être adaptés, mais tous ces fichiers quels qu'ils soient sont humainement lisibles et richement commentés.

A la différence de Sendmail, programme monolithique par excellence, Postfix est composé de nombreux petits programmes réalisant chacun une tâche bien définie. Pour la plupart, ces programmes ne sont pas vus de l'utilisateur mais appelés directement par le programme serveur /usr/sbin/postfix, lui-même lancé au démarrage du système via un script, selon la méthode System V habituelle (en tous cas, sur les systèmes Linux). Sur le mien, le script en question s'appelle /etc/init.d/postfix et, sur mon système FreeBSD, Postfix est lancé via la ligne sendmail_enable="YES" dans le fichier /etc/rc.conf (vous comprendrez plus loin ce que Sendmail vient faire ici ...).

Démarrage de Postfix

Ainsi que nous venons de le dire, sur un système Linux, c'est le script /etc/init.d/postfix (auquel le processus init passe l'option start) qui lance le serveur /usr/sbin/postfix. Celui-ci lance à son tour le serveur principal, /usr/libexec/postfix/master qui prend alors les choses en main et s'occupera de lancer les autres démons selon les besoins. Ces démons se termineront après avoir accompli leurs tâches ou après une certaine période d'inactivité. Seul, le démon de gestion de la file d'attente reste en permanence en activité.

Tout ceci peut se vérifier par une simple commande ps :

$ ps axf
...
583  ?  S    0:00 /usr/local/libexec/postfix/master
584  ?  S    0:00  \_ pickup -t fifo -c
585  ?  S    0:00  \_ qmgr -t fifo -u -c
...

qui met en évidence la présence du démon master et le fait qu'il a lui-même lancé les démons pickup et qmgr (la commande ps utilisée ici est celle de GNU, l'option -f n'a pas la même signification avec un ps BSD).

pickup est responsable de la récupération des courriers locaux : comme nous l'écrivions plus haut, pour des raisons de compatibilité, Postfix utilise un programme nommé /usr/sbin/sendmail (qui n'est pas le programme sendmail bien connu). Ce programme est utilisé pour déposer les courriers locaux dans la file d'attente maildrop : tous les courriers qui sont postés par tous les utilisateurs sont déposés dans cette file.

pickup s'occupe de les récupérer et de les passer au démon cleanup qui s'occupera de remplir les en-têtes manquantes, de gérer les enveloppes des messages et les déposera enfin dans une autre file d'attente, nommée incoming. Puis, cleanup avertira le gestionnaire de file d'attente, qmgr, qu'un nouveau courrier est arrivé.

qmgr s'occupera alors de délivrer le courrier dans les boîtes aux lettres de leurs destinataires et de gérer les délivrances qui ont échoué.

Nous verrons plus loin les autres démons entrant en jeu dans la délivrance du courrier. Passons maintenant à une configuration minimum pour tester Postfix en local.

Configuration minimale

Notre but, ici, est d'arriver à poster et recevoir du courrier en local : par exemple, root doit pouvoir poster un message à l'utilisateur babe. Ce dernier doit pouvoir récupérer le message, le lire et répondre à root. Pour simplifier, nous utiliserons le programme canonique mail.

Nous supposerons que notre machine s'appelle alex et que notre domaine s'appelle linux-france.org. Vérifions tout de suite que c'est le cas :

$ hostname
alex.linux-france.org

Ainsi que nous l'avons déjà dit, la majeure partie du travail de configuration consiste à adapter le fichier /etc/postfix/main.cf à nos besoins. Bien entendu, tout cela doit se faire sous le compte root. La première chose à faire est de sauvegarder le fichier original :

# cp /etc/postfix/main.cf /etc/postfix/main.cf.0

Puis, charger /etc/postfix/main.cf dans votre éditeur de texte favori. Normalement, un certain nombre d'options sont déjà positionnées, certaines conviennent, d'autres non. Voici les lignes qui nous intéressent (les commentaires et les lignes non modifiées ont été supprimés) :

# INFORMATIONS SUR LES REPERTOIRES LOCAUX
queue_directory = /var/spool/postfix
command_directory = /usr/local/sbin
daemon_directory = /usr/local/libexec/postfix

# POSSESSION DES FILES D'ATTENTE ET DES PROCESSUS
mail_owner = postfix

# NOMS DE LA MACHINE ET DU DOMAINE
myhostname = alex.linux-france.org

# POUR L'ENVOI DU COURRIER
myorigin = $myhostname

# MODE DE TRANSPORT
default_transport = smtp

# GESTION DES ALIAS
alias_maps = hash:/etc/postfix/aliases
alias_database = hash:/etc/postfix/aliases

# DELIVRANCE DU COURRIER
mailbox_command = /usr/local/bin/procmail

Assurez-vous que toutes les autres possibilités pour ces lignes soient considérées comme des commentaires en les faisant précéder du caractère dièse (#) et ne touchez pas aux autres.

Avant de tester tout cela, détaillons rapidement les options choisies (pour des renseignements plus précis, reportez-vous aux pages de manuel et à la documentation fournie avec le programme). La première section sert à spécifier les emplacements :

/var/spool/postfix est le répertoire de base pour toutes les files d'attente de Postfix. Lors de son premier lancement, Postfix créera tous les sous-répertoires pour ses files sous ce répertoire;
/usr/local/sbin est le réperoire où se trouve les commandes de Postfix (les exécutables dont le nom commence par post et sa version de sendmail);
/usr/local/libexec/postfix est le répertoire contenant les démons de Postfix : c'est là que se trouvent tous les programmes serveurs qu'il utilise.

La deuxième section précise qui est le propriétaire de la file d'attente et de la plupart des processus serveurs de Postfix. Ici, nous avons gardé la proposition initiale, après avoir créé l'utilisateur postfix. Voici son entrée dans notre fichier /etc/passwd :

postfix:x:101:101::/var/spool/postfix:/bin/false

Le `x' dans la partie mot de passe vient du fait que nous utilisons les «shadow passwords» . Le groupe 101 correspond au groupe postfix, lui aussi créé pour l'occasion :

# grep 101 /etc/group
postfix:x:101:

La troisième section sert à indiquer le nom complet de votre machine.

La section suivante concerne l'envoi du courrier : elle permet de renseigner Postfix sur la machine qui a posté. Pour le moment, nous considérerons que c'est ce que contient la variable $myhostname.

Nous précisons ensuite le protocole utilisé pour l'acheminement du courrier. Pour l'instant, Postfix ne reconnaît que smtp et uucp (en réalité, on peut créer des transports dans /etc/postfix/master.cf comme on veut, ce qui permet de changer des paramètres en fonction de multiples critères. On peut ainsi dupliquer le transport smtp et en changer les caractéristiques en fonction des courriers entrants ou sortants, ce qui est très flexible. Toutefois, ne l'ayant pas pratiqué, je n'en dirai pas plus ...).

La gestion des alias peut faire appel au fichier /etc/aliases utilisé par ses prédécesseurs, mais nous préférons en utiliser un autre : /etc/postfix/aliases. La commande man aliases vous renseignera en détail sur le format de ce fichier. Disons simplement que, comme son nom l'indique, il permet de définir des alias entre des noms de destinataires. Ainsi, par exemple, un serveur de news poste quotidiennement un rapport sur ses activités à l'utilisateur news (ou usenet). Supposons que babe soit l'administrateur des news sur alex : pour qu'il puisse recevoir ces messages, et si root est d'accord, bien entendu, il suffit d'indiquer que les destinataires news et usenet ont pour alias babe. Ceci est réalisé par l'ajout de la ligne suivante dans /etc/postfix/aliases :

news: babe
usenet: babe

Le fichier aliases peut être à peu près n'importe où, mais il est préférable d'utiliser plutôt /etc/postfix pour cela (de même qu'il vaut mieux utiliser /etc/mail pour Sendmail, car ce sera l'emplacement par défaut dans les futures versions).

Pour des raisons d'optimisation, Postfix, comme ses prédécesseurs, demande à ce que ce fichier soit traité comme une base de données au format DBM ou DB. Pour générer ces formats, on utilise l'utilitaire /usr/sbin/postalias (qui, rappelons-le, est un lien vers /usr/local/sbin/postalias). Ma machine ne reconnaissant pas le format DBM, j'ai donc opté pour le second et produit la base à l'aide de la commande :

# postalias hash:/etc/postfix/aliases

qui m'a généré le fichier /etc/postfix/aliases.db.

La section concernant la délivrance du courrier local indique ici que nous souhaitons utiliser procmail pour cette tâche. Tout autre programme ayant la même fonction peut convenir (deliver, par exemple), mais procmail est le plus connu dans le monde Linux. Cette section ne concerne que l'acheminement local du courrier, c'est-à-dire son écriture dans les boîtes aux lettres des destinataires.

Test de la configuration locale

Après toute modification de l'un des fichiers que nous venons d'étudier, il faut demander à Postfix de relire sa configuration :

# postfix reload

A l'aide de la commande ps ax, vérifiez la présence des démons master, pickup et qmgr. Si vous ne les voyez pas, c'est qu'il y a eu un problème : consultez les fichiers /var/log/mail.* pour tenter d'en rechercher la cause. Si tout c'est bien passé, root va pouvoir envoyer un courrier à babe :

# mail jaco -s test
premier test local
.
Cc:
#

Immédiatement, babe a dû recevoir ce courrier :

$ mail
Mail version 8.1 6/6/93. Type ? for help.
«/var/spool/mail/jaco»: 1 message 1 new
>N 1 root@alex.linux-france.org. Wed Jan 20 01:46
12/424     «test»
&  1
Message 1:
From root@alex.linux-france.org Wed Jan 20 01:46:10
1999
Delivered-To: jaco@alex.linux-france.org
To: jaco@alex.linux-france.org
Subject: test
Date: Wed, 20 Jan 1999 01:46:10 +0100 (CET)
From: root@alex.linux-france.org

premier test local
& d
& q
%

On notera la présence d'un champ Delivered-To: qui est rajouté par Postfix afin d'éviter les boucles dans la délivrance du courrier et ne sera pas affiché par défaut avec la plupart des logiciels de lecture du courrier (en tous cas, avec Gnus et Netscape ...).

Essayons encore : maintenant postez sous le compte babe un message à root et vite, très vite, faites ps axf. Sous Linux, vous devriez voir les lignes suivantes :

1271  ?  S    0:00 /usr/local/libexec/postfix/master
1272  ?  S    0:00  \_ pickup -t fifo -c
1273  ?  S    0:00  \_ qmgr -t fifo -u -c
1286  ?  S    0:00  \_ cleanup -t unix -u -c
1287  ?  S    0:00  \_ trivial-rewrite -n rewrite -t unix -u -c
1288  ?  S    0:00  \_ local -t unix

Assez rapidement, vous remarquerez, si vous faites la même commande, que cleanup et local se sont terminés, tandis que trivial-rewrite perdure encore un peu. Lui aussi se terminera à son tour. Tout ceci corrobore ce que nous disions plus haut : pickup a récupéré le message et l'a passé à cleanup. trivial-rewrite s'est chargé de réécrire l'adresse en rajoutant le nom de la machine locale derrière le nom de l'utilisateur. local est le démon responsable de la délivrance locale du message dans la boîte aux lettres du destinataire. C'est à ce moment que le fichier des alias est pris en compte et, si le destinataire utilise un fichier ~/.forward, local le fait suivre à l'adresse indiquée. C'est local qui ajoute le champ Delivered-To: pour éviter un bouclage intempestif et c'est lui qui remplit le champ From de l'enveloppe (à ne pas confondre avec le champ From: ...).

Pour finir cette partie, il ne vous reste plus qu'à essayer de faire la même chose avec vos logiciels de lecture de courrier favoris : cela ne devrait pas poser de problèmes puisque local délivre les messages à l'endroit où la plupart des logiciels s'attendent à les trouver.

Eric Jacoboni
Linux Magazine France n° 13 - Janvier 00