Cyrus-imapd

Ici, ça va être un peu plus long et aussi un peu plus délicat.

Installation

Nous voulons proposer IMAP mais aussi POP3 ? Nous avons à installer deux paquets, les dépendances nécessaires suivront :

aptitude install cyrus-imapd

Pour plus de confort, installons aussi quelques paquets recommandés :

aptitude install cyrus-clients cyrus-doc

Nous devrions disposer de tout ce qui est nécessaire.

Configuration

Nous avons deux fichiers sur lesquels il nous faut intervenir

Cyrus.conf

Cyrus est un outil très puissant, qui sait répartir les boîtes aux lettres sur plusieurs serveurs. Notre objectif n'est pas de concurrencer le premier fournisseur d'accès de France, nous resterons plus humbles et n'utiliserons pas ces fonctionnalités.

Dans l'exemple qui suit, nous activons POP3 et IMAP. Nous opourrions aussi activer POP3S et IMAP4 et même aussi un serveur de type usenet (nntp, en installant en plus cyrus-nntpd-2.2) si nous voulons, mais web-cyradm ne gèrera pas ce dernier.

# Debian defaults for Cyrus IMAP server/cluster implementation
# see cyrus.conf(5) for more information
#
# All the tcp services are tcpd-wrapped. see hosts_access(5)
# $Id: cyrus.conf 567 2006-08-14 18:19:32Z sven $

START {
	# do not delete this entry!
	recover		cmd="/usr/sbin/ctl_cyrusdb -r"
  
	# this is only necessary if idlemethod is set to "idled" in imapd.conf
	#idled		cmd="idled"

	# this is useful on backend nodes of a Murder cluster
	# it causes the backend to syncronize its mailbox list with
	# the mupdate master upon startup
	#mupdatepush   cmd="/usr/sbin/ctl_mboxlist -m"

	# this is recommended if using duplicate delivery suppression
	delprune	cmd="/usr/sbin/cyr_expire -E 3"
	# this is recommended if caching TLS sessions
	tlsprune	cmd="/usr/sbin/tls_prune"
}

# UNIX sockets start with a slash and are absolute paths
# you can use a maxchild=# to limit the maximum number of forks of a service
# you can use babysit=true and maxforkrate=# to keep tight tabs on the service
# most services also accept -U (limit number of reuses) and -T (timeout)
SERVICES {
	# --- Normal cyrus spool, or Murder backends ---
	# add or remove based on preferences
	imap		cmd="imapd -U 30" listen="imap" prefork=0 maxchild=100
	#imaps		cmd="imapd -s -U 30" listen="imaps" prefork=0 maxchild=100
	#pop3		cmd="pop3d -U 30" listen="pop3" prefork=0 maxchild=50
	#pop3s		cmd="pop3d -s -U 30" listen="pop3s" prefork=0 maxchild=50
	#nntp		cmd="nntpd -U 30" listen="nntp" prefork=0 maxchild=100
	#nntps		cmd="nntpd -s -U 30" listen="nntps" prefork=0 maxchild=100

	# At least one form of LMTP is required for delivery
	# (you must keep the Unix socket name in sync with imap.conf)
	#lmtp		cmd="lmtpd" listen="localhost:lmtp" prefork=0 maxchild=20
	#lmtpunix	cmd="lmtpd" listen="/var/run/cyrus/socket/lmtp" prefork=0 maxchild=20
	lmtpunix       cmd="lmtpd" listen="/var/spool/postfix/cyrussock/lmtp" prefork=0 maxchild=20
	# ----------------------------------------------

	# useful if you need to give users remote access to sieve
	# by default, we limit this to localhost in Debian
  	sieve		cmd="timsieved" listen="localhost:sieve" prefork=0 maxchild=100

	# this one is needed for the notification services
	#notify		cmd="notifyd" listen="/var/run/cyrus/socket/notify" proto="udp" prefork=1
	notify         cmd="notifyd" listen="/var/spool/postfix/cyrussock/notify" proto="udp" prefork=1

	# --- Murder frontends -------------------------
	# enable these and disable the matching services above, 
	# except for sieve (which deals automatically with Murder)

	# mupdate database service - must prefork at least 1
	# (mupdate slaves)
	#mupdate       cmd="mupdate" listen=3905 prefork=1
	# (mupdate master, only one in the entire cluster)
	#mupdate       cmd="mupdate -m" listen=3905 prefork=1

	# proxies that will connect to the backends
	#imap		cmd="proxyd" listen="imap" prefork=0 maxchild=100
	#imaps		cmd="proxyd -s" listen="imaps" prefork=0 maxchild=100
	#pop3		cmd="pop3proxyd" listen="pop3" prefork=0 maxchild=50
	#pop3s		cmd="pop3proxyd -s" listen="pop3s" prefork=0 maxchild=50
	#lmtp		cmd="lmtpproxyd" listen="lmtp" prefork=1 maxchild=20
	# ----------------------------------------------
}

