Note :
A compter la version 1.7.6 de Prestashop la gestion des emails a été changée et cet article n’est plus d’actualité.

Les emails dans Prestashop ne permettent aucune factorisation, chaque email comprends son code html complet, lorsque vous souhaitez modifier du contenu dans l’entête ou dans le pied de page d’un email il est nécessaire de réaliser la modification sur l’ensemble des emails du site.

Ce n’est pas très pratique et cela peut être source de perte de temps.
Nous allons voir dans cet article qu’il existe des solutions natives et rapides pour optimiser ce point.
Via des créations de modules comme souvent 🙂
Nous allons créer dans cet article un module hhmail dont vous retrouverez le code complet en fin d’article

Principe Technique et prérequis

Lors de l’envoi d’un email de nombreux événements sont exécutés dans la fonction Mail::send,  mais ceux qui nous intéressent sont les suivants :

  • actionEmailAddBeforeContent : exécuté avant la récupération du template de l’email
  • actionEmailAddAfterContent : exécuté après la récupération du template de l’email

Grâces à ces hooks nous pouvons donc injecter du contenu avant et après le contenu de l’email, il est donc aisé de gérer un header et un footer commun pour l’ensemble des emails 🙂

Pour éviter d’ajouter ces contenus sur des emails qui le contiennent déjà, il faudra restreindre la liste des templates sur lesquels ces contenus s’ajouteront, dans cette version je part du principe que seuls les emails surchargés dans le thème seront impactés.

Codes et exemples

Voici le code du module qui gère l’ensemble des principes énoncés ci-dessus, les commentaires sur les différentes fonctions expliquent le fonctionnement.

class Hhmail extends Module
{
 
    /** @var Liste des templates éligibles array | null */
    protected $_eligiblesTemplates;
 
    public function __construct()
    {
        $this->name = 'hhmail';
        $this->tab = 'others';
        $this->version = '0.1.0';
        $this->author = 'hhennes';
        $this->bootstrap = true;
        parent::__construct();
 
        $this->displayName = $this->l('Hh mail');
        $this->description = $this->l('Email Optimisation module');
       //A compter de la version 1.7.6 , la gestion des emails est changée et n'est plus compatible
        $this->ps_versions_compliancy = array('min' => '1.6.1.0', 'max' => '1.7.6.0');
    }
 
    /**
     * Installation du module
     * @return bool
     */
    public function install()
    {
        if (!parent::install()
            || !$this->registerHook([
                'actionEmailAddBeforeContent',
                'actionEmailAddAfterContent'
            ])
 
        ) {
            return false;
        }
 
        return true;
    }
 
 
    /**
     * Ajout de contenu AVANT le contenu du template email
     * @param array(
     *   'template' => $template,
     *   'template_html' => &$templateHtml,
     *   'template_txt' => &$templateTxt,
     *   'id_lang' => (int) $idLang,
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    public function hookActionEmailAddBeforeContent($params)
    {
        //Via ce paramètre il est possible de choisir les emails pour lequels appliquer ou non le comportement
        //Pour l'exemple la fonction récupère uniquement les emails suchargés dans le thème
        //Il est possible de faire une conf admin si nécessaire pour gérer les cas mais ici on est dans le cadre d'un poc ;)
        if (in_array($params['template'], $this->_getOverridablesTemplates())) {
            $params['template_html'] .= $this->_getHeaderContent();
        }
    }
 
 
    /**
     * Ajout de contenu APRES le contenu du template email
     * @param array(
     *   'template' => $template,
     *   'template_html' => &$templateHtml,
     *   'template_txt' => &$templateTxt,
     *   'id_lang' => (int) $idLang,
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    public function hookActionEmailAddAfterContent($params)
    {
        if (in_array($params['template'], $this->_getOverridablesTemplates())) {
            $params['template_html'] .= $this->_getFooterContent();
        }
    }
 
    /**
     * Récupération du contenu du header
     * @return string
     */
    protected function _getHeaderContent()
    {
        return $this->_getMailContent('header', $this->context->language->iso_code);
    }
 
