Migration courier-imap => dovecot

dovecotLogo

C’est quoi ça encore ?

Dans des articles précédents, je montre comment se monter un serveur de mails assez complet sous Debian. Mais un choix fait il y a fort longtemps, le choix de courier-imap et courier-pop comme brique gérant l’IMAP et le POP, n’avait pas été bien réfléchi et il se trouve que courier-* manque de fonctions, notamment la prise en charge du protocole SIEVE, permettant du tri de mails en amont, sur le serveur.
Après un peu d’utilisation, il y a aussi d’autres petites choses qui se passent mieux avec dovecot plutôt que courier-*. Bref, autant y aller.

Ainsi, avec Dovecot, lorsque les utilisateurs sont virtuels (en base MySQL ici), on peut régler les filtres (et répondeur automatique) depuis par exemple le webmail ou un plugin pour Thunderbird gérant le SIEVE (mais ce plugin est plus brut, il faut écrire le script SIEVE au lieu de le générer graphiquement comme avec RoundCube).
Au passage, j’en ai profité pour ajouter (obliger en fait !) le TLS sur les ports non sécurisés ; c’est une alternative au SSL, bien plus en vogue. Perso, j’ai tout toléré (SSL, TLS sur port normal) et simplement interdit le mode « tout en clair ».

Voici donc comment migrer ; c’est assez rapide une fois qu’on s’est payé pas mal de docs, tuto etc
En gros on change la couche IMAP (de courier à dovecot), on le configure, on adapte les structures Maildir – automatiquement grâce à un script de migration prévu pour – pour que dovecot trouve ses petits à partir de l’existant courier (fichiers courierimapsubscribed & co), on change 2/3 trucs dans postfix et on relance postfix et dovecot. Zou.

Références

Je suis parti de ces documents là :
https://library.linode.com/email/postfix/postfix2.9.6-dovecot2.0.19-mysql – sauf pour le cryptage des mots de passe, car je suis parti sur des mots de passe des mes utilisateurs virtuels assez simples (via la fonction MySQL ENCRYPT) là où un SHA-512 aurait pû être plus pertinent.
donc j’ai mixé la doc avec celle-ci : http://www.pointroot.org/index.php/2012/04/13/un-serveur-de-mails-debian-postfix-dovecot-mysql-smtps-imaps/

Avant de commencer

Avant de réaliser la bascule, prévenez vos utilisateurs que ça va couper ; et mieux, coupez vos accès aux ports imap, imaps, pop3, pop3s (si vous utilisez le POP).
Je n’ai pas eu de surprise trop mauvaises à la relance. Les clients Apple (iphone, mail, ipad) ont perdu les sous-répertoires des boîtes mails, je n’ai rien trouvé d’autre que d’effacer les comptes et de les recréer… merci apple.
Outlook s’en est bien sorti et suivant les versions, il a voulu – ou pas – créer des répertoires « Eléments envoyés » plutôt que « Sent » ; à voir suivant vos versions. A la limite, c’est plutôt cool, sauf si les noms habituels « Sent, Trash » etc sont définis à d’autres endroits, comme par exemple dans votre webmail.

Vous pouvez aussi bloquer votre serveur SMTP afin que les mails n’entrent plus. En effet, on supprime éventuellement procmail et vacation si vous l’utilisiez ; et le temps que le reste soit en place, c’est mieux qu’aucun mail ne transite. On pourrait avoir des mails qui se perdent je pense, sinon.

On installe Dovecot

L’accès aux ports IMAP et POP est coupé ? on attaque

Ajout du mode TLS uniquement pour renforcer la sécurité

Dans /etc/postfix/main.cf j’ajoute smtpd_tls_auth_only = yes

Configuration pour dovecot

Dans /etc/postfix/main.cf, j’ajoute ou modifie :
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
virtual_transport = lmtp:unix:private/dovecot-lmtp

Ajout de submission dans postfix

Pour vraiment prendre en charge tous les protocoles (port 587), dans /etc/postfix/master.cf, décommenter les lignes du protocole « submission » :
submission inet n - - - - smtpd
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING

Désactivation de procmail et vacation