EVENTS {
	# this is required
	checkpoint	cmd="/usr/sbin/ctl_cyrusdb -c" period=30

	# this is only necessary if using duplicate delivery suppression
	delprune	cmd="/usr/sbin/cyr_expire -E 3" at=0401

	# this is only necessary if caching TLS sessions
	tlsprune	cmd="/usr/sbin/tls_prune" at=0401
	
	# indexing of mailboxs for server side fulltext searches

	# reindex changed mailboxes (fulltext) approximately every other hour
	#squatter_1	cmd="/usr/bin/nice -n 19 /usr/sbin/squatter -s" period=120

	# reindex all mailboxes (fulltext) daily
	#squatter_a	cmd="/usr/sbin/squatter" at=0517
}
Ici encore, les sockets unix sont à déplacer dans la cage de Postfix si nous voulons les utiliser (et nous voudrons).

Imapd.conf

Plus spécifique à imap, voici ce fichier, débarrassé de ses commentaires « d'usine » :

configdirectory: /var/lib/cyrus
defaultpartition: default
partition-default: /var/spool/cyrus/mail
altnamespace: no

# rappelez-vous, lors de la configuration de web-cyradm...
unixhierarchysep: yes
virtdomains: yes

# Vous avez bien un domaine dans lequel se trouve le serveur ?

lmtp_downcase_rcpt: yes
allowanonymouslogin: no
popminpoll: 1
autocreatequota: 0
umask: 077
sieveusehomedir: false
sievedir: /var/spool/sieve
hashimapspool: true
allowplaintext: yes
sasl_mech_list: PLAIN

# Comment exploiter SASL (et son socket unix)
sasl_pwcheck_method: saslauthd
sasl_saslauthd_path: /var/spool/postfix/var/run/saslauthd/mux
sasl_auto_transition: no

# Nous verrons comment faire du TLS proprement plus tard
tls_ca_path: /etc/ssl/certs
tls_session_timeout: 1440
tls_cipher_list: TLSv1+HIGH:!aNULL:@STRENGTH

# Et n'oublions pas l'emplacement des sockets
lmtpsocket: /var/spool/postfix/cyrussock/lmtp

idlemethod: poll
idlesocket: /var/spool/postfix/cyrussock/idle
notifysocket: /var/spool/postfix/cyrussock/notify

syslog_prefix: cyrus
allowusermoves: yes

# Enfin, il faut déclarer au moins un administrateur
admins: cyrus
imap_admins: cyrus
sieve_admins: cyrus

Rappelez-vous que nous avons dans notre base MySQL un administrateur nommé cyrus. Le paramètre unixhierarchysep: yes indique à Cyrus qu'il doit utiliser le séparateur / plutôt que le . qui est sa configuration par dafaut, et qui a l'inconvénient que le . n'est plus utilisable dans les noms d'utilisateurs. Dans la configuration choisie, il est indispensable de pouvoir mettre des points dans les noms d'utilisateurs.

