Dev Life
Créer des flux de travail d’emails transactionnels pour les notifications d’expédition avec l’API de Mailgun
Lorsque vous commandez un article en ligne, vous vous attendez à savoir exactement où il se trouve et quand il arrivera. Les flux de travail d’emails transactionnels rendent possible ce type de communication en temps opportun.
Contrairement aux emails de marketing qui font la promotion de produits, les emails transactionnels sont envoyés en réponse à l’action d’un utilisateur, comme le fait de passer une commande ou de recevoir une mise à jour d’expédition. Ils fournissent des détails en temps réel qui tiennent les utilisateurs informés à chaque étape.
Dans cet article, vous apprendrez à créer un flux de travail d’emails transactionnels pour les notifications d’expédition à l’aide de l’API de Mailgun. Le flux de travail intégrera BullMQ, un puissant système de file d’attente de tâches, pour mettre en file d’attente et traiter les notifications par email séparément de la logique principale de l’application, et améliorer la scalabilité et les performances. Cela est utile pour les applications à fort trafic où l’envoi d’emails directement dans un cycle de requête-réponse pourrait ralentir le système.
Mettre en œuvre des flux de travail d’emails transactionnels pour les notifications d’expédition avec l’API de Mailgun
Pour suivre ce guide, vous avez besoin de ces outils et comptes :
- Un compte Mailgun
- Node.js et Docker installé sur votre machine locale
- Un éditeur de code (ce tutoriel utilise VS Code) et un navigateur web
Avant de nous plonger dans la mise en œuvre, examinons le flux de travail :

Voici comment fonctionne le processus :
- L’équipe d’expédition (ou toute personne gérant les mises à jour d’expédition) envoie une requête HTTP pour mettre à jour le statut de la commande
- Le serveur Express met à jour le statut de la commande dans la base de données SQLite et met une tâche en file d’attente dans BullMQ
- Un worker BullMQ traite les tâches de la file d’attente et interagit avec l’API de Mailgun pour envoyer un email au client
- Le worker relance automatiquement les tâches échouées
- Mailgun livre l’email au client
Configuration du compte Mailgun
Pour utiliser l’API de Mailgun, vous avez besoin d’un domaine Mailgun et d’une clé API pour l’authentification. Mailgun fournit deux types de domaines : des domaines sandbox pour les tests et des domaines personnalisés pour une utilisation dans les environnements de production.
Dans ce guide, vous utiliserez un domaine sandbox. Chaque compte Mailgun en est automatiquement pourvu, vous n’avez donc pas besoin de le créer manuellement. Pour obtenir votre domaine sandbox, connectez-vous à votre compte Mailgun, puis accédez à Envoi > Envois > Domaines dans la barre latérale. Copiez votre domaine :

Par défaut, un domaine sandbox ne peut envoyer des emails qu’à destinataires autorisés. Pour configurer un email comme destinataire autorisé, cliquez sur votre nom de domaine sur la page Domaines pour afficher ses paramètres. Dans l’onglet Configuration, sous Ajouter des destinataires autorisés, ajoutez l’adresse email à laquelle vous souhaitez envoyer des emails. Veillez à suivre les instructions envoyées à l’adresse email que vous avez fournie pour la configurer en tant que destinataire autorisé :

Pour obtenir votre clé API, accédez à la page Clés API et cliquez sur Ajouter une nouvelle clé pour créer une nouvelle clé API. Donnez un nom à la clé et cliquez sur Créer la clé, puis veillez à copier la valeur de votre clé, car elle ne s’affichera qu’une seule fois :