Si vous utilisiez procmail, vous aviez peut-être des lignes commençant par procmailpipe_ (ou un autre nom venant un pipe créé dans le master.cf
On enlève aussi ça : mailbox_command = /usr/bin/procmail -a "$EXTENSION"
Dans ma base MySQL, j’avais un tas de « forwardings » vers ces pipe + dans la table transport ; je les supprime. C’est ce qui permettait de renvoyer vers procmail ou vacation pour le répondeur de vacances.

Installation de DOVECOT – sans sieve pour l’instant, pour ne pas tout mélanger

aptitude install dovecot-core dovecot-imapd dovecot-pop3d dovecot-lmtpd dovecot-mysql
cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig
cp /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10-mail.conf.orig
cp /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10-auth.conf.orig
cp /etc/dovecot/dovecot-sql.conf.ext /etc/dovecot/dovecot-sql.conf.ext.orig
cp /etc/dovecot/conf.d/10-master.conf /etc/dovecot/conf.d/10-master.conf.orig
cp /etc/dovecot/conf.d/10-ssl.conf /etc/dovecot/conf.d/10-ssl.conf.orig

Ensuite on adapte.

Dans /etc/dovecot/dovecot.conf ligne 21 après include_try *.protocol :
protocols = imap pop3 lmtp
On peut se passer du pop3 (suivant votre cas) et on prend le LDA lmtp ; le LDA est le Local Delivery Agent, le programme en charge de prendre le mail du serveur postfix vers la boîte mail de la personne.

Dans /etc/dovecot/conf.d/10-mail.conf :
Ligne 30 :
#mail_location = mbox:~/mail:INBOX=/var/mail/%u
mail_location = maildir:/vmailboxes/%d/%n

Car mes identifiants de compte sont de la forme user@domain.com et pas juste « user ».
Ligne 116 :
mail_privileged_group = vmail

Dans /etc/dovecot/conf.d/10-auth.conf :
Ligne 10 :
disable_plaintext_auth = yes
Si on veut renforcer un peu la sécu ; lire les commentaires au-dessus de ce paramètre pour bien comprendre
Ligne 102 :
auth_mechanisms = plain login
Ligne 127 : j’inverse les 2 lignes pour indiquer que je fais une authentification par SQL, pas par compte système :
#!include auth-system.conf.ext
!include auth-sql.conf.ext

Dans /etc/dovecot/conf.d/auth-sql.conf.ext :
A la fin du fichier – si j’ai bien compris – on lui dit d’aller vérifier l’existence d’un compte (pas son mot de passe) simplement en se basant sur la présence ou non du répertoire correspondant, au lieu d’aller requêter pour peu de choses :
#userdb {
# driver = sql
# args = /etc/dovecot/dovecot-sql.conf.ext
#}

# If you don't have any user-specific settings, you can avoid the user_query
# by using userdb static instead of userdb sql, for example:
#
userdb {
driver = static
#args = uid=vmail gid=vmail home=/var/vmail/%u
args = uid=vmail gid=vmail home=/vmailboxes/%d/%n
}

Idem, mes comptes sont créés de la sorte : /vmailboxes/‹mondomain.com›/‹monuser› pour un compte user@domain.com
Ajouter enfin :
driver = mysql
connect = host=mon_serveur_mysql dbname=ma_db_postfix user=mon_admin password=mon_pass
default_pass_scheme = CRYPT
password_query = SELECT email as user, password FROM users WHERE email='%u';

C’est ici que, si j’avais opté pour un cryptage plus costaud dès le départ, j’aurais pu le préciser, type SHA-512.

Dans /etc/dovecot/conf.d/10-master.conf :
Ligne 53 :
unix_listener /var/spool/postfix/private/dovecot-lmtp {
#mode = 0666
mode = 0600
user = postfix
group = postfix

Ligne 85 :
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
}

Ligne 106 :
mode = 0600
user = vmail

Ligne 120 :
user=dovecot
Ligne 130 :
user=vmail

Dans /etc/dovecot/conf.d/10-ssl.conf :
Au début, à vous de voir si vous mettez yes/no ou carrément imposez avec « required » le paramètre « ssl ». Puis, si vous aviez déjà des certificats :
ssl_cert = ‹/etc/postfix/smtpd.cert
ssl_key = ‹/etc/postfix/smtpd.key

Voilà pour cette première passe sur la configuration Dovecot.
On adapte quelques permissions et on relance :

chown -R vmail:dovecot /etc/dovecot
chmod -R o-rwx /etc/dovecot
service dovecot restart
service postfix restart

Choix imap VS imaps, pop ou pas pop ?

Dans /etc/dovecot/conf.d/10-master.conf :
On désactive un protocole en mettant son « port » à 0 ; sinon en laissant en commentaire.
Concernant IMAP vs IMAPS, pensez bien qu’avec TLS, le IMAP normal devient tout aussi secure que IMAPS (SSL).

Conversion des fichiers courierimap* vers la structure Dovecot

Il y a un outil très bien fait et expliqué ici : http://wiki2.dovecot.org/Migration/Courier
On le lance en faisant /root/courier-dovecot-migrate.pl --to-dovecot --recursive /vmailboxes # puis idem avec --convert

TLS dans roundcube

Si c’est l’occasion pour vous aussi de renforcer le cryptage au niveau réseau, vous pouvez ajouter tls:// devant le nom du serveur SMTP dans le fichier main.inc.php, variable $rcmail_config['smtp_server'] de RoundCube.
C’est obligatoire si vous avez forcé le TLS dans postfix via smtpd_tls_auth_only = yes dans le main.cf.

Ajout de SIEVE

SIEVE dans Dovecot

Rappel, c’est pour permettre le tri côté serveur des messages. C’est vacation et procmail, en plus accessible. Et utilisable par un utilisateur lambda via le plugin qui va bien dans RoundCube.
Pour avoir SIEVE sur LMTP (et non le LDA normal), j’ai utilisé cette doc : https://rtcamp.com/tutorials/mail/server/sieve-filtering/
D’abord, on ajoute ce qu’il manque à Dovecot :

aptitude install dovecot-sieve dovecot-managesieved

Ce qui a pour but de créer les fichiers 20-managesieve.conf et 90-sieve.conf dans /etc/dovecot/conf.d/.
Du coup, on précise à Dovecot qu’il doit proposer SIEVE.

Dans /etc/dovecot/dovecot.conf, on ajoute le protocole sieve dans la liste des protocols définie tout à l’heure.
Dans /etc/dovecot/conf.d/20-lmtp.conf, on change :
#mail_plugins = $mail_plugins
mail_plugins = $mail_plugins sieve
postmaster_address = vous@quelquepart.fr

Dans /etc/dovecot/conf.d/90-sieve.conf :
Ligne 11, on indique où stocker le script SIEVE (c’est un langage) associé au compte :
#sieve = ~/.dovecot.sieve
sieve = /vmailboxes/%d/%n/dovecot.sieve

On relance Dovecot et c’est tout 🙂

plugin SIEVE dans RoundCube

De base, on a le plugin « managesieve » dans RoundCube. Il vaut mieux récupérer « sieverules » qui est bien mieux fait. C’est ici : https://github.com/JohnDoh/Roundcube-Plugin-SieveRules-Managesieve/releases

Il ne faut pas prendre bêtement la dernière version, mais celle qui va bien en fonction de votre version roundcube. Le tableau de compatibilité est là : http://plugins.roundcube.net/packages/johndoh/sieverules
Je récupère donc wget https://github.com/JohnDoh/Roundcube-Plugin-SieveRules-Managesieve/archive/2.0.tar.gz, je renomme le répertoire obtenu en sieverules et le place dans « plugins » de l’installation roundcube.
Dans le répertoire du plugin :
1) on crée un fichier config.inc.php à partir du config.inc.php.dist, on change le port de 2000 à 4190 (la nouvelle norme de sieve, sur lequel notre Dovecot s’attend à trouver SIEVE).
2) on peut là aussi activer le TLS via $rcmail_config['sieverules_usetls'] = TRUE;

