TUTORIEL PHP 
Conception d'un client de messagerie IMAP (3e partie)
Suite de notre série, où nous apportons à notre script des fonctionnalités de lecture brute, avec décomposition d'un message en ses parties. (05/09/2005)
Nous continuons notre exploration des fonctionnalités IMAP (en fait POP3 pour l'heure) de PHP (voir nos articles du 03/05/2005 et du 03/06/2005 pour les deux premières parties de cette série). En l'état actuel des choses, voici ce dont nous disposons : une page principale qui affiche le contenu de l'en-tête des e-mails d'une boîte POP3, et un mail-delete.php qui nous permet d'effacer les e-mails de manière transparente.

Notre première version permettait d'afficher les 256 premiers octets d'un e-mail, mais la dernière version ne le fait plus. Nous allons donc ici prendre en charge l'affichage complet d'un e-mail (contenu MIME compris, en brut).

Script principal
Notre script du 3 juin avait modifié les colonnes du tableau d'affichage pour permettre l'ajout du numéro du message, ainsi que celui d'une case à cocher pour les messages à effacer. C'était là une modification statique, il nous reste à en faire une plus dynamique : celle qui permet, lors d'un clic sur le sujet du message, d'ouvrir celui-ci. En bref, nous allons ajouter à la boucle principale un lien vers le fichier mail-lire.php, qui de toute évidence affichera le contenu en question :

      <tr>
        <td><?=$i;?></td>
        <td><?=$message->headers['date'];?></td>
        <td><?=$message->headers['from'];?></td>
        <td>
          <b><a href="mail-lire.php?id=<?=$i;?>">
            <?=wordwrap($message->headers['subject'], 40, '<br />');?>
          </a></b>
        </td>
        <td><input type="checkbox" name="delete[]" value="<?=$i;?>"></td>
      </tr>


Ceci mit en place, il reste à construire l'affichage même de l'e-mail

Affichage

Avec mail-lire.php, nous avons un but simple (pour le moment) : afficher les principales informations contenues dans notre e-mail. À savoir : la date, l'auteur, le titre, et le contenu même. Le problème de nos jours est que la plupart des e-mails sont envoyés au format MIME (par exemple pour ajouter des fichiers), donc il nous faudra plus travailler que si les mails étaient simplement envoyés en texte brut.

Les fonctions internes de PHP nous permettent de gérer la plupart des situations, mais pour parer à toutes les éventualités, il faudra sensiblement plus de code que ce que nous vous présentons ici - ou passer par une bibliothèque dédiée, comme PEAR::Mail/mimeDecode.

Un e-mail est donc composé de deux grandes sections : l'en-tête et le corps.  Si l'en-tête est plus ou moins la même selon les messages (avec de possibles ajouts propriétaires ici et là), le corps peut soit être en texte clair, soit en "multipart" : il contiendrait alors une version claire et une version HTML du message, cette dernière étant encodée dans une section MIME.

Contentons-nous pour le moment d'afficher les principales en-têtes, et de rendre le corps du message le plus lisible possible :

<?php
require 'mail-config.php';

if ($mail_cnx = imap_open ("{".$serveur_entrant.$port.$protocole."}".$boite, $identifiant, $mot_de_passe) ) {
  if (isset($_GET['id']) && !empty($_GET['id']) ) {
    $id = $_GET['id'];


Après avoir récupéré les informations sur le compte e-mail, stockées dans le fichier mail-config.php, nous nous connectons au serveur avec celles-ci. Une fois la connexion établie, nous nous assurons que nous disposons bien d'un identifiant pour le mail, et le simplifions dans $id.

    $entetes = imap_header($mail_cnx, $id);
    $corps = imap_body($mail_cnx, $id);
    $struct = imap_fetchstructure($mail_cnx, $id);
    $nbrparts = count($struct->parts);


Nous commençons ici à décomposer le message : les fonctions IMAP de PHP nous permettent de cibler précisément ce que nous voulons récupérer :
- imap_header pour les en-têtes
- imap_body pour le corps brut
- imap_fetchstructure pour créer un objet comprenant toutes les sous-parties du message
- imap_fetchbody pour extraire une partie précise (que nous utilisons juste après.

La différence entre imap_body et imap_fetchbody tient dans le résultat : la première donne l'intégralité du corps en brut (et n'est donc à utiliser que dans le cas où un message ne contient pas de sous-parties MIME), tandis que la seconde permet de mieux cibler ce que l'on veut extraire.

    if (!empty($struct->parts)) {
      for ($i=0, $j=count($struct->parts); $i < $j; $i++) {
        $partie = $struct->parts[$i];
        if ($partie->subtype == 'PLAIN') {
          $corps = imap_fetchbody($mail_cnx, $id, $i+1);
          }
        } // fin for
      } // fin if !empty


Notre objet $struct contient la structure du message, dont le tableau $struct->parts, qui lui décrit des objets décrivant les diverses parties du message. À partir de là, on peut récupérer la section qui nous intéresse, pour peu que l'on sache la désigner...

    $corps = nl2br(htmlspecialchars(strip_tags($corps, '<a>')));
?>


Nous nettoyons ici notre corps pour qu'il s'affiche de manière lisible. Ceci est temporaire. Nous améliorerons le traitement du corps dans le prochain volet.

    <table border="1">
      <tr>
        <td colspan="3"><a href="imap-3.php">Retour à la boîte aux lettres</a> <input type="submit" name="repondre" value="Répondre" />
         <input type="submit" name="transferer" value="Transférer" />
         <input type="submit" name="effacer" value="Effacer" /></td>
      </tr>
      <tr>
        <td><?=$id;?></td>
        <td><b>Date : </b><?=$entetes->date;?></td>
        <td><b>Auteur : </b><<?=$entetes->fromaddress;?>></td>
      </tr>
      <tr>
        <td colspan="3"><b>Sujet : </b><?=$entetes->subject;?></td>
      </tr>
      <tr>
        <td colspan="3"><?=$corps;?></td>
      </tr>
    </table>


Reste à afficher le tout, dans un tableau regroupant les diverses données répérées. L'objet $entetes nous permet d'accéder aux propriétés utiles (date, adresse, sujet), tandis que nous affichons pour l'heure notre corps tel quel.

<?php
    } // fin isset/empty
  } // fin cnx
imap_close($mail_cnx);

?>


Enfin, nous fermons la connexion.

  Forum

Réagissez dans les forums de JDN Développeurs

Reste la partie la plus délicate de la lecture de l'e-mail : la gestion des parties, de MIME, et des encodages. Au lieu de nous reposer sur PEAR pour faire cela, nous tenterons la prochaine fois de décortiquer les diverses manières de parvenir à un résultat lisible et utile.
 
Xavier Borderie, JDN Développeurs
 
Accueil | Haut de page
 
 





Quand achetez-vous le plus en ligne ?
Du lundi au vendredi
Le samedi
Le dimanche

Tous les sondages