E-mails transactionnels : joindre les images aux messages

  • De le 25 septembre 2010
  • Difficulté : 3/4

E-mails transactionnels : joindre les images aux messages Les clients de messagerie bloquent systématiquement les contenus distants : la simple inclusion du logo de la boutique génère un avertissement, pas toujours rassurant pour l'internaute. Alors pourquoi ne pas inclure les images directement dans l'e-mail ?

Recommandations

L'enjeu majeur de l'e-mailing pour un site e-commerce est de passer au travers des barrières anti-spam, de moins en moins permissives. L'e-mail reste la plus part du temps le seul lien entre le client et le marchand : suivi de commande, informations de connexion, factures...

Je ne préconise pas l'inclusion d'images dans les e-mails à destination des clients, les recommandations sont généralement assez claires sur ce point :

  • N'utilisez pas trop d'images dans vos e-mails. Moins d'images vous utiliserez, mieux se portera votre e-mail face aux logiciels anti-spam
  • Evitez les pièces jointes, préférez passer par un lien sur vos serveurs

Source : Insidedaweb - Emailing, 20 astuces anti-spam.

Les e-commerçants ont souvent le désire d'agrémenter les messages d'images, et d'y faire figurer au minimum le logo de la boutique. Un lien vers l'image sur le serveur du commerçant engendrera systématiquement ce type d'avertissement :

E-mails et contenus distants

L'affichage d'un avertissement sur la protection de la vie privée dans un message destiné à fournir un mot de passe peut générer certaines craintes... Pour ce type de mail "sensible" il parait évident de se séparer des images.

Pour les e-mails de suivi de commande, de confirmation de livraison ou de facture, un e-mail correctement stylisé est largement recommandé.

Inclure les images directement dans l'e-mail

Ces recommandations établies, il est tout de même intéressant de se pencher sur la question d'inclure directement les images dans le message. Les freins à ce type de pratique sont donc le blocage de certains anti-spams, et l'augmentation du poids des messages.

L'insertion d'un simple logo de quelques kilo-octets peut cependant ne pas poser problème. Il faudra effectuer une série de tests au préalable.

L'objectif de notre module sera donc d'extraire l'ensemble des images que composent le message, de les joindre à l'e-mail, puis d'établir un lien entre le chemin de l'image et la pièce jointe. Nous obtiendrons ainsi un affichage des images, sans avertissement sur la confidentialité :

E-mails et contenus distants

Architecture du module

  • app/code/local/Magentix/ImageAttachments/etc/
  • config.xml
  • app/code/local/Magentix/ImageAttachments/Model/Email/
  • Template.php
  • app/etc/modules/
  • Magentix_ImageAttachments.xml

Développement du module

Rien de très complexe dans l'architecture. Il s'agit d'une simple surcharge de la classe Mage_Core_Model_Email_Template.

app/code/local/Magentix/ImageAttachments/etc/config.xml

<?xml version="1.0"?>
<config>
     <modules>
          <Magentix_ImageAttachments>
               <version>0.1.0</version>
          </Magentix_ImageAttachments>
     </modules>
     <global>
          <models>
               <core>
                    <rewrite>
                         <email_template>Magentix_ImageAttachments_Model_Email_Template</email_template>
                    </rewrite>
               </core>
          </models>
     </global>
</config>

Nous déclarons ensuite le module à Magento :

app/etc/modules/Magentix_ImageAttachments.xml

<?xml version="1.0"?>
<config>
     <modules>
          <Magentix_ImageAttachments>
               <active>true</active>
               <codePool>local</codePool>
          </Magentix_ImageAttachments>
     </modules>
</config>

Nous attaquons maintenant la méthode chargée d'inclure les images au mail. Zend_Mail nous fournit toutes les fonctionnalités dont nous avons besoin.

Il nous faudra également utiliser le bon type MIME (Multipurpose Internet Mail Extensions). Rappelons que MIME est un standard permettant d'insérer des documents (images, sons, texte...) dans un courrier. Le type qui nous intéresse est multipart/related. Petite définition :

Le Multipart/Related content-type présente la représentation MIME d'objets combinés. L'objet est défini par un paramètre "type". Des paramètres additionnels sont fournis pour indiquer le départ d'une partie spécifique ou de la racine, et des informations auxiliaires qui pourraient être nécessaires, lors du ré-assemblage ou de la création de l'objet.

Notre message contiendra plusieurs parties, le corps du message de type text/html, et les images de type image/gif ou image/jpeg, encodées en base 64.

Ce qui donnera par exemple :

MIME multipart/related

Content-Type: multipart/related;
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline
MIME-Version: 1.0

