Le protocole IMAP4
22/02/2005
 Christian CALECA 
Liste des cours

Le protocole IMAP

Accueil ] [ Introduction ] [ Le protocole ] [ Serveurs IMAP ] [ Plus avec Cyrus ]


Comme nous l'avons dit plus haut, tous les clients de messagerie ne gèrent pas IMAP au mieux. Voir ce que l'on peut faire avec ce protocole à travers un MUA ne donnera pas un aperçu de toutes les possibilités de ce protocole. Et puis, mettre un peu les mains dans le cambouis, ça ne fait pas de mal.

Définition du protocole

RTFRFC 2060, comme on dit chez les branchés.

Il en existe une traduction officieuse en français. Elle est suffisamment bien faite pour ne pas manquer de l'utiliser. Il n'est donc pas question ici de reprendre tout ce qui est dit dedans. Nous allons plutôt essayer de vérifier quelques points par la pratique.

Il est tout de même peut-être bon de rappeler que IMAP est un protocole d'application, qu'il s'appuie sur TCP et que le serveur écoute par défaut sur le port 143.

Mode opératoire

Il n'est pas conseillé de "bricoler" avec des serveurs IMAP de production, par exemple celui (ceux) de votre FAI. Généralement, ces serveurs sont très sollicités. Avec le développement sans cesse croissant des connexions permanentes à haut débit, les habitudes changent .

Tout ceci fait que les serveurs SMTP/POP/IMAP voient leur charge augmenter dans d' énormes proportions.

Pour au moins ces raisons, il est bien plus convenable de bidouiller sur un serveur IMAP "maison". Si l'on dispose d'une (voire plusieurs) machine(s) sous Linux, ce n'est pas obligatoirement compliqué à mettre en oeuvre.

De plus, en ayant complètement la main sur les machines hébergeant les serveurs, nous pourrons modifier les configurations et voir de près comment les boîtes sont construites.

Les serveurs IMAP courants

Nous en avons déjà parlé, rappelons-le :

UW-IMAPD

UW IMAPD est développé par l'université de Washington. Il s'appuie sur le format "mailbox" pour stocker les messages. C'est un format classique que les MDA savent généralement bien gérer. En gros, les messages sont enregistrés dans un fichier unique, pour un utilisateur donné. Le plus souvent, chaque utilisateur devra disposer d'un compte sur le serveur, même si ce compte ne lui permet pas d'ouvrir une session shell. Les dossiers IMAP que le client peut créer se situent au même niveau que INBOX et chaque dossier créé correspond sur le serveur à un fichier.

Ce genre de serveur est extrêmement facile à installer. Nous en utiliserons un exemple sur une Debian woody stable, avec EXIM comme MTA.

CYRUS

Cyrus est " l'autre " serveur IMAP. Développé par l'université de Carnegie Mellon, il s'appuie sur le format "maildir". Les messages sont stockés chacun dans un fichier séparé, rangés dans un répertoire par utilisateur.

Les utilisateurs peuvent être enregistrés dans une base de données, un annuaire LDAP et n'ont absolument pas besoin de disposer d'un compte UNIX sur la machine serveur.

Ce serveur est plus souple, plus sûr, offre plus de possibilités et, bien entendu, est beaucoup plus difficile à installer et à configurer. Nous en verrons un exemple sur cyclope.maison.mrs, une machine Debian "testing".

 

D'autres serveurs existent, comme courier-imap, souvent utilisé avec le SMTP QMAIL. Il est plus proche de Cyrus que de UW-imap et utilise lui aussi le format "Maildir".

Les outils à (presque) tout faire

Pour vérifier et expérimenter le protocole, en plus d'un MUA gérant proprement IMAP, nous utiliserons deux outils de base :

Les comptes pour faire les manips

Nous disposons de trois comptes sur trois serveurs différents (nous avons les moyens) :

testimap@gw2.maison.mrs serveur uw-imap "packagé" dans la Debian Woody
testimap@cyclope.maison.mrs serveur Cyrus 21 de la Debian "testing"

Et d'un client sur un poste Windows XP (pour changer un peu de système).

Premier contact

Comme je vous l'ai dit plus haut, une très honnête traduction de RFC 2060 existe, vous n'avez donc pas manqué de la lire , moi non plus d'ailleurs. Pas encore ? C'est pourtant nécessaire.... Nous savons donc déjà certaines choses :

Dans chacun de ces états, on a droit à un nombre plus ou moins grand de commandes. Dans le premier, non authentifié, on ne peut pas faire grand chose, mais tout de même...

