TUTORIEL PHP 
Conception d'un client de messagerie IMAP (5e partie)
Affichage des principales en-têtes d'un message précis, ainsi que l'ensemble de ses images attachées. (25/11/2005)
Après avoir divergé sur la théorie du format MIME (lire notre article du 17/10/05), nous allons enfin aborder le côté pratique de l'affichage de mails dans ce format, au travers des fonctions dédiées de PHP.

Nous décomposerons pour ce faire le message en quelques-unes de ces composantes (principales en-têtes, fichiers joints). Nous allons voir comment récupérer ses divers éléments pour les afficher correctement.

Récupérer les en-être
Beaucoup d'informations sur le mail sont contenus dans les entêtes : titre, auteur, date, destinaire, serveur... Il nous faut alors récupérer ces en-têtes, et en extraire l'information tant recherchée. Pour cela, deux fonctions PHP s'offrent principalement à nous.

imap_fetchheader() : renvoi les en-têtes sous forme d'une chaîne, qu'il faudra ensuite décomposer au sein d'un tableau, par exemple, pour pouvoir exploiter son contenu simplement. Cette fonction est exploitée surtout quand l'utilisateur veut afficher l'ensemble des en-tête, brut de pomme.

imap_headerinfo() (imap_header()) : renvoi un objet contenant les éléments de l'en-tête, chacune dans sa propriété : subject, fromaddress, toaddress, ccaddress, date, ... C'est elle qui nous utiliserons pour récupérer chaque en-tête.

Voici par exemple comment nous récupérons la date, le titre et l'auteur, au format brut :

if ($mail_cnx = imap_open ("{".$serveur_entrant.$port.$protocole."}".$boite, $identifiant, $mot_de_passe) ) {
  if (isset($_GET['id']) && !empty($_GET['id']) ) {
    $id = $_GET['id'];
    $entetes = imap_header($mail_cnx, $id);
?>
<b>Date : </b><?=$entetes->date;?><br />
<b>Auteur : </b><<?=$entetes->fromaddress;?>><br />


Précisions sur l'adresse
fromaddress n'est cependant pas idéal, car il renvoi une chaîne pas forcément facile à traiter. Idem pour toaddress, d'autant que cette dernière ne facile pas la cas où il y a plusieurs destinataires.

On utilisera alors avantageusement from et to. Ce sont chacun des tableaux qui contiennent quatre entrées : personnal (le nom complet, "Prénom Nom"), mailbox (l'identifiant du compte mail, "mon-compte"), host (l'hébergeur, "exemple.com") et adl. Tous ne sont pas forcément remplis, donc il est de bon temps de vérifier avant affichage. Ceci est d'ailleurs vrai pour tous les composants d'un mail...

Donc, par exemple, pour afficher la chaîne "Prénom Nom <mon-compte@exemple.com>", il faudra combiner les appels sous cette forme :

echo $entetes->from[0]->personal . " <" . $entetes->from[0]->mailbox . "@" . $entetes->from[0]->host . ">";

Pour personal, il faudra également prévoir de décoder une possible chaîne MIME...

  Forum

Réagissez dans les forums de JDN Développeurs

Précisions sur la date
L'affichage brut de la date n'est pas des plus pratiques : echo $entetes->date; nous donne "Thu, 24 Nov 2005 16:38:52 +0100". Il nous faut reprendre cette chaîne et la convertir dans un format plus conforme à nos habitudes :

echo date("d/m/Y - G:i", strtotime($entetes->date) );

Afficher les images
Les images sont encodées au sein du corps du message. Celui-ci peut comprendre une structure en plusieurs parties, qui peut largement varier d'un message à l'autre.

Il nous faut donc parcourir la structure à la recherche de certains signes clefs, et une fois trouvés, appliquer au contenu de cette section de la structure quelques fonctions qui nous permettront de parvenir à nos fins.

if ($struct->type == 1) {
  $nbrparts = !$struct->parts ? "1" : count($struct->parts);
  echo "Ce mail a $nbrparts parties.";
  }

for($i = 0; $i < $nbrparts; $i++) {
  $part = !$struct->parts[$i] ? $part = $struct : $part = $struct->parts[$i];

  if ( ($part->encoding == "ENCBASE64")
        and ($part->subtype == "JPEG"
            or $part->subtype == "GIF"
            or $part->subtype == "PJPEG")) {
    for ($i = 0; $i < count($part->parameters); $i++) {
      $param = $part->parameters[$i];
      if ($param->attribute == "NAME") {
        $nom_fichier = $param->value;
        }
      else {
        $nom_fichier = "Nom de fichier introuvable";
      }
    echo "<b>Image :</b> $nom_fichier<br>";
    echo affiche_image($id, $part, $i+1, $nom_fichier) . "<br>";
    }
  }

function affiche_image($id, $part, $part_id, $nom_fichier) {
  echo "<img src='afficher-image.php?folder=INBOX&msgnum=$id
&part_id=$part_id&type=$part->subtype&name=$nom_fichier'>";
  }


Nous devons faire appel à un fichier exterieur pour afficher effectivement l'image, car il nous faut envoyer des entêtes spécifiques, indiquant au navigateur que l'on veut afficher l'image. Le voici :

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

if ($mail_cnx = imap_open ("{".$serveur_entrant.$port.$protocole."}".$boite, $identifiant, $mot_de_passe) ) {
  Header("Content-type: image/".$_GET['type']."");
  $data = imap_fetchbody($mail_cnx, $_GET['msgnum'], $_GET['part_id']);
  echo imap_base64($data);
  }
?>


Il nous reste le Saint Graal : le corps lui-même, à décoder et à afficher correctement... Ce sera pour notre dernier article.
 
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