--=_3b6520e6a8a2e3bf9ac3d27cde45300a
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

<html>
     <body>
          Bonjour !
          <img src="cid:deeb5488abd448fc8db7dcdb130e5e29" alt="Mon image" />
     </body>
</html>

--=_3b6520e6a8a2e3bf9ac3d27cde45300a
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-ID: <deeb5488abd448fc8db7dcdb130e5e29>
Content-Disposition: inline; filename="logo_email.gif"
Content-Location: http://www.mondomaine.com/skin/frontend/default/modern/images/logo_email.gif

R0lGODlhrQAxAOZDAAEBAe43KvFbUICAgEBAQL+/v/CUjhAQEO/v7+9mXJ+fn9/f38/PzyAgIPHDwGBgYFBQUDAw (etc...)

La méthode sera nommée setInlinePictureAttachments, avec le texte HTML du message passé en paramètre.

app/code/local/Magentix/ImageAttachments/Model/Email/Template.php

public function setInlinePictureAttachments($html) {

     /* 1. Le type MIME sera multipart/related */
     $this->getMail()->setType(Zend_Mime::MULTIPART_RELATED);

     /* 2. Chargement du contenu HTML afin d'y extraire les images */
     $dom = new DOMDocument();
     $dom->loadHTML($html);

     $images = $dom->getElementsByTagName('img');

     /* 3. On parcoure l'ensemble des images */
     for ($i = 0; $i < $images->length; $i++) {
          $img = $images->item($i);
          $url = $img->getAttribute('src');
     
          /* 4. On vérifie que l'image existe bien physiquement */
          $image_http = new Zend_Http_Client($url);
          $response = $image_http->request();
     
          if ($response->getStatus() == 200) {
               /* 5. On remplace l'URL de l'image par l'id (URL encodé en MD5) */
               $html = preg_replace('@'.$url.'@','cid:'.md5($url),$html);

               /* 6. Ouverture du fichier, définition des propriétés (encodage, disposition, location...) */
               $image_content = $response->getBody();

               $pathinfo = pathinfo($url);

               $mime_type = $response->getHeader('Content-Type');
               $mime = new Zend_Mime_Part($image_content);
               $mime->id          = md5($url); /* id de la partie (Content-ID), URL encodé en MD5 */
               $mime->location    = $url;
               $mime->type        = $mime_type;
               $mime->disposition = Zend_Mime::DISPOSITION_INLINE;
               $mime->encoding    = Zend_Mime::ENCODING_BASE64;
               $mime->filename    = $pathinfo['basename'];
     
               /* 7. On joint le fichier au mail */
               $this->getMail()->addAttachment($mime);
          }
     }

     return $html;
}

Le chemin de l'image (paramètre src) doit correspondre au Content-ID de la partie concernée, précédé de "cid:". J'ai choisi ici d'encoder simplement l'URL de l'image en MD5 (généralement recommandé) :

MIME multipart/related

<img src="cid:deeb5488abd448fc8db7dcdb130e5e29" alt="Mon image" />

Reste à surcharger une méthode de la classe Mage_Core_Model_Email_Template afin de faire appel à notre nouvelle méthode. La méthode getProcessedTemplate correspond à nos besoins. Elle se charge d'appliquer les variables au template (Ex : var customer.name) :

app/code/local/Magentix/ImageAttachments/Model/Email/Template.php

<?php
class Magentix_ImageAttachments_Model_Email_Template extends Mage_Core_Model_Email_Template {
        
     public function getProcessedTemplate(array $variables = array()) {

          /* ... */

          try{
               $processedResult = $processor->filter($this->getPreparedTemplateText());
          }
          catch ( Exception $e)   {
               $this->_cancelDesignConfig();
               throw $e;
          }
          $this->_cancelDesignConfig();
                
          // + Ajout des images au mail
          $processedResult = $this->setInlinePictureAttachments($processedResult);

          return $processedResult;
     }

     public function setInlinePictureAttachments($html) {
          /* ... */
     }
}

Attention, la méthode getProcessedTemplate a légèrement évolué entre les versions 1.3 et 1.4 de Magento. Le module a ici été développé sous une 1.4. Le mieux reste de copier/coller la méthode correspondant à sa version de Magento.

Le module est maintenant fonctionnel ! L'ensemble des e-mails envoyés contiendront désormais la totalité des images contenues dans le template.

Bien entendu le poids du message doit rester le plus léger possible... Il faut se limiter à 1 ou 2 images simplistes. N'envoyez pas d'e-mails de 50ko à vos clients...

commentaires

Commentez cet article : E-mails transactionnels : joindre les images aux messages