Tutoriel : Comment bien envoyer vos e-mails en HTML/CSS avec NodeJS

Découvrez nodemailer, hogan.js, inline-css et caniemail.com !

Tutoriel : Comment bien envoyer vos e-mails en HTML/CSS avec NodeJS

Lorsque vous devez concevoir un site, une application ou une simple API web, il y a de grandes chances pour que vous deviez configurer un envoi d'e-mails transactionnels.

Les e-mails transactionnels sont, par opposition aux e-mails commerciaux, des e-mails contenant une information relative à une action d'un utilisateur sur votre site. Ex : e-mail d'inscription, de récupération de mot de passe, de notification,...

Un envoi d'e-mails est assez facile à configurer, mais la tâche se complique lorsque ces derniers se multiplient, qu'ils doivent être jolis et efficaces et que le code se doit d'être propre et maintenable.

Je vais donc vous montrer différents outils qui vous serviront à créer un module d'envoi d'e-mails personnalisés en quelques lignes de code !

Les outils

nodemailer

Cette bibliothèque est l'une des plus utilisées pour envoyer des e-mails transactionnels en Nodejs car elle est complète, reste simple d'accès et il existe de nombreux plugins pour se connecter facilement à différents services d'envoi d'e-mails.

Nous utiliseront deux méthodes de la bibliothèque : "createTransport(options)" pour créer la connexion au serveur SMTP, et "sendMail(data)" pour envoyer les e-mails en question.

Vous pourrez retrouver le code d'exemple dans la deuxième partie de ce tutoriel, mais vous pouvez aussi aller directement consulter la documentation :

https://www.npmjs.com/package/nodemailer

hogan.js

Comme la principale fonction des e-mails transactionnels est d'amener l'utilisateur à effectuer une action ou de lui transmettre une information sur son activité, ces e-mails doivent contenir des informations personnalisées.

"hogan.js" est un moteur de templating simple qui va nous permettre d'injecter des données dynamique dans un template HTML grâce à un système de moustaches (handlebars) du type {{data}}.

Cette bibliothèque va nous permettre de garder des templates clairs et est capable de compiler des données simples, comme de décomposer des objets ou itérer sur une liste d'objets.

Pour voir la documentation, le lien est juste ici :

https://twitter.github.io/hogan.js/

inline-css

Les clients mails ont pour but de supprimer un maximum de données inutiles dans les e-mails, à la fois pour éviter les failles de sécurité dûes aux ressources externes, mais aussi pour diminuer leurs besoin en stockage.

C'est pour celà que de nombreux clients suppriment les éléments <head></head> mais aussi parfois les balises <style></style> du contenu des e-mails, obligeant les développeurs à écrire le style de ces derniers directement en inline.

Mais afin de garder la lisibilité du code HTML, de séparer les données du style et surtout de garder un code maintenable, nous allons utiliser la bibliothèque "inline-css" qui va nous permettre de parser les balises <style> ainsi que les fichiers css externes afin de les injecter directement dans les attributs "style" des différents éléments.

Le lien vers la bibliothèque en question :

https://www.npmjs.com/package/inline-css

caniemail.com

Si designer un e-mail en html peut paraitre simple, cela se révèle en fait être une tâche bien plus compliquée qu'elle n'y parait. Car si l'on est habitué à devoir tester le rendu de nos pages sur une poignée de navigateurs web contrôlant 99% des parts de marché, les clients mail, eux, sont bien plus nombreux, et bien différents les uns des autres.

Pour preuve, le moteur de rendu d'Outlook 2019 sur Windows utilise encore celui de... Microsoft Word ! Ce qui donne des différences de rendu énorme entre les différents clients et des techniques qu'il faut connaitre afin d'optimiser l'affichage de ses e-mails.

Voilà un article (en anglais) qui décrit plutôt bien la situation d'Outlook si ça vous intéresse !

Mais alors comment savoir si telle propriété CSS ou tel élément HTML est pris en charge lors de la conception de vos e-mails ? Tout simplement grâce à un site intitulé caniemail.com et qui répertorie un maximum d'information sur les fonctionnalités supportées par les différents clients e-mails :

https://caniemail.com

Le code

Voici le code d'exemple intégrant toutes les bibliothèques présentées précédemment, incluant le chargement du template, l'injection du CSS, le binding des données et l'envoi de l'email !

index.js

Retrouvez ici toute la logique de ce module d'e-mail :

const nodemailer = require('nodemailer'),
    fs = require('fs'),
    hogan = require('hogan.js'),
    inlineCss = require('inline-css');

// Create and initialize the email transport object
const transporter = nodemailer.createTransport({
    "host": "smtp.example.com",
    "port": 587,
    "secure": false,
    "auth": {
        "user": "sender@example.com",
        "pass": "password"
    }
});

(async function(){
    try {
        
        //Load the template file
        const templateFile = fs.readFileSync("./template/template.html");
        //Load and inline the style
        const templateStyled = await inlineCss(templateFile.toString(), {url: "file://"+__dirname+"/template/"});
        //Inject the data in the template and compile the html
        const templateCompiled = hogan.compile(templateStyled);
        const templateRendered = templateCompiled.render({text: "HelloWorld"});

        const emailData = { 
            to: "receiver@example.com", 
            from: '"Example" sender@example.com', 
            subject: "My Beautiful Email", 
            html: templateRendered 
        };
	
    	//Send the email
        await transporter.sendMail(emailData);
        
    } catch(e){
        console.error(e);
    }      
})()

template/template.html

Ci-dessous se trouve un modèle minimaliste d'e-mail, compatible pour l'injection de données avec hogan.js grâce à sa directive {{text}} :

<html>
    <head>
    	<link rel="stylesheet" href="./template.css">
    </head>
    <body>
        <div class="page">
            <h1>My title</h1>
            <p>{{text}}</p>
        </div>
    </body>
</html>

template/template.css

Le fichier css contenant tout le style de vos e-mails doit se trouver à l'emplacement indiqué dans le fichier html, en voici un exemple :


h1 { /* ... */ }
p { /* ... */ }
div.page { /* ... */ }

Libre à vous de rajouter autant de style que vous le désirez, tout en vérifiant sur caniemail.com que vos e-mails s'afficheront correctement sur toutes les clients mails !

Attention néanmoins, vous ne pourrez pas utiliser de @media-query étant donné que ce style n'est pas compatible avec l'inline !

Voilà, vous êtes maintenant prêts à envoyer de magnifiques e-mails en NodeJS ! J'espère que cet article vous aura plu, et à bientôt sur le blog !


À propos de l'auteur

Hello, je suis Nicolas Brondin-Bernard, ingénieur web indépendant depuis 2015 passionné par le partage de d'expériences et de connaissances.

Aujourd'hui je suis aussi coach pour développeurs web juniors, tu peux me contacter sur nicolas@brondin.com, sur mon site ou devenir membre de ma newsletter pour ne jamais louper le meilleur article de la semaine et être tenu au courant de mes projets !


Photo par Mathyas Kurmann sur Unsplash