Serveur de mails multi-domaines

May 23, 2008

Ayant voulu créer un serveur de mail avec des comptes et des domaines virtuels je me suis très vite rendu compte que les différents tutoriels ne fonctionnaient pas dans ma configuration.

J’ai donc décidé de créer ce billet pour présenter le fonctionnement d’une telle infrastructure et comment la mettre en place.

Infrastructure du serveur

Le serveur va se composer de quatre services : l’agent de livraison (Postfix), le serveur de mails IMAP (Courier) et le serveur web (Apache + PHP) et la base de données (MySQL). Pour accéder au mails j’ai décidé d’utiliser RoundCube et PostfixAdmin pour administrer les utilisateurs, les alias et les domaines.

Infrastructure serveur de mails multi-domaines

Création du compte virtuel

On va d’abord créer un utilisateur sur le serveur qui stockera les mails des utilisateurs :

addgroup --gid 20001 virtual
adduser --uid 20001 --gid 20001 virtual

Installation des services

On va commencer par le plus simple : Apache et MySQL. On va tout simplement les récupérer dans les dépots :

apt-get install apache2 mysql-server-5.0 php5 php5-mysql php5-gd

Je n’aborderai pas ici la configuration d’Apache ni de PHP (penser juste à activer l’extension pour MySQL si ce n’est pas fait).

Base de données

Il faut créer la base de données que vont utiliser les autres services pour identifier les utilisateurs. Il suffit d’exécuter le script SQL suivant : PostfixMySQL.sql. Penser à modifier l’identifiant et le mot de passe pour le compte (ici : postfix / postfix).

mysql
...
mysql>CREATE DATABASE postfix;
mysql>GRANT ALL PRIVILEGES ON postfix.* TO 'postfix'@'localhost' IDENTIFIED BY 'postfix';
mysql>. PostfixMySQL.sql

On ajoute l’administrateur de PostfixAdmin directement dans la base de données :

mysql>INSERT INTO domain (domain, description)
      VALUES ('mkhelif.fr', 'Domaine personnel');
Query OK, 1 row affected (0.00 sec)

mysql>INSERT INTO admin (username, password, active)
      VALUES ('[email protected]', '$1$CeeAzXb...J8njWAw1', '1');
Query OK, 1 row affected (0.00 sec)

mysql>INSERT INTO domain_admins (username, domain, active)
      VALUES ('[email protected]', 'ALL', '1');
Query OK, 1 row affected (0.00 sec)

mysql>INSERT INTO mailbox (username, password, name, maildir, domain, active)
      VALUES ('[email protected]', '$1$ExhxBRG6$...qhF/unIwe0Kk1',
              'Marwan KHELIF', '[email protected]/', 'mkhelif.fr', '1');
Query OK, 1 row affected (0.00 sec)

Note : le mot de passe est hashé en MD5 avec du sel. Voici un script PHP pour encoder votre mot de passe :


On vérifie que l’utilisateur que l’on vient de créer a bien accès à la base de données :

mysql postfix -u postfix -p
Enter password: postfix
...
mysql>

Voilà la base de données est prête à être utilisée par les différents services.

Postfix

On commence par installer Postfix et le module de connexion à la base de données. Attention lors de l’installation si Exim4 est installé il sera supprimé et remplacé par Postfix.

apt-get install postfix postfix-mysql

Note : pendant l’installation sélectionner Site Internet.

Une fois installé il faut modifier le fichier suivant : /etc/postfix/main.cf. Rajouter les propriétés suivantes à la fin du fichier :

virtual_transport = maildrop
virtual_mailbox_base = /home/virtual
virtual_alias_maps = proxy:mysql:/etc/postfix/mysql_virtual_alias_maps.cf
virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql_virtual_domains_maps.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
virtual_minimum_uid = 20001
virtual_uid_maps = static:20001
virtual_gid_maps = static:20001