Commençons doucement. Nous allons juste ouvrir une session sur chaque serveur et poser la question "CAPABILITY" à chacun d'eux.

C'est parti :

c:\> telnet gw2.maison.mrs 143
* OK [CAPABILITY IMAP4REV1 X-NETSCAPE LOGIN-REFERRALS AUTH=LOGIN] gw2.maison.mrs
IMAP4rev1 2001.315 at Thu, 6 Nov 2003 15:05:29 +0100 (CET)

A0001 CAPABILITY
* CAPABILITY IMAP4REV1 X-NETSCAPE NAMESPACE MAILBOX-REFERRALS SCAN SORT 
THREAD=REFERENCES THREAD=ORDEREDSUBJECT MULTIAPPEND LOGIN-REFERRALS AUTH=LOGIN
A0001 OK CAPABILITY completed

A0002 LOGOUT
* BYE gw2.maison.mrs IMAP4rev1 server terminating connection
A0002 OK LOGOUT completed
c:\>telnet cyclope.maison.mrs 143
* OK cyclope.maison.mrs Cyrus IMAP4 v2.1.14-IPv6-Debian-2.1.14-1 server ready

A0001 CAPABILITY
* CAPABILITY IMAP4 IMAP4rev1 ACL QUOTA LITERAL+ MAILBOX-REFERRALS NAMESPACE UIDPLUS
ID NO_ATOMIC_RENAME UNSELECT CHILDREN MULTIAPPEND SORT THREAD=ORDEREDSUBJECT
THREAD=REFERENCES IDLE LISTEXT LIST-SUBSCRIBED ANNOTATEMORE
A0001 OK Completed

A0002 LOGOUT
* BYE LOGOUT received
A0002 OK Completed

Sans vraiment comprendre toutes les subtilités de "CAPABILITY", on voit clairement que Cyrus propose d'avantage de choses que UW-imap.

Notez que ce qui est important aux yeux de la norme, c'est que IMAP4rev1 figure dans la liste, ce qui est le cas des deux serveurs.

Quelques commandes simples avec Telnet

Puisque maintenant, vous avez forcément lu les RFC 2060, vous avez pu constater que IMAP4 est bien plus riche que POP3. Nous n'allons pas passer des pages et des pages à analyser toutes les commandes possibles, ce travail n'aurait d'ailleurs d'intérêt que pour ceux qui souhaitent développer un client (ou un serveur) IMAP. L'objectif de ce qui suit est juste de comprendre le principe de fonctionnement.

Les (bons) clients IMAP4 permettent de ne charger que les objets des messages, leur date et leur taille. Il est donc possible, même avec une mauvaise connexion, d'exploiter ce protocole sans blocage. Les conditions de travail ne sont plus les mêmes qu'avec le bon vieux POP3.

Comme nous sommes sur cette page surtout pour étudier le protocole, nous allons faire quelques manips simples avec le serveur uw-imap installé sur gw2, avec un compte tout neuf : testimap2@gw2.maison.mrs. Il vient juste d'être créé et aucun client n'y a encore accédé.

Préliminaires

Commençons par regarder ce qu'il y a dans le répertoire de l'utilisateur "testimap2" :

/home/testimap2# ls
/home/testimap2#

Il n'y a rien du tout. 

Ouverture d'une session IMAP

Il est possible d'utiliser la commande : LOGIN <user> <passwd>. Faisons-le

c:\>telnet gw2.maison.mrs 143
* OK [CAPABILITY IMAP4REV1 X-NETSCAPE LOGIN-REFERRALS AUTH=LOGIN] gw2.maison.mrs
 IMAP4rev1 2001.315 at Sat, 8 Nov 2003 17:16:42 +0100 (CET)
0001 LOGIN testimap2 testimap2
0001 OK [CAPABILITY IMAP4REV1 X-NETSCAPE NAMESPACE MAILBOX-REFERRALS SCAN SORT 
THREAD=REFERENCES THREAD=ORDEREDSUBJECT MULTIAPPEND] User testimap2 authenticated
0002 LOGOUT
* BYE gw2.maison.mrs IMAP4rev1 server terminating connection
0002 OK LOGOUT completed

Ca marche. Dans un cas pareil, les identifiants du client passent en clair sur le réseau, comme avec POP3. Mais il est possible de faire mieux avec la commande AUTHENTICATE. Nous ne la verrons pas avec Telnet, vous comprendrez vite pourquoi. La manipulation est faite avec Thunderbird, le tout sniffé avec Ethereal :

