Comment créer un mail texte/HTML en PHP avec les images intégrées et surtout faire en sorte que ce mail soit lisible par une majorité de clients de messagerie ou webmail.
Après de nombreuses recherches qui ne me donnaient pas entière satisfaction, j'ai finalement trouvé une architecture de mail qui permet d'avoir à la fois une version HTML, texte et les images intégrées directement dans le corps de celui-ci.
Comme vous le savez peut-être, un mail est séparé en plusieurs parties définies par des "boundaries" (frontières) qui délimitent chaque élément du mail.
Dans l'exemple suivant, le mail complet doit avoir comme Content-Type multipart/alternative. Ceci signifie que le client mail qui recevra le courrier devra utiliser une seule partie du mail : la partie texte ou HTML. C'est très utile pour une question de compatibilité ou en cas d'absence du support HTML par le logiciel de messagerie.
Voici un exemple de code PHP :
// definition du saut de ligne et des boundaries
pour chaque partie du mail
$eol="\r\n";
$mime_boundary = md5(time());
$html_mime_boundary = $mime_boundary."_html";
$text_mime_boundary = $mime_boundary."_text";
$image_mime_boundary = $mime_boundary."_image";
$related_mime_boundary = $mime_boundary."_related";
$headers = "";
$headers .= "Reply-To: no-reply".$eol;
$headers .= "Return-Path: no-reply".$eol;
$headers .= "Message-ID: <".time()."-".$from.">".$eol;
$headers .= "X-Mailer: PHP v".phpversion().$eol;
$headers .= 'MIME-Version: 1.0'.$eol;
// content-type : alternative pour la gestion du format texte/html
et déclaration de la "boundary"
$headers .= "Content-Type: multipart/alternative;
boundary=\"--".$mime_boundary."\"".$eol.$eol;
// ATTENTION !!! Notez l'ajout de "--" en plus des précédents
$msg = "----".$mime_boundary.$eol;
// déclaration du format texte
$msg .= "Content-Type: text/plain; charset=UTF-8".$eol;
$msg .= "Content-Transfer-Encoding: base64".$eol.$eol;
// ajout du message en texte
// notez l'utilisation de la fonction chunk_split et de
// l'encodage en base 64 (pour plus d'explications,
// voir la partie HTML du mail)
$msg .= chunk_split(base64_encode($text_body)).$eol.$eol;
// on sépare les partie avec la "boundary" alternative
$msg .= "----".$mime_boundary.$eol;
// creation de la partie HTML contenant du HTML
et d'autres éléments (images, ...)
$msg .= "Content-Type: multipart/related;
boundary=\"--".$related_mime_boundary."\"".$eol.$eol;
// ATTENTION !!! Notez l'ajout de "--" en plus des précédents
$msg .= "----".$related_mime_boundary.$eol;
// partie HTML
$msg .= "Content-Type: text/html; charset=UTF-8".$eol;
$msg .= "Content-Transfer-Encoding: base64".$eol.$eol;
// ajout du message HTML
// notez l'utilsation du chunk_split et de l'encodage en base64
// pour éviter que le contenu en clair et la limite de 1000 caractères
// par ligne ne viennent perturber le serveur SMTP
$msg .= chunk_split(base64_encode($html_body)).$eol.$eol;
// on sépare les partie avec la "boundary" related
$msg .= "----".$related_mime_boundary.$eol;
// déclaration des images (encodées en Base 64)
$attached = "/header.jpg";
$msg .= "Content-Type: ".mime_content_type($attached).";
name=\"header.jpg\"".$eol;
$msg .= "Content-Transfer-Encoding: base64".$eol;
$msg .= "Content-ID: ".$eol;
$msg .= "Content-Description: header.jpg".$eol;
$msg .= "Content-Disposition: inline; filename=\"header.jpg\"".$eol;
$msg .= "Content-Location: header.jpg".$eol.$eol;
$file = fopen($attached,'rb');
$data = fread($file,filesize($attached));
fclose($file);
$data = chunk_split(base64_encode($data));
$msg .= $data.$eol;
// on ferme la "boundary" de la partie "related"
(Notez l'ajout de "--" à la fin de la boundary pour fermer)
$msg .= "----".$related_mime_boundary."--".$eol;
/** AJOUTER ICI D'AUTRES IMAGES OU ELEMENTS SI NECESSAIRE
VEILLEZ A LES ENCODER EN BASE 64 ET A LES SEPARER
AVEC LA "BOUNDARY" RELATED*/
// on ferme la "boundary" de la partie "alternative"
en fait on ferme le mail complet (Notez
l'ajout de "--" à la fin de la "boundary" pour fermer)
$msg .= "----".$mime_boundary."--".$eol.$eol;
Pour chaque image ajoutée, vous remarquerez qu'il faut déclarer un "Content-ID". C'est cet identifiant qui servira à utiliser l'image dans le code HTML de la façon suivante :
<img src="cid:header"/>