    /**
     * Récupération du contenu du footer
     * @return string
     */
    protected function _getFooterContent()
    {
        return $this->_getMailContent('footer', $this->context->language->iso_code);
    }
 
    /**
     * Récupération du contenu des fichiers mails situés dans /mails/codeLangue/
     * @param $template
     * @param $iso_code
     * @return bool|false|string
     */
    protected function _getMailContent($template, $iso_code)
    {
        $templateFile = _PS_MODULE_DIR_ . $this->name . '/mails/' . $iso_code . '/' . $template . '.html';
        if (is_file($templateFile)) {
            return Tools::file_get_contents($templateFile);
        }
        return false;
    }
 
    /**
     * Récupération des emails éligibles pour être managés avec un header/footer
     * On part du principe que ce ne sont que ceux du thème
     * ( car les emails initiaux de Prestashop les comportent déjà )
     * @return array
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    protected function _getOverridablesTemplates()
    {
        if (null === $this->_eligiblesTemplates) {
 
            $templates = [];
            $defaultLang = (int)Configuration::get('PS_LANG_DEFAULT');
            $language = new Language($defaultLang);
            $mailDefaultDir = _PS_THEME_DIR_ . 'mails/' . $language->iso_code . '/';
 
            //Pas d'utilisation de lib symfony pour compatibilité avec PS < 1.7
            if (is_dir($mailDefaultDir)) {
                $handle = opendir($mailDefaultDir);
                while (false !== ($entry = readdir($handle))) {
                    if ($entry != "." && $entry != ".." 
                        && !is_dir($mailDefaultDir . '/' . $entry) //Exclusion des dossier
                        //On prends uniquement les fichiers avec extension html
                        && 'html' === strtolower(pathinfo($mailDefaultDir . '/' . $entry, PATHINFO_EXTENSION))
                    ) {
                        $templates[] = pathinfo($entry, PATHINFO_FILENAME);
                    }
                }
            }
            $this->_eligiblesTemplates = $templates;
        }
 
        return $this->_eligiblesTemplates;
    }
}

Voici le contenu d’un email dans lequel l’entête et le pied de page ont été supprimé ( email mot de passe oublié )

/

<!-- Le header est ajouté automatiquement via le module hhmail -->
		<span style="color: #555454; font-family: Open-sans, sans-serif; font-size: small;">
			<span class="title" style="font-weight: 500; font-size: 28px; text-transform: uppercase; line-height: 33px;">Bonjour {firstname} {lastname},</span>
		</span>
 

Vos nouvelles informations d’identification sur {shop_name}

Adresse e-mail : {email}
 
<br>
 
		<span style="color: #555454; font-family: Open-sans, sans-serif; font-size: small;">
 
				Vous pouvez accéder à tout moment au suivi de votre commande et télécharger votre facture dans <a style="color: #337ff1;" href="{history_url}">"Historique des commandes"</a> de la rubrique <a style="color: #337ff1;" href="{my_account_url}">"Mon compte"</a> sur notre site.			
		</span>
 
 
		<span style="color: #555454; font-family: Open-sans, sans-serif; font-size: small;">
 
				Si vous avez un compte invité, vous pouvez suivre votre commande dans la section <a style="color: #337ff1;" href="{guest_tracking_url}?id_order={order_name}">"Suivi invité"</a> de notre site.			
		</span>
 
 
<!-- Le footer est ajouté automatiquement via le module hhmail -->

Les contenus des parties header et footer ne présentent pas d’intérêt je ne les détaille pas ici mais vous pouvez les trouvez dans l’archive.

Voici le rendu final du mail avec le remplacement du header et du footer ( exactement le même que les autres emails. ), mais les contenus sont récupérés dynamiquement du module hhmail

Email avec header et footer dynamique

En revanche si vous avez des modifications à faire dans les styles, dans l’entête ou le footer de vos emails les modifications seront instantanées sur tous les emails utilisant les templates,  🙂

Vous pouvez télécharger le module ici : hhmail