On crée alors les fichiers de mapping avec la base de données :

Fichier : /etc/postfix/mysql_virtual_alias_maps.cf
user = postfix
password = postfix
hosts = localhost
dbname = postfix
query = SELECT goto FROM alias WHERE address = '%s' and active = '1'
Fichier : /etc/postfix/mysql_virtual_domains_maps.cf
user = postfix
password = postfix
hosts = localhost
dbname = postfix
query = SELECT domain FROM domain WHERE domain = '%s' and active = '1'
Fichier : /etc/postfix/mysql_virtual_mailbox_maps.cf
user = postfix
password = postfix
hosts = localhost
dbname = postfix
query = SELECT maildir FROM mailbox WHERE username = '%s' and active = '1'

Modifier le fichier /etc/postfix/master.cf afin de modifier la livraison par maildrop :

Remplacer la ligne :
maildrop  unix  -       n       n       -       -       pipe
  flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}

par :
maildrop  unix  -       n       n       -       -       pipe
   flags=DRhu user=virtual argv=/usr/bin/maildrop -w 90 -d ${user}@${nexthop}
   ${extension} ${recipient} ${user} ${nexthop} ${sender}

On redémarre alors le service :

/etc/init.d/postfix restart

Maildrop

On va alors installer le livreur de mails : maildrop.

apt-get install maildrop

On créer le fichier /home/virtual/.mailfilter de livraison, si vous souhaitez spécifier certaines règles de livraisons (mailinglists, spams, …) vous devez modifier ce fichier ou en créer un dans les dossiers de vos utilisateurs :

Fichier : /home/virtual/.mailfilter
logfile "/home/virtual/.maildrop.log"
`[ -d $DEFAULT ] || (maildirmake $DEFAULT && maildirmake -f Spam $DEFAULT && maildirmake -f sent-mail $DEFAULT && maildirmake -f SpamToLearn $DEFAULT &&
maildirmake -f SpamFalse $DEFAULT)`

`test -r $HOME/$DEFAULT.mailfilter`
if( $RETURNCODE == 0 )
{
    log "(==)  Including $HOME/$DEFAULT.mailfilter"
    exception {
        include $HOME/$DEFAULT.mailfilter
    }
}

Une fois ce fichier créé il faut modifier les droits à ce fichier :

chmod 600 .mailfilter

Courier

On installe de la même façon Courier et le module de connexion à la base de données :

apt-get install courier-imap courier-authlib-mysql

Note : pendant l’installation choisissez NON lorsqu’il vous propose de créer les répertoires Web.

Modifier les paramètres dans les fichiers suivants :

Fichier : /etc/courier/authdaemonrc
authmodulelist="authmysql"

Fichier : /etc/courier/authmysqlrc
MYSQL_SERVER	localhost
MYSQL_USERNAME	postfix
MYSQL_PASSWORD	postfix
MYSQL_SOCKET	/var/run/mysqld/mysqld.sock
MYSQL_PORT	3306
MYSQL_OPT	0

MYSQL_DATABASE	postfix
MYSQL_USER_TABLE	mailbox
MYSQL_CRYPT_FIELD	password
MYSQL_LOGIN_FIELD	username
MYSQL_HOME_FIELD	'/home/virtual'
MYSQL_UID_FIELD		'20001'
MYSQL_GID_FIELD		'20001'
MYSQL_NAME_FIELD	name
MYSQL_MAILDIR_FIELD	maildir
MYSQL_WHERE_CLAUSE	active='1'

Note : vérifier qu’il n’y ai que des tabulations entre le nom et la valeur d’une propriété.

Il faut donner les accès à l’utilisateur virtual :

chown virtual /usr/lib/courier/authdaemon
chmod 750 /usr/lib/courier/authdaemon

On redémarre alors les services IMAP et AuthDaemon de Courier :

/etc/init.d/courier-imap restart
/etc/init.d/courier-authdaemon restart