Source        Destination   Protocol Info
192.168.0.252 192.168.0.10  IMAP     Response: * OK [CAPABILITY IMAP4REV1 ...
192.168.0.10  192.168.0.252 IMAP     Request: 1 capability
192.168.0.252 192.168.0.10  IMAP     Response: * CAPABILITY IMAP4REV1 ...
192.168.0.10  192.168.0.252 IMAP     Request: 2 authenticate login
192.168.0.252 192.168.0.10  IMAP     Response: + VXNlciBOYW1lAA==
192.168.0.10  192.168.0.252 IMAP     Request: dGVzdGltYXA=
192.168.0.252 192.168.0.10  IMAP     Response: + UGFzc3dvcmQA
192.168.0.10  192.168.0.252 IMAP     Request: dGVzdGltYXA=
192.168.0.252 192.168.0.10  IMAP     Response: 2 OK [CAPABILITY IMAP4REV1 ...

Vous voyez, c'est un peu compliqué à faire avec telnet. Avec cette méthode, c'est déjà un peu plus difficile de pirater les identifiants du client.

Arranger son intérieur

Avec cette manipulation au moyen de Thunderbird, dont il n'est affiché qu'un court extrait, juste pour voir travailler "AUTHENTICATE", il s'est tout de même passé d'autres choses. La preuve : si nous retournons voir dans le répertoire de l'utilisateur :

/home/testimap2# ls -l
total 4
-rw-------    1 testimap2 nogroup       528 Nov  8 17:29 Trash
/home/testimap2#

Il y a maintenant un répertoire nommé "Trash". Il ne vient certainement pas du ciel, ce doit être Thunderbird qui l'a créé. Ressortons donc la trace Ethereal et cherchons...

Source        Destination   Protocol Info
...
192.168.0.10  192.168.0.252 IMAP     Request: 14 create "Trash"
192.168.0.252 192.168.0.10  IMAP     Response: 14 OK CREATE completed
...

Et nous trouvons ! La commande "CREATE" permet bien de créer un répertoire.

Essayons à la main :

c:\> telnet gw2.maison.mrs 143
* OK [CAPABILITY IMAP4REV1 ...
001 login testimap2 testimap2
001 OK [CAPABILITY IMAP4REV1 ...
002 create "Sent"
002 OK CREATE completed
003 logout
* BYE gw2.maison.mrs IMAP4rev1 server terminating connection
003 OK LOGOUT completed

A priori, ça a l'air d'avoir marché. Vérification sur le serveur :

/home/testimap2# ls -l
total 8
-rw-------    1 testimap2 nogroup       528 Nov  8 18:01 Sent
-rw-------    1 testimap2 nogroup       528 Nov  8 17:29 Trash
/home/testimap2#

Pas de surprise.

Bien. Nous n'allons pas tout passer en revue, l'important est de comprendre le principe. Juste deux ou trois manips et ça ira bien.

Lire un message

Pour ça, il faut déjà qu'il y en ait au moins un à lire. Envoyons un message par l'intermédiaire de "mail" directement depuis le serveur :

/home/testimap2# mail testimap2@gw2.maison.mrs
Subject: test simple
coucou
.
Cc:
/home/testimap2#

A-t-on ajouté quelque chose dans le répertoire de l'utilisateur ?

/home/testimap2# ls -l
total 8
-rw------- 1 testimap2 nogroup 528 Nov 8 18:01 Sent
-rw------- 1 testimap2 nogroup 528 Nov 8 17:29 Trash
/home/testimap2#

Il semble bien que non. Ca peut paraître curieux, mais c'est normal. Le message n'a pas encore été lu et il se trouve ailleurs. Vous aimeriez savoir où ? Nous l'avons déjà vu en page précédente, mais je vais vous le redire...

Nous utilisons sur cette machine le MTA Exim, qui range les message locaux dans le répertoire /var/spool/mail qui est en fait un alias de /var/mail :

/var/mail# ls -l
total 40
-rw-rw----    1 chris    mail        36189 Nov  8 12:41 chris
-rw-rw----    1 testimap2 mail          520 Nov  8 18:09 testimap2
/var/mail#

Ce fichier : "testimap2", contient tous les messages reçus. La preuve : 

/var/mail# cat testimap2
From root@gw2.maison.mrs Sat Nov 08 18:09:47 2003
Return-path: <root@gw2.maison.mrs>
Envelope-to: testimap2@gw2.maison.mrs
Received: from root by ca-marseille-34-108.w80-8.abo.wanadoo.fr with local (Exim 3.35 #1 (Debian))
        id 1AIWap-0006ku-00
        for <testimap2@gw2.maison.mrs>; Sat, 08 Nov 2003 18:09:47 +0100
To: testimap2@gw2.maison.mrs
Subject: test simple
Message-Id: <E1AIWap-0006ku-00@ca-marseille-34-108.w80-8.abo.wanadoo.fr>
From: Christian Caleca <root@gw2.maison.mrs>
Date: Sat, 08 Nov 2003 18:09:47 +0100

coucou

/var/mail#

Allons faire des choses avec telnet :

* OK [CAPABILITY IMAP4REV1 ...
0001 login testimap2 testimap2
0001 OK [CAPABILITY IMAP4REV1 ...
0002 list "*" "*"
* LIST (\NoInferiors) NIL INBOX
* LIST (\NoInferiors \UnMarked) "/" Trash
* LIST (\NoInferiors \UnMarked) "/" .mailboxlist
* LIST (\NoInferiors \UnMarked) "/" Sent
* LIST (\NoInferiors) NIL INBOX
0002 OK LIST completed
0003 select INBOX
* 1 EXISTS
* NO Trying to get mailbox lock from process 26105
* 1 RECENT
* OK [UIDVALIDITY 1068314830] UID validity status
* OK [UIDNEXT 2] Predicted next UID
* FLAGS (\Answered \Flagged \Deleted \Draft \Seen)
* OK [PERMANENTFLAGS (\* \Answered \Flagged \Deleted \Draft \Seen)] Permanent flags
* OK [UNSEEN 1] first unseen message in /var/mail/testimap2
0003 OK [READ-WRITE] SELECT completed
0004 logout
* BYE gw2.maison.mrs IMAP4rev1 server terminating connection
0004 OK LOGOUT completed

La commande LIST

De la façon utilisée ici, elle ne fait qu'afficher le contenu du répertoire de l'utilisateur, à quelque chose près : INBOX, qui n'est rien d'autre que le fichier /var/mail/<user> dans notre exemple. Comme vous avez maintenant lu les RFC, vous savez que :

La commande SELECT

Elle permet de sélectionner le dossier que l'on souhaite consulter. Dans l'exemple, nous apprenons :

Pour le reste, je vous laisse chercher dans les RFC.

Nous n'avons pas fait grand chose encore, mais retournons tout de même voir /var/mail/testimap2 :

/var/mail# cat testimap2
From root@gw2.maison.mrs Sat Nov 08 19:05:21 2003
Return-path: <root@gw2.maison.mrs>
Envelope-to: testimap2@gw2.maison.mrs
Received: from root by ca-marseille-34-108.w80-8.abo.wanadoo.fr with local (Exim 3.35 #1 (Debian))
        id 1AIXSb-0006nG-00
        for <testimap2@gw2.maison.mrs>; Sat, 08 Nov 2003 19:05:21 +0100
To: testimap2@gw2.maison.mrs
Subject: test simple
Message-Id: <E1AIXSb-0006nG-00@ca-marseille-34-108.w80-8.abo.wanadoo.fr>
From: Christian Caleca <root@gw2.maison.mrs>
Date: Sat, 08 Nov 2003 19:05:21 +0100
X-IMAPbase: 1068314830 1
Status: O
X-Status:
X-Keywords:
X-UID: 1
coucou

/var/mail#

A l'évidence, le serveur IMAP a rajouté quelques lignes dans l'en-tête du message...

Rejouons la connexion par telnet :

c:\> telnet gw2.maison.mrs 143
* OK [CAPABILITY IMAP4REV1 ...
01 login testimap2 testimap2
01 OK [CAPABILITY IMAP4REV1 ...
02 list "*" "*"
* LIST (\NoInferiors) NIL INBOX
* LIST (\NoInferiors \UnMarked) "/" Trash
* LIST (\NoInferiors \UnMarked) "/" .mailboxlist
* LIST (\NoInferiors \UnMarked) "/" Sent
* LIST (\NoInferiors) NIL INBOX
02 OK LIST completed
03 select INBOX
* 1 EXISTS
* 0 RECENT
* OK [UIDVALIDITY 1068365879] UID validity status
* OK [UIDNEXT 2] Predicted next UID
* FLAGS (\Answered \Flagged \Deleted \Draft \Seen)
* OK [PERMANENTFLAGS (\* \Answered \Flagged \Deleted \Draft \Seen)] Permanent flags
* OK [UNSEEN 1] first unseen message in /var/mail/testimap2
03 OK [READ-WRITE] SELECT completed
04 logout
* BYE gw2.maison.mrs IMAP4rev1 server terminating connection
04 OK LOGOUT completed

La seule chose qui a changé, c'est que le "1 RECENT" est passé à "0 RECENT". Nous n'avons pas lu le message (UNSEEN 1), mais le serveur a noté que depuis notre dernière visite, il n'y a pas eu de nouveaux messages.

Rien n'a changé dans /var/mail/testimap2.

La commande FETCH

Vous avez pu constater dans les RFC la complexité de cette commande, nous allons l'utiliser ici simplement.

D'abord pour lire l'en-tête de l'unique message disponible (BODY[HEADER]) puis pour lire le texte du message (BODY[TEXT]) :

* OK [CAPABILITY IMAP4REV1...
001 login testimap2 testimap2
001 OK [CAPABILITY IMAP4REV1 ...
002 select INBOX
* 1 EXISTS
* NO Trying to get mailbox lock from process 28032
* 0 RECENT
* OK [UIDVALIDITY 1068367935] UID validity status
* OK [UIDNEXT 2] Predicted next UID
* FLAGS (\Answered \Flagged \Deleted \Draft \Seen)
* OK [PERMANENTFLAGS (\* \Answered \Flagged \Deleted \Draft \Seen)] Permanent flags
002 OK [READ-WRITE] SELECT completed

003 fetch 1 BODY[HEADER]
* 1 FETCH (BODY[HEADER] {471}
Return-path: <root@gw2.maison.mrs>
Envelope-to: testimap2@gw2.maison.mrs
Received: from root by gw2.maison.mrs with local (Exim
3.35 #1 (Debian))
        id 1AIlIA-0007Hi-00
        for <testimap2@gw2.maison.mrs>; Sun, 09 Nov 2003 09:51:30 +0100
To: testimap2@gw2.maison.mrs
Subject: test simple
Message-Id: <E1AIlIA-0007Hi-00@gw2.maison.mrs>
From: Christian Caleca <root@gw2.maison.mrs>
Date: Sun, 09 Nov 2003 09:51:30 +0100
)
003 OK FETCH completed

004 fetch 1 BODY[TEXT]
* 1 FETCH (BODY[TEXT] {8}
coucou
)
004 OK FETCH completed
005 logout
* BYE gw2.maison.mrs IMAP4rev1 server terminating connection
005 OK LOGOUT completed

Voyez les RFC pour une description complète des options de la commande FETCH.

Retournons voir dans /var/mail/testimap2 si quelque chose a changé :

/var/mail# cat testimap2
From root@gw2.maison.mrs Sun Nov 09 09:51:30 2003
Return-path: <root@gw2.maison.mrs>
Envelope-to: testimap2@gw2.maison.mrs
Received: from root by gw2.maison.mrs with local (Exim 3.35 #1 (Debian))
        id 1AIlIA-0007Hi-00
        for <testimap2@gw2.maison.mrs>; Sun, 09 Nov 2003 09:51:30 +0100
To: testimap2@gw2.maison.mrs
Subject: test simple
Message-Id: <E1AIlIA-0007Hi-00@gw2.maison.mrs>
From: Christian Caleca <root@gw2.maison.mrs>
Date: Sun, 09 Nov 2003 09:51:30 +0100
X-IMAPbase: 1068314830 1
Status: RO
X-Status:
X-Keywords:
X-UID: 1

coucou

/var/mail#

Oui. Le "tag" Status est passé de O à RO.

La commande STORE

Cette commande permet de modifier les "flags" attachés à un message.

Les flags que l'on peut attribuer à un message sont les suivants :

\Seen    Le message a été lu
      
\Answered    On a répondu au message
      
\Flagged    Le message est "flagged" pour y donner une attention urgente/spéciale
      
\Deleted    Le message est "deleted" (supprimé) pour que plus tard un EXPUNGE puisse l'enlever
      
\Draft    Le message n'a pas été entièrement composé (marqué en tant que brouillon (draft)).
      
\Recent    Le message est arrivé récemment dans cette boîte aux lettres. Cette session est la première session qui ait reçu une notification a propos de ce message.

Les sessions ultérieures ne verront pas l'état \Recent pour ce message. Ce drapeau ne peut être modifié par le client.

S'il n'est pas possible de déterminer si oui ou non, cette session est la première session a être notifiée du message, alors ce message DEVRA (SHOULD) être considéré comme récent. Si de multiples connexions ont sélectionné la même boîte aux lettres simultanément, on ne peut définir laquelle de ces connexions verra les messages arrivés nouvellement avec l'état \Recent et quelles vont être celles qui le verront sans \Recent.
   

Extrait de http://jlr31130.free.fr/rfc2060.html#2.3.2.

Il est temps maintenant de reprendre un point très important de IMAP. Très important, parce que si l'on n'a pas compris ce qui va suivre, on va laisser son compte IMAP s'engraisser sans comprendre pourquoi et arrivera un jour où votre BAL se retrouvera pleine, vos messages entrants seront refusés, alors que vous pensez avoir bien fait le ménage.

Un message considéré comme effacé ne l'est pas. il a juste le flag \Deleted positionné.

Comme c'est clairement indiqué, seul le flag "\Recent" ne peut être modifié par le client.

Le problème qui se pose avec la plupart des clients de messagerie est le suivant :

Lorsque l'utilisateur méthodique efface ensuite le contenu de la poubelle, il ne fait que marquer dans Trash les messages avec le flag \Deleted

Vu de dehors, tout semble vide, vu de dedans, votre message existe toujours, et en double, en plus !

Démonstration.

Nous avons déjà vu ça en page précédente, mais c'est tellement important qu'il vaut mieux le répéter

Nous repartons d'un compte IMAP parfaitement vide, nous le vérifions sur le serveur :

/var/mail# cat testimap2

# Il n'y a rien dans /var/mail/testimap2

/var/mail# cat /home/testimap2/Trash
From MAILER-DAEMON Sun Nov  9 10:48:15 2003
Date: 09 Nov 2003 10:48:15 +0100
From: Mail System Internal Data <MAILER-DAEMON@gw2.maison.mrs>
Subject: DON'T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA
Message-ID: <1068371295@gw2.maison.mrs>
X-IMAP: 1068308988 0000000004
Status: RO

This text is part of the internal format of your mail folder, and is not
a real message.  It is created automatically by the mail system software.
If deleted, important folder data will be lost, and it will be re-created
with the data reset to initial values.

# Là, il y a quelque chose, mais le texte du message l'indique clairement:
# c'est un message nécessaire au système MAILBOX , ce n'est pas un réel message
# et il ne faut pas le détruire.

/var/mail#

Envoi d'un message de test, comme vu plus haut :

/var/mail# mail testimap2@gw2.maison.mrs
Subject: test DELETE
message destiné à devenir un fantôme...
.
Cc:
ca-marseille-35-89:/var/mail#

Ce n'est pas la peine de tout refaire, nous savons qu'il est maintenant dans /var/mail/testimap2.

Nous allons utiliser Thunderbird pour :

Mais Ethereal va suivre toutes ces opérations...

Pour alléger la lecture, je supprime la partie authentification, repérage de tous les paramètres IMAP, de même que tout ce qui ne concerne que TCP. Nous démarrons à la sélection de INBOX :

Source         Destination    Protocol Info
# Sélection de INBOX
192.168.0.15   192.168.0.252  IMAP     Request: 13 select "INBOX"
192.168.0.252  192.168.0.15   IMAP     Response: * 1 EXISTS
192.168.0.15   192.168.0.252  IMAP     Request: 14 UID fetch 1:* (FLAGS)
192.168.0.252  192.168.0.15   IMAP     Response: * 1 FETCH (UID 1 FLAGS (\Recent))
192.168.0.15   192.168.0.252  IMAP     Request: 15 UID fetch 1 (UID RFC822.SIZE FLAGS BODY.PEEK[HEADER...
192.168.0.252  192.168.0.15   IMAP     Response: * 1 FETCH (UID 1 RFC822.SIZE 512 FLAGS (\Recent) BODY[HEADER.FIELDS...
# Lecture du message
192.168.0.15   192.168.0.252  IMAP     Request: 16 UID fetch 1 (UID RFC822.SIZE BODY[])
192.168.0.252  192.168.0.15   IMAP     Response: * 1 FETCH (UID 1 RFC822.SIZE 512 BODY[] {512}
# Copie dans Trash
192.168.0.15   192.168.0.252  IMAP     Request: 17 uid copy 1 "Trash"
192.168.0.252  192.168.0.15   IMAP     Response: 17 OK UID COPY completed
# Effacement de INBOX (positionnement du flag "\Deleted")
192.168.0.15   192.168.0.252  IMAP     Request: 18 uid store 1 +FLAGS (\Deleted)
192.168.0.252  192.168.0.15   IMAP     Response: * 1 FETCH (FLAGS (\Recent \Seen \Deleted) UID 1)
192.168.0.252  192.168.0.15   IMAP     Response: * OK [CAPABILITY IMAP4REV1 ...
...
# Sélection de Trash
192.168.0.15   192.168.0.252  IMAP     Request: 2 select "Trash"
192.168.0.252  192.168.0.15   IMAP     Response: * 1 EXISTS
192.168.0.15   192.168.0.252  IMAP     Request: 3 UID fetch 1:* (FLAGS)
192.168.0.252  192.168.0.15   IMAP     Response: * 1 FETCH (UID 6 FLAGS (\Seen))
192.168.0.15   192.168.0.252  IMAP     Request: 4 UID fetch 6 (UID RFC822.SIZE FLAGS BODY.PEEK[HEADER....
192.168.0.252  192.168.0.15   IMAP     Response: * 1 FETCH (UID 6 RFC822.SIZE 512 FLAGS (\Seen) BODY[HEADER.FIELDS...
# Lecture du message qui se trouve dans la poubelle
192.168.0.15   192.168.0.252  IMAP     Request: 5 UID fetch 6 (UID RFC822.SIZE BODY[])
192.168.0.252  192.168.0.15   IMAP     Response: * 1 FETCH (UID 6 RFC822.SIZE 512 BODY[] {512}
# Effacement du message dans Trash (positionnement du flag \Deleted)
192.168.0.15   192.168.0.252  IMAP     Request: 6 uid store 6 +Flags (\Deleted)
192.168.0.252  192.168.0.15   IMAP     Response: * 1 FETCH (FLAGS (\Seen \Deleted) UID 6)
...
# Il ne se passe plus rien d'important.

A ce niveau de la manipulation, l'utilisateur de Thunderbird :

Il n'en est rien, la preuve :

/var/mail# cat testimap2
From root@gw2.maison.mrs Sun Nov 09 11:03:25 2003
Return-path: <root@gw2.maison.mrs>
Envelope-to: testimap2@gw2.maison.mrs
Received: from root by gw2.maison.mrs with local (Exim 3.35 #1 (Debian))
id 1AImPl-0007KO-00
for <testimap2@gw2.maison.mrs>; Sun, 09 Nov 2003 11:03:25 +0100
To: testimap2@gw2.maison.mrs
Subject: test DELETE
Message-Id: <E1AImPl-0007KO-00@gw2.maison.mrs>
From: Christian Caleca <root@gw2.maison.mrs>
Date: Sun, 09 Nov 2003 11:03:25 +0100
X-IMAPbase: 1068372272 1
Status: RO
X-Status: D
X-Keywords:
X-UID: 1

message destiné à devenir un fantôme...

/var/mail#

Dans /var/mail/testimap2 (INBOX) le message est toujours présent, il n'y a que X-STATUS: D pour indiquer qu'il est détruit.

/var/mail# cat /home/testimap2/Trash
From MAILER-DAEMON Sun Nov  9 11:04:51 2003
Date: 09 Nov 2003 11:04:51 +0100
From: Mail System Internal Data <MAILER-DAEMON@gw2.maison.mrs>
Subject: DON'T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA
Message-ID: <1068372291@gw2.maison.mrs>
X-IMAP: 1068308988 0000000006
Status: RO

This text is part of the internal format of your mail folder, and is not
a real message.  It is created automatically by the mail system software.
If deleted, important folder data will be lost, and it will be re-created
with the data reset to initial values.

From root@gw2.maison.mrs Sun Nov 09 11:03:25 2003
Return-path: <root@gw2.maison.mrs>
Envelope-to: testimap2@gw2.maison.mrs
Received: from root by gw2.maison.mrs with local (Exim 3.35 #1 (Debian))
        id 1AImPl-0007KO-00
        for <testimap2@gw2.maison.mrs>; Sun, 09 Nov 2003 11:03:25 +0100
To: testimap2@gw2.maison.mrs
Subject: test DELETE
Message-Id: <E1AImPl-0007KO-00@gw2.maison.mrs>
From: Christian Caleca <root@gw2.maison.mrs>
Date: Sun, 09 Nov 2003 11:03:25 +0100
Status: RO
X-Status: D
X-Keywords:
X-UID: 6

message destiné à devenir un fantôme...

/var/mail#

Dans /home/testimap2/Trash, La poubelle, le message est toujours présent, il n'y a que X-STATUS: D pour indiquer qu'il est détruit.

Autrement dit, alors même que l'on croit s'être définitivement débarrassé du message, on n'a fait que le copier en double dans son système de messagerie...

Comment faire alors ?

La commande EXPUNGE

Rassurez vous, IMAP4rev1 a prévu cet ennui et met à disposition une commande qui élimine définitivement tous les messages marqués \Deleted dans un répertoire donné.

Nous l'utilisons avec Telnet :

* OK [CAPABILITY IMAP4REV1...
001 login testimap2 testimap2
001 OK [CAPABILITY IMAP4REV1 ...
002 select INBOX
* 1 EXISTS
* 0 RECENT
* OK [UIDVALIDITY 1068372272] UID validity status
* OK [UIDNEXT 2] Predicted next UID
* FLAGS (\Answered \Flagged \Deleted \Draft \Seen)
* OK [PERMANENTFLAGS (\* \Answered \Flagged \Deleted \Draft \Seen)] Permanent flags
002 OK [READ-WRITE] SELECT completed
003 expunge
* 1 EXPUNGE
* 0 EXISTS
* 0 RECENT
003 OK Expunged 1 messages

004 select Trash
* 1 EXISTS
* 0 RECENT
* OK [UIDVALIDITY 1068308988] UID validity status
* OK [UIDNEXT 7] Predicted next UID
* FLAGS (\Answered \Flagged \Deleted \Draft \Seen)
* OK [PERMANENTFLAGS (\* \Answered \Flagged \Deleted \Draft \Seen)] Permanent flags
004 OK [READ-WRITE] SELECT completed
005 expunge
* 1 EXPUNGE
* 0 EXISTS
* 0 RECENT
005 OK Expunged 1 messages
006 logout
* BYE gw2.maison.mrs IMAP4rev1 server terminating connection
006 OK LOGOUT completed

retour sur le serveur :

/var/mail# cat testimap2
/var/mail#

/var/mail/testimap2 (INBOX) est bien vide...

/var/mail# cat /home/testimap2/Trash
From MAILER-DAEMON Sun Nov 9 11:40:30 2003
Date: 09 Nov 2003 11:40:30 +0100
From: Mail System Internal Data <MAILER-DAEMON@gw2.maison.mrs>
Subject: DON'T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA
Message-ID: <1068374430@gw2.maison.mrs>
X-IMAP: 1068308988 0000000006
Status: RO

This text is part of the internal format of your mail folder, and is not
a real message. It is created automatically by the mail system software.
If deleted, important folder data will be lost, and it will be re-created
with the data reset to initial values.

/var/mail#

et /home/testimap2/Trash est également vide. Ouf !

Conclusions

Ce court exposé n'avait d'autre ambition que de montrer quelques points importants. Il est clair que celui qui voudra développer un client de messagerie IMAP devra effectivement lire les RFC et faire beaucoup plus de manipulations préliminaires que celles que nous avons vues ici.

Emploi des commandes IMAP

Les commande IMAP sont toutes en mode texte, comme pour tout protocole d'application "classique". Elles sont donc utilisables plus ou moins simplement avec telnet. Ici, c'est nettement plus compliqué qu'avec POP3, mais ça reste faisable.

Pourquoi sont-elles précédées d'un "tag" ?

Comme vous avez attentivement lu les RFC, vous savez que c'est parce que le client peut envoyer plusieurs commandes sans obligatoirement attendre à chaque fois la réponse. Le "tag" permet donc de retrouver facilement la réponse à une commande donnée.

De l'importance de EXPUNGE...

Nous avons vu qu'il est fondamental de paramétrer correctement son client de messagerie pour qu'il envoie périodiquement la commande EXPUNGE au serveur sur les divers dossiers de notre messagerie. Avec Thunderbird :

Je vous laisse le soin de trouver l'équivalent sur d'autres clients de messagerie.

Le format MAILBOX

Au travers de ces manipulations, nous avons pu comprendre que le format MAILBOX consiste en un unique fichier par dossier, dans lequel tous les messages sont ajoutés les uns derrière les autres, avec quelques drapeaux spécifiques pour indiquer l'état de ces messages (X-IMAPbase:, Status:, X-Status:, X-Keywords:, X-UID: ).

Ce système, d'ailleurs repris par la plupart des clients de messagerie pour le stockage en local des messages, offre au moins un gros inconvénient : si le fichier est endommagé, la totalité de son contenu sera probablement perdue.

Le format MAILDIR, que nous n'avons pas vu ici, élimine en grande partie cet inconvénient. Nous le verrons rapidement dans la page suivante.


Accueil ] [ Introduction ] [ Le protocole ] [ Serveurs IMAP ] [ Plus avec Cyrus ]