Une limitation : les accents ne sont pas appréciés dans les noms de répertoire, j’obtiens l’erreur suivante si je fais une règle de tri vers un répertoire avec accent :
sieve: info: started log at Mar 31 10:03:17.
error: msgid=<53392139.5060003@toto.com>: failed to store into mailbox '_ blabla &AOA- avecaccent': Mailbox doesn't exist: _ blabla &-AOA- avecaccent.

Ne pas oublier d’activer le plugin dans la conf Roundcube, dans le config/main.inc.php :
$rcmail_config['plugins'] = array('password', 'fail2ban', 'zipdownload', 'show_additional_headers', 'jqueryui', 'sieverules', 'quickrules');
Je crois que « jqueryui » est un pré-requis pour sieverules ; trou de mémoire.

Remarques finales

  • Penser à lire les logs de roundcube au début, dans le sous-répertoire logs/.
  • attention aux permissions www-data sur le répertoire plugins/sieverules et partout où on a mis nos gros doigts
  • Côté procmail, vacation, penser à supprimer tout ce qui les concerne dans master.cf (le pipe), dans les règles de transport, les forwardings etc + les éventuels liens symboliques du fait de procmail, dans /vmailboxes (si vous avez suivi mes docs jusqu’alors)
  • Nettoyer les fichiers courierimap* des Maildir une fois qu’on est sûr de ne pas faire de retour arrière
  • Se créer un fichier « subscriptions » (remplaçant de courierimapsubscribed) de référence pour les abonnements par défaut des comptes que l’on crée dans le futur
  • Penser à lire le fichier dovecot.sieve.log de chaque Maildir pour comprendre les bugs (c’est là que j’ai vu que les accents ne passaient pas)
  • Pour faire du SIEVE dans Thunderbird (déjà il faut rendre son port 4190 accessible), c’est là : https://github.com/thsmi/sieve/blob/master/nightly/README.md car à l’époque où j’ai fait la manip, le plugin dans sa version officielle sur le site d’extensions Thunderbird ne fonctionnait pas pour TBird 24 et +
  • Désinstaller les paquets vacation, procmail