Pour vérifier que le serveur IMAP arrive bien à se connecter à la base de données on exécute un test d’authentification :

authtest [email protected]
Authentication succeeded.

     Authenticated: [email protected]  (uid 20001, gid 20001)
    Home Directory: /home/virtual
           Maildir: [email protected]/
             Quota: 0S
Encrypted Password: $1$CeeAzXb...J8njWAw1
Cleartext Password: (none)
           Options: (none)

Maintenant tous les services sont configurés et communiquent entre eux, on peut configurer les accès Web.

PostfixAdmin et Roundcube

Tout d’abord on récupère les archives (récupérer les dernières versions depuis RoundCube et PostfixAdmin) :

wget http://garr.dl.sourceforge.net/sourceforge/roundcubemail/roundcubemail-0.1.1.tar.gz
wget http://dfn.dl.sourceforge.net/sourceforge/postfixadmin/postfixadmin_2.2.0.tar.gz

On extrait alors les sources :

tar -xzf roundcubemail-0.1.1.tar.gz
tar -xzf postfixadmin_2.2.0.tar.gz

Configuration de PostfixAdmin

Pour configurer PostfixAdmin il faut modifier les paramètres suivants du fichier config.inc.php et supprimer le fichier setup.php :

$CONF['configured'] = true;
$CONF['postfix_admin_url'] = 'http://www.mkhelif.fr/';
$CONF['create_default_folders'] = true;
$CONF['database_type'] = 'mysqli';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfix';
$CONF['database_password'] = 'postfix';
$CONF['database_name'] = 'postfix';

Vous pouvez modifier les autres propriétés selon vos besoins.

Configuration de RoundCube

On va tout d’abord créer la base de données que va utiliser RoundCube :

mysql
...
mysql>CREATE DATABASE roundcube;
Query OK, 1 row affected (0.00 sec)

mysql>GRANT ALL PRIVILEGES ON roundcube.* TO 'roundcube'@'localhost' IDENTIFIED BY 'roundcube';
Query OK, 1 row affected (0.00 sec)

Pour configurer RoundCube il faut déplacer les fichiers :

mv ./config/db.inc.php.dist ./config/db.inc.php
mv ./config/main.inc.php.dist ./config/main.inc.php

Et modifier les paramètres :

Fichier : config/db.inc.php
$rcmail_config['db_dsnw'] = 'mysqli://roundcube:roundcube@localhost/roundcube';

Fichier : config/main.inc.php
$rcmail_config['default_host'] = 'localhost';

Problèmes rencontrés

La commande authtest échoue

Cela signifie généralement que le serveur IMAP n’arrive pas à accéder à la base de données. Vérifier tous les paramètres du fichier /etc/courier/authmysqlrc et que le nom et la valeur des propriétés soient bien séparés par des tabulations et pas des espaces.

Pour activer les logs au niveau de Courier il faut modifier le fichier /etc/courier/authdaemonrc et positionner le paramètre DEBUG_LOGIN à 1.

J’obtiens l’erreur suivante : imapd: authentication error: Input/output error

J’avais rencontré ce problème car IMAP n’arrivai pas à se connecter à la base de données (mauvais mot de passe). Il faut vérifier le fichier /etc/courier/authmysqlrc.

RoundCube n’authentifie pas les utilisateurs

J’ai rencontré ce problème dans le cas où Apache n’a pas accès pour créer les répertoire par défaut d’un utilisateur (Inbox, Sent, Trash, Spam, Drafts), vérifier bien que le dossier existe et que le propriétaire est bien virtual. Sinon créer les répertoires grâce à la commande : maildirmake * en vérifiant les droits : *755.*
*

Conclusion

Voilà votre serveur de mails multi-domaines est prêt. Vous pouvez ajouter d’autres services : antispam (SpamAssassin), antivirus (ClamAV), gestion de quotas, …Mais je n’aborderai pas ces points là dans ce tutoriel.