Configuration du modèle de départ
Pour que ce tutoriel reste centré sur la création de flux de travail d’emails transactionnels, nous avons préparé un modèle de départ sur lequel vous pouvez vous appuyer. Clonez le modèle sur votre machine locale en exécutant la commande suivante dans votre terminal :
git clone --single-branch -b starter-template https://github.com/kimanikevin254/mailgun-transactional-email-workflows.git
Voici les fichiers clés du projet :
src/controllers/order.controller.ts contientdeux méthodes :indexeffectue le rendu de l’interface d’administration, définie danssrc/views/admin.ejsupdateOrderStatusmet à jour le statut de la commande dans la base de données
src/database/entity/order.entity.tsdéfinit l’entité de la commandesrc/database/entity/user.entity.tsdéfinit l’entité de l’utilisateursrc/database/seed.tsremplit la base de données avec un utilisateur et une commande de testdocker-compose.yml exécuteRedis dans Docker, ce qui est requis par BullMQ
Installez toutes les dépendances à l’aide de la commande suivante :
npm install
Ensuite, renommez le fichier .env.example en .env et remplacez les éléments de substitution pour MAILGUN_DOMAIN et MAILGUN_API_KEY par les identifiants que vous avez obtenus depuis le tableau de bord de Mailgun. Pour la variable MAIL_FROM, indiquez votre adresse email comme valeur.
Ensuite, ouvrez le fichier src/database/seed.ts et remplacez les informations de l’élément de substitution dans la constante userInfo par vos propres informations. Pour l’email, veillez à en fournir un que vous avez ajouté en tant que destinataire autorisé.
Enfin, remplissez la base de données en exécutant la commande npm run db:seed dans votre terminal. Vous pouvez maintenant exécuter le projet à l’aide de la commande npm run dev et accéder à http://localhost:3000 dans votre navigateur pour afficher et mettre à jour le statut de la commande :