N'oublions pas :

mkdir -p /var/spool/postfix/cyrussock

Notez que cette configuration n'a que valeur d'exemple. Consultez le imapd.conf « d'usine » pour avoir plus d'informations. Consultez aussi le manuel : man imapd.conf (:-P) pour tous les paramètres possibles.

Bon. Et PAM ?

Ne l'oublions pas. Dans /etc/pam.d, nous avons le fichier imap à modifier comme suit :

auth sufficient pam_mysql.so user=mail passwd=epikoi host=localhost db=mail table=accountuser usercolumn=username passwdcolumn=password crypt=1
account required pam_mysql.so user=mail passwd=epikoi host=localhost db=mail table=accountuser usercolumn=username passwdcolumn=password crypt=1
Les parties surlignées sont à modifier en fonction de votre personnalisation bien sûr.

Le fichier imap doit contenir ces deux lignes et seulement ces deux lignes

Il ne faut pas oublier non plus d'installer ce qu'il faut pour que PAM puisse utiliser MySQL :

aptitude install libpam-mysql

Ce paquet crée également un fichier d'exemple de configuration /etc/pam-mysql.conf qui dans notre approche ne sert à rien. Une autre approche de la configuration de pam pour imap serait de mettre dans ce fichier les informations que nous avons mises dans /etc/pam.d/imap et de modifier ce dernier comme suit:

auth       sufficient   pam_mysql.so config_file=/etc/pam-mysql.conf
account    sufficient   pam_mysql.so config_file=/etc/pam-mysql.conf

Vérifications

L'outil testsaslauthd va nous permettre de vérifier que l'utilisateur cyrus est authentifié :

# testsaslauthd -u cyrus -p epikoi -f /var/spool/postfix/var/run/saslauthd/mux
0: OK "Success."

Web-cyradm devrait maintenant nous permettre de créer des domaines et des comptes dans ces domaines. Créer un nouveau domaine

C'est fait. Voilà qui est fait

Créons maintenant un compte de test : Créer un nouveau compte

Un compte de test

Voilà qui est fait. Voilà qui est fait

Vérification avec l'outil cyradm en ligne de commande :

aptitude install cyrus-admin-2.2

Puis :

# cyradm --user cyrus --server localhost
Password: 
localhost> lm
user/test@nain-t.net (\HasNoChildren)  
localhost> lam user/test@nain-t.net
test@nain-t.net lrswipcda
cyrus lrswipcda
localhost> exit

Ça marche. Il faudra quand même approfondir un peu cet outil. Faites m'y penser si j'oubliais…