Voilà, j’espère ne rien avoir oublié… ça paraît long mais ce n’est pas très compliqué au final.

3 comments

  1. Très bon article – j’aurai été content de le lire il y a 15 jours, quand j’ai mis en place pour un client une solution de mails complète (postfix/dovecot/mysql)!

    J’étais parti sur postfix/courier/saslauthd, mais après deux jours à me battre avec saslauthd (qui n’aime pas mysql), j’ai fini par installer dovecot en lieu et place de courier: ça m’a pris une heure, et hop, tout était fonctionnel, notamment SSL/TLS (je ne voulais pas que quoique ce soit puisse passer en clair).

    1. Ah oui désolé, d’autant que l’article était rédigé quasiment totalement depuis 1 bon mois…
      saslauthd et mysql, ça fonctionne, mais c’est foireux à configurer.
      En tout cas, dovecot est largement plus simple à mettre en oeuvre et apporte le SIEVE, ce qui est pratique

  2. Bonjour,

    Pour les accents voici comment je m’en suis sortie :

    find /var/vmail -name dovecot-uidlist -delete
    find /var/vmail -name dovecot-keywords -delete
    find /var/vmail -name subscriptions -delete
    perl /root/bin/courier-dovecot-migrate.pl –to-dovecot –recursive /var/vmail
    php /root/bin/migration-utf7IMAP.php

    Et le fichier migration-utf7IMAP.php :

    <?php

    $dirVmail = '/var/vmail';
    $scanVmail = scandir($dirVmail);

    foreach ($scanVmail as $domain) {
    if (is_dir($dirVmail.'/'.$domain) && $domain != '..' && $domain != '.'){
    echo "\n\n## ";
    echo $domain;
    echo"\n";
    $scanUser = scandir($dirVmail.'/'.$domain);
    foreach ($scanUser as $user) {
    if ($user != '..' && $user != '.') {

    echo "#".$user;
    echo"\n";
    if (is_file($dirVmail.'/'.$domain.'/'.$user.'/Maildir/subscriptions')) {
    $fichier = file($dirVmail.'/'.$domain.'/'.$user.'/Maildir/subscriptions');
    $total = count($fichier);
    for($i = 0; $i « .$maildir_convert;
    $maildir_convert = mb_convert_encoding($maildir, ‘UTF7-IMAP’);
    rename($dirVmail.’/’.$domain.’/’.$user.’/Maildir/’.$maildir,
    $dirVmail.’/’.$domain.’/’.$user.’/Maildir/’.$maildir_convert);
    echo »\n »;
    }
    }
    }

    }
    }
    }
    }

    echo « NE SURTOUT PAS LANCE 2 « ;

    ?>

    Belle journée,
    David

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.