Dans la section suivante, vous implémenterez un flux de travail qui envoie automatiquement un email à l’utilisateur une fois le statut de la commande mis à jour.
Conception des modèles d’emails
Des modèles d’emails bien conçus améliorent la lisibilité et l’expérience utilisateur, tout en garantissant une apparence professionnelle sur tous les appareils. Dans cette section, vous allez créer des modèles qui rendent vos emails transactionnels clairs, engageants et efficaces.
Une commande passe par trois états (expédiée, en cours de livraison et livrée), tels que définis dans le type OrderStatus du fichier src/types/index.ts. Vous allez créer un modèle d’email correspondant à chaque état pour tenir les clients informés à chaque étape.
Pour ce faire, créez un fichier dans src/email-templates/html/shipped.html et ajoutez le code suivant :
<!DOCTYPE html>rn<html>rn<head>rn <meta charset="UTF-8" />rn <title>Order Shipped</title>rn</head>rn<body style="font-family: Arial, sans-serif; background-color: #f4f4f4; padding: 20px; text-align: center;">rnrn <div style="background: #ffffff; padding: 20px; border-radius: 8px; max-width: 600px; margin: auto; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);">rnrn <div style="background-color: #007bff; color: white; padding: 15px; font-size: 22px; font-weight: bold; border-top-left-radius: 8px; border-top-right-radius: 8px;">rn Your Order Has Been Shipped! ✈️rn </div>rnrn <div style="padding: 20px; font-size: 16px; color: #333; text-align: left;">rn <p style="margin: 0 0 10px;">Hello, <%= name %></p>rn <p style="margin: 0 0 10px;">Your order has been shipped and is on its way to you. 📦</p>rn <p style="margin: 0 0 10px;"><strong>Tracking Number:</strong> <%= trackingNumber %></p>rn <p style="margin: 0 0 10px;">You can track your package below. We hope you enjoy your purchase!</p>rnrn <a href="https://yourwebsite.com/track?trackingNumber=<%= trackingNumber %>"rn style="background-color: #007bff; color: white; text-decoration: none; padding: 12px 18px; border-radius: 5px; display: inline-block; margin-top: 15px; font-weight: bold;">rn Track Your Shipmentrn </a>rn </div>rnrn <div style="background-color: #f4f4f4; padding: 10px; font-size: 14px; color: #555; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px;">rn Thank you for shopping with us! 🛒rn </div>rn </div>rn</body>rn</html>rn
Ce modèle d’email permet d’informer les clients que leur commande a été expédiée. Il inclut des éléments de substitution pour le nom et le numéro de suivi du client, qui seront remplis dynamiquement par EJS lors du rendu du modèle. Les modèles pour les deux autres statuts de commande suivront le même format.
Créez un modèle pour notifier les utilisateurs que leur commande est en cours de livraison. Pour ce faire, créez un fichier nommé out_for_delivery.html dans le dossier src/email-templates/html et ajoutez le code suivant :
<!DOCTYPE html>rn<html>rn<head>rn <meta charset="UTF-8" />rn <title>Out for Delivery</title>rn</head>rn<body style="font-family: Arial, sans-serif; background-color: #f4f4f4; padding: 20px; text-align: center;">rnrn <div style="background: #ffffff; padding: 20px; border-radius: 8px; max-width: 600px; margin: auto; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);">rnrn <div style="background-color: #28a745; color: white; padding: 15px; font-size: 22px; font-weight: bold; border-top-left-radius: 8px; border-top-right-radius: 8px;">rn Your Order Is Out for Delivery! 🚚rn </div>rnrn <div style="padding: 20px; font-size: 16px; color: #333; text-align: left;">rn <p style="margin: 0 0 10px;">Hello, <%= name %></p>rn <p style="margin: 0 0 10px;">Good news! Your package is out for delivery and will arrive soon. 📦</p>rn <p style="margin: 0 0 10px;"><strong>Tracking Number:</strong> <%= trackingNumber %></p>rn <p style="margin: 0 0 10px;">We appreciate your business and can't wait for you to receive your order!</p>rnrn <a href="https://yourwebsite.com/track?trackingNumber=<%= trackingNumber %>"rn style="background-color: #28a745; color: white; text-decoration: none; padding: 12px 18px; border-radius: 5px; display: inline-block; margin-top: 15px; font-weight: bold;">rn Track Your Packagern </a>rn </div>rnrn <div style="background-color: #f4f4f4; padding: 10px; font-size: 14px; color: #555; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px;">rn Thank you for choosing us! 🛍️rn </div>rn </div>rn</body>rn</html>
Enfin, créez un modèle pour informer les utilisateurs que leur commande a été livrée, en créant un fichier nommé delivered.html dans le dossier src/email-templates/html et en ajoutant le code suivant :
<!DOCTYPE html>rn<html>rn<head>rn <meta charset="UTF-8" />rn <title>Order Delivered</title>rn</head>rn<body style="font-family: Arial, sans-serif; background-color: #f4f4f4; padding: 20px; text-align: center;">rnrn <div style="background: #ffffff; padding: 20px; border-radius: 8px; max-width: 600px; margin: auto; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);">rnrn <div style="background-color: #ffc107; color: white; padding: 15px; font-size: 22px; font-weight: bold; border-top-left-radius: 8px; border-top-right-radius: 8px;">rn Your Order Has Been Delivered! 🎉rn </div>rnrn <div style="padding: 20px; font-size: 16px; color: #333; text-align: left;">rn <p style="margin: 0 0 10px;">Hello, <%= name %></p>rn <p style="margin: 0 0 10px;">We're happy to inform you that your package has been successfully delivered. 🎁</p>rn <p style="margin: 0 0 10px;"><strong>Tracking Number:</strong> <%= trackingNumber %></p>rn <p style="margin: 0 0 10px;">We hope you enjoy your purchase! If you have any questions, feel free to contact us.</p>rnrn <a href="https://yourwebsite.com/track?trackingNumber=<%= trackingNumber %>"rn style="background-color: #ffc107; color: white; text-decoration: none; padding: 12px 18px; border-radius: 5px; display: inline-block; margin-top: 15px; font-weight: bold;">rn Track Your Orderrn </a>rn </div>rnrn <div style="background-color: #f4f4f4; padding: 10px; font-size: 14px; color: #555; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px;">rn Thank you for shopping with us! 🛍️rn </div>rn </div>rn</body>rn</html>
Pour gérer et générer des modèles d’emails de manière dynamique, vous devez créer une classe qui charge et organise les modèles pour les différents statuts de commande. Cette classe récupérera le modèle approprié et en effectuera le rendu avec les données spécifiques au client. Pour ce faire, créez un nouveau fichier nommé index.ts dans le dossier src/email-templates et ajoutez le code suivant :
import { readFileSync } from "fs";rnimport { EmailTemplate, OrderStatus } from "../types";rnimport ejs from "ejs";rnrnexport class EmailTemplateManager {rn private templates: Map<OrderStatus, EmailTemplate>;rnrn constructor() {rn this.templates = new Map();rn this.loadTemplates();rn }rnrn private loadTemplates() {rn // Load each template for different statusesrn const statuses: OrderStatus[] = [rn "shipped",rn "out_for_delivery",rn "delivered",rn ];rn const subjects: Record<OrderStatus, string> = {rn shipped: "Your Order Has Been Shipped! ✈️",rn out_for_delivery: "Your Order is Out for Delivery! 🚚",rn delivered: "Your Order Has Been Delivered! 🎉",rn };rnrn statuses.forEach((status) => {rn const htmlTemplate = readFileSync(rn `src/email-templates/html/${status}.html`,rn "utf-8"rn );rnrn this.templates.set(status, {rn subject: subjects[status],rn html: htmlTemplate,rn });rn });rn }rnrn getTemplate(status: OrderStatus): EmailTemplate {rn const template = this.templates.get(status);rn if (!template) {rn throw new Error(`No template found for status: ${status}`);rn }rn return template;rn }rnrn renderTemplate(templateString: string, data: Record<string, any>): string {rn return ejs.render(templateString, data); // Render the template with the provided datarn }rn}
Cette classe initialise une variable privée nommée templates, qui stocke les modèles d’emails dans une structure Map pour une recherche rapide en fonction du statut de la commande. L’utilisation d’une structure Map garantit une récupération efficace et évite de lire les fichiers de manière répétée à partir du disque. La classe définit également les méthodes suivantes :
loadTemplates(privée) lit les modèles HTML à partir de fichiers et les stocke dans la structure Map templates, avec leurs objets d’email correspondants.getTemplaterécupère le modèle d’email pour un statut de commande donné et renvoie une erreur si aucun modèle n’est trouvé.renderTemplateutilise EJS pour effectuer un rendu dynamique d’un modèle avec les données fournies.
Implémentation de la fonctionnalité d’envoi d’emails
Une fois les modèles d’emails configurés, l’étape suivante consiste à implémenter la fonctionnalité d’envoi des notifications. Cela implique de mettre les tâches d’email en file d’attente et de les traiter de manière asynchrone.
Mais avant de pouvoir le faire, vous devez installer quelques dépendances en exécutant la commande suivante :
npm i mailgun.js@11.1.0 form-data@4.0.2 bullmq@5.41.2 ioredis@5.5.0
Voici un aperçu de chacune de ces dépendances :
mailgun.jsest un client Node.js permettant d’interagir avec l’API de Mailgun. Vous l’utiliserez pour envoyer des emails transactionnels.form-dataest un package requis parmailgun.jspour gérer les envois de formulaires lors de l’envoi d’emails.bullmqest une bibliothèque de file d’attente de tâches permettant de gérer les tâches asynchrones. Elle vous permet de mettre les notifications par email en file d’attente et de les traiter en arrière-plan.ioredisest un client Redis pour Node.js utilisé par BullMQ pour stocker et gérer les tâches mises en file d’attente.
Ensuite, vous devez définir un client de l’API de Mailgun que vous utiliserez pour envoyer des emails. Pour ce faire, créez un nouveau fichier dans src/config/mailgun.config.ts et ajoutez le code suivant :
import FormData from "form-data";rnimport Mailgun from "mailgun.js";rnrnconst mailgun = new Mailgun(FormData);rnexport const mgClient = mailgun.client({rn username: "api",rn key: process.env.MAILGUN_API_KEY,rn});
Ce code configure et exporte un client Mailgun à l’aide de la bibliothèque mailgun.js et de form-data, ce qui permet à votre application d’envoyer des emails via l’API de Mailgun avec la clé API stockée dans les variables d’environnement.
Vous devez maintenant définir une connexion Redis qui sera utilisée par BullMQ pour stocker et gérer les tâches en arrière-plan. Pour ce faire, créez un nouveau fichier nommé redis.config.ts dans le dossier src/config et ajoutez le code ci-dessous :
import IORedis from "ioredis";rnrnexport const redisConfig = new IORedis({rn host: process.env.REDIS_HOST,rn port: parseInt(process.env.REDIS_PORT),rn maxRetriesPerRequest: null,rn});
Vous devez configurer une file d’attente BullMQ pour les notifications d’expédition, qui gérera les tâches de notification par email en arrière-plan en utilisant la connexion Redis définie à l’étape précédente. Pour ce faire, créez un nouveau fichier nommé queues.config.ts dans le dossier src/config et ajoutez le code suivant :
import { Queue } from "bullmq";rnimport { redisConfig } from "./redis.config";rnrnexport const QUEUE_NAMES = {rn SHIPPING_NOTICATIONS: "shipping-notifications",rn};rnrnexport const JOB_NAMES = {rn SEND_NOTIFICATION: "send-notification",rn};rnrnexport const SHIPPING_NOTICATIONS_QUEUE = new Queue(rn QUEUE_NAMES.SHIPPING_NOTICATIONS,rn {rn connection: redisConfig,rn }rn);
Ce code définit également des noms pour la file d’attente et le type de tâche, qui peuvent être utilisés dans d’autres parties de l’application pour éviter les chaînes de caractères codées en dur.
Enfin, créez un nouveau fichier dans src/services/notifications.service.ts et ajoutez le code suivant :
import { Job, Queue, Worker } from "bullmq";rnimport {rn QUEUE_NAMES,rn SHIPPING_NOTICATIONS_QUEUE,rn JOB_NAMES,rn} from "../config/queues.config";rnimport { redisConfig } from "../config/redis.config";rnimport { mgClient } from "../config/mailgun.config";rnimport { IMailgunClient } from "mailgun.js/Interfaces";rnimport { EmailTemplateManager } from "../email-templates";rnimport { MailgunMessageData } from "mailgun.js";rnimport { NotificationJob } from "../types";rnrnexport class NotificationService {rn private queue: Queue;rn private mailgunClient: IMailgunClient;rn private templateManager: EmailTemplateManager;rnrn constructor() {rn this.queue = SHIPPING_NOTICATIONS_QUEUE;rn this.mailgunClient = mgClient;rn this.templateManager = new EmailTemplateManager();rn this.setupWorker();rn }rnrn private setupWorker() {rn const worker = new Worker(rn QUEUE_NAMES.SHIPPING_NOTICATIONS,rn async (job) => {rn console.log(`Processing job: ${job.id}`);rn await this.processNotification(job);rn },rn {rn connection: redisConfig,rn }rn );rnrn worker.on("completed", (job) => {rn console.log(`Job ${job.id} completed successfully`);rn });rnrn worker.on("failed", (job, error) => {rn console.log(`Job ${job?.id} failed`, error);rn });rn }rnrn private async processNotification(job: Job<NotificationJob>) {rn const { email, trackingNumber, status, metadata } = job.data;rnrn try {rn const template = this.templateManager.getTemplate(status);rn const emailData: MailgunMessageData = {rn from: process.env.MAIL_FROM,rn to: email,rn subject: template.subject,rn html: this.templateManager.renderTemplate(template.html, {rn trackingNumber,rn ...metadata,rn }),rn };rnrn await this.mailgunClient.messages.create(rn process.env.MAILGUN_DOMAIN,rn emailDatarn );rn } catch (error) {rn console.log(error);rn throw error;rn }rn }rnrn async queueNotification(data: NotificationJob) {rn await this.queue.add(JOB_NAMES.SEND_NOTIFICATION, data, {rn attempts: 5, // number of retry attempts before failing permanentlyrn backoff: {rn type: "exponential", // Retry using exponential backoffrn delay: 5000, // Delay in ms before retryingrn },rn });rn console.log("Job queued successfully");rn }rn}
Ce code définit une classe NotificationService qui gère les notifications par email en utilisant un système de file d’attente de tâches avec BullMQ et Mailgun. Cette classe initialise trois propriétés privées : queue, qui est la file d’attente où les tâches d’email sont ajoutées ; mailgunClient, qui est le client Mailgun pour l’envoi d’emails ; et templateManager, qui est une instance de la classe TemplateManager que vous avez créée précédemment pour gérer et récupérer les modèles d’emails. Cette classe définit également les méthodes suivantes :
setupWorkercrée un worker qui écoute les nouvelles tâches d’email et les traite. Il consigne la réussite ou l’échec de la tâche.processNotificationrécupère le modèle d’email approprié, le remplit avec des données dynamiques et envoie l’email via Mailgun.queueNotificationajoute une nouvelle tâche d’email à la file d’attente, avec des tentatives de relance et un délai d’attente exponentiel pour les tentatives échouées. Cette méthode peut être appelée depuis d’autres parties de l’application pour ajouter des tâches à la file d’attente.
Intégration avec les événements de l’application
Pour envoyer des notifications par email lorsqu’un statut de commande est mis à jour, vous devez mettre une tâche en file d’attente dans le système de notification. Pour ce faire, ouvrez le fichier src/controllers/order.controller.ts et ajoutez l’instruction d’importation suivante pour importer la classe NotificationService :
import { NotificationService } from "../services/notifications.service";
Ensuite, définissez une propriété privée dans la classe OrderController pour contenir une instance de la classe NotificationService :
private notificationService: NotificationService;
Initialisez cette propriété en ajoutant le code suivant dans la méthode constructor :
this.notificationService = new NotificationService();
Enfin, ajoutez le code suivant dans la méthode updateOrderStatus après await this.orderRepository.save(order); pour mettre une tâche en file d’attente une fois le statut de la commande mis à jour avec succès :
// Send notificationrnthis.notificationService.queueNotification({rn email: order.user.email,rn trackingNumber: order.trackingNumber,rn status,rn metadata: {rn name: order.user.name.split(" ")[0],rn },rn});
Le flux de travail de l’email transactionnel est maintenant terminé. Vous pouvez maintenant vérifier que tout fonctionne comme prévu.
Tester le flux de travail
Pour vous assurer que tout fonctionne correctement, démarrez Redis en exécutant la commande suivante dans votre terminal :
docker compose up -d
Après avoir exécuté cette commande, vous pouvez vérifier que Redis est opérationnel en listant les conteneurs :
docker ps
Cette commande affiche une liste de conteneurs actifs, et vous devriez voir le conteneur redis en cours d’exécution.
Ensuite, lancez le serveur Express à l’aide de la commande npm run dev et accédez à http://localhost:3000 dans votre navigateur. Sur le tableau de bord de l’application, mettez à jour le statut de la commande avec l’une des options disponibles. Une fois la mise à jour effectuée, vous recevrez une réponse immédiate :

Dans votre terminal, vous obtiendrez un journal vous indiquant que la tâche d’envoi d’email a bien été mise en file d’attente et est en cours de traitement :
Job queued successfully
Processing job: 1
Et lorsqu’elle est terminée :
Job 1 completed successfully
Vous recevrez ensuite un email contenant le statut actualisé de la commande :

Chaque fois que vous mettez à jour le statut d’une commande, le système enverra automatiquement un email correspondant à l’utilisateur, pour le tenir informé :

Le code complet de l’application est disponible sur GitHub.
Suivi et gestion des emails
Pour vous assurer que vos emails transactionnels parviennent bien à vos clients, vous devez surveiller leur état de livraison et leurs taux d’ouverture, et gérer les éventuels échecs. Mailgun propose un tableau de bord où vous pouvez suivre les emails envoyés, vérifier s’ils ont été livrés, ouverts ou cliqués, et consulter les rapports de rebond.
Vous pouvez accéder à ce tableau de bord en accédant à Envoi > Rapports > Statistiques dans Mailgun :

Cependant, les taux d’ouverture ne sont pas suivis automatiquement. Vous devez les configurer manuellement via l’onglet Paramètres de votre domaine d’envoi :

De plus amples informations sur le suivi des taux d’ouverture et de clics sont disponibles dans la documentation officielle.
De plus, vous pouvez utiliser webhooks pour recevoir des notifications en temps réel concernant les échecs de livraison et prendre les mesures appropriées, telles que renvoyer l’email.
En surveillant activement les performances de vos emails, vous pouvez améliorer la délivrabilité, réduire les rebonds et vous assurer que les notifications importantes parviennent à vos clients.
Conclusion
Dans cet article, vous avez appris à configurer un flux de travail d’emails transactionnels pour les notifications d’expédition à l’aide de Mailgun, BullMQ et Redis. Vous avez appris à configurer Mailgun pour l’envoi d’emails, à définir une file d’attente de tâches avec BullMQ, et à l’intégrer à un système de mise à jour des commandes afin de garantir que les clients reçoivent des notifications par email en temps réel. Cette approche améliore la communication et optimise l’expérience client globale.
Cet article vous a-t-il été utile ? N’oubliez pas de vous inscrire à notre newsletter pour recevoir d’autres tutoriels et analyses approfondies comme celle-ci.