En gros, la BAL est bien créée, l'utilisateur test@nain-t.net a tous les droits dessus et l'administrateur cyrus aussi (nécessaire pour l'administration par le compte cyrus).

Et l'utilisateur test@nain-t.net est-il bien authentifié par saslauthd ?

# testsaslauthd -u test@nain-t.net -p epikoi -f /var/spool/postfix/var/run/saslauthd/mux
0: OK "Success."

Impeccable, il pourra donc accéder à sa BAL avec son MUA favori.

Vérification avec telnet :

# telnet localhost 143
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
* OK openmailadmin Cyrus IMAP4 v2.2.13-Debian-2.2.13-14+b1 server ready
10 login test@nain-t.net epikoi
10 OK User logged in
20 logout
* BYE LOGOUT received
20 OK Completedhttp://smartsieve.sourceforge.net/
Connection closed by foreign host.
Il ne reste plus qu'à injecter des messages là dedans avec Postfix, et notre solution sera presque opérationnelle. Il restera à s'occuper un peu de la sécurité de l'ensemble.

Sieve

Il s'agit d'un langage de de filtrage d'e-mails, comparable dans sa fonctionnalité au langage de scripts de procmail. Son avantage est d'être normalisé dans le RFC 5228. Son inconvénient est d'être sans doute moins puissant que le langage procmail.

La souplesse de Sieve vient du fait que l'utilisateur peut placer sur le serveur des règles de filtrage, sans pour autant disposer d'un compte unix. Il existe plusieurs moyens de le faire :

  • un plug-in dans squirrelmail : avelsieve ;
  • le composant Ingo de la suite horde (non testté);
  • Smartsieve est un projet autonome en PHP dédié à cette tâche.

Pour des raisons de sécurité, il est préférable de limiter le service timsieved à l'écoute de localhost, ce qui est le cas par défaut dans la distribution Debian. Extrait du /etc/cyrus.conf :

SERVICES {
...
	# ----------------------------------------------

	# useful if you need to give users remote access to sieve
	# by default, we limit this to localhost in Debian
  	sieve		cmd="timsieved" listen="localhost:sieve" prefork=0 maxchild=100
...
}

Les scripts vont dans /var/spool/sieve/ où ils sont rangés avec la même logique que les boites aux lettres.

De plus, pour que l'utilisateur puisse manipuler ses scripts sieve, il faudra que PAM dispose dans /etc/pam.d/ d'un fichier nommé sieve et, dans l'immédiat, identique à imap.

Note importante

Suppression d'un message

Lors de la suppression d'un message dans la boite de réception, le protocole IMAP prévoit que le message est marqué comme effacé, mais n'est pas supprimé. Pour supprimer définitivement un message, c'est à dire pour l'effacer physiquement sur le serveur, il faut utiliser la commande expunge. Il se trouve que cette procédure est gérée très diversement suivant le MUA employé.

Le plus souvent, le fait d'effacer un message se traduit pas :

  • le marquage dudit message comme « effacé » ;
  • la copie du message dans le répertoire « Trash » (la poubelle).

Autrement dit : Effacer un message revient à le recopier dans un autre répertoire. En croyant gagner de la place, on en perd. Plutôt que de longs discours, voyons ceci sur un exemple. La boite aux lettres de sysop@nain-t.net est vide :

cyrus:/var/spool/cyrus/mail/domain/n/nain-t.net/s/user/sysop# ls -l
total 20
-rw------- 1 cyrus mail    4 2008-07-12 20:42 cyrus.cache
-rw------- 1 cyrus mail  199 2008-07-11 15:43 cyrus.header
-rw------- 1 cyrus mail   76 2008-07-12 20:42 cyrus.index
drwx------ 2 cyrus mail 4096 2008-07-12 23:14 Sent
drwx------ 2 cyrus mail 4096 2008-07-12 23:13 Trash

Les répertoires Sent et Trash le sont également.

sysop@nain-t.net reçoit un message :

cyrus:/var/spool/cyrus/mail/domain/n/nain-t.net/s/user/sysop# ls -l
total 24
-rw------- 1 cyrus mail 1270 2008-07-12 23:18 16.
-rw------- 1 cyrus mail  740 2008-07-12 23:18 cyrus.cache
-rw------- 1 cyrus mail  199 2008-07-11 15:43 cyrus.header
-rw------- 1 cyrus mail  136 2008-07-12 23:18 cyrus.index
drwx------ 2 cyrus mail 4096 2008-07-12 23:14 Sent
drwx------ 2 cyrus mail 4096 2008-07-12 23:13 Trash
Nous retrouvons bien le message sans le répertoire se sysop. La poubelle est toujours vide. sysop lit son message, puis le « supprime » avec son thunderbird favori. Dans son MUA, le message a disparu, mais il se retrouve dans la corbeille. Voyons le résultat dans son répertoire :
cyrus:/var/spool/cyrus/mail/domain/n/nain-t.net/s/user/sysop# ls -l
total 24
-rw------- 2 cyrus mail 1270 2008-07-12 23:18 16.
-rw------- 1 cyrus mail  740 2008-07-12 23:18 cyrus.cache
-rw------- 1 cyrus mail  199 2008-07-11 15:43 cyrus.header
-rw------- 1 cyrus mail  136 2008-07-12 23:21 cyrus.index
drwx------ 2 cyrus mail 4096 2008-07-12 23:14 Sent
drwx------ 2 cyrus mail 4096 2008-07-12 23:21 Trash
cyrus:/var/spool/cyrus/mail/domain/n/nain-t.net/s/user/sysop# ls -l Trash/
total 16
-rw------- 2 cyrus mail 1270 2008-07-12 23:18 19.
-rw------- 1 cyrus mail  740 2008-07-12 23:21 cyrus.cache
-rw------- 1 cyrus mail  199 2008-07-11 16:00 cyrus.header
-rw------- 1 cyrus mail  136 2008-07-12 23:21 cyrus.index
Nous retrouvons bien un message dans Trash, mais le message se trouve toujours dans le répertoire racine (INBOX). En gros, sysop n'a fait que recopier le message dans Trash.

sysop vide la corbeille :

cyrus:/var/spool/cyrus/mail/domain/n/nain-t.net/s/user/sysop# ls -l
total 24
-rw------- 1 cyrus mail 1270 2008-07-12 23:18 16.
-rw------- 1 cyrus mail  740 2008-07-12 23:18 cyrus.cache
-rw------- 1 cyrus mail  199 2008-07-11 15:43 cyrus.header
-rw------- 1 cyrus mail  136 2008-07-12 23:21 cyrus.index
drwx------ 2 cyrus mail 4096 2008-07-12 23:14 Sent
drwx------ 2 cyrus mail 4096 2008-07-12 23:26 Trash
cyrus:/var/spool/cyrus/mail/domain/n/nain-t.net/s/user/sysop# ls -l Trash/
total 12
-rw------- 1 cyrus mail   4 2008-07-12 23:26 cyrus.cache
-rw------- 1 cyrus mail 199 2008-07-11 16:00 cyrus.header
-rw------- 1 cyrus mail  76 2008-07-12 23:26 cyrus.index

Le message a disparu dans Trash, mais il est toujours présent dans la racine du répertoire de sysop (INBOX) !. Pour le faire disparaitre, sysop doit utiliser la commande « compacter », en cliquant du bouton droit sur « courrier entrant » :

cyrus:/var/spool/cyrus/mail/domain/n/nain-t.net/s/user/sysop# ls -l
total 20
-rw------- 1 cyrus mail    4 2008-07-12 23:30 cyrus.cache
-rw------- 1 cyrus mail  199 2008-07-11 15:43 cyrus.header
-rw------- 1 cyrus mail   76 2008-07-12 23:30 cyrus.index
drwx------ 2 cyrus mail 4096 2008-07-12 23:14 Sent
drwx------ 2 cyrus mail 4096 2008-07-12 23:26 Trash

Cette remarque s'applique à tous les dossiers que sysop aura pu créer (à l'exception de la poubelle, qui est systématiquement purgée lorsqu'elle est vidée) y compris le dossier Sent (messages envoyés).

Il est donc important que les utilisateurs en prennent conscience, faute de quoi leur quota sera atteint sans qu'ils ne comprennent pourquoi.

Il est possible de demander à Thunderbird de purger automatiquement le répertoire INBOX lorsqu'il est refermé, mais cette opération ne purgera que le répertoire INBOX et pas les autres.

La bonne pratique consiste à ne pas utiliser la corbeille mais à demander à Thunderbird de marquer les messages comme « effacés » ce qui est le comportement normal, prévu par IMAP. De cette manière le message apparait barré, n'est pas recopié dans Trash et ne disparait effectivement dans l'affichage du MUA que lors de l'envoi de la commande « compacter ».