MJML - la bibliothèque open source pour créer facilement des emails responsives

📌 Introduction

Lorsqu'il s'agit de créer des emails, la compatibilité multiplateforme est souvent un véritable casse-tête. En effet, il est difficile de garantir que les emails s'afficheront correctement sur tous les clients de messagerie et sur tous les appareils. C'est là que MJML intervient.

MJML est une bibliothèque open source pour répondre aux personnes qui cherchent à créer des emails efficaces tout en réduisant le temps de développement. La bibliothèque est équipée de nombreuses fonctionnalités utiles, telles que des composants préconstruits pour les boutons, les tableaux, les listes, etc. MJML propose également une mise en page flexible et facilement personnalisable pour répondre aux besoins spécifiques de chaque projet.

💡 Pour l'hébergement des photos de vos mails, je vous conseille ImgBB. Il s'agit d'une plateforme en ligne gratuite qui permet d'héberger et de partager des images en toute simplicité. En l'utilisant, les utilisateurs peuvent visualiser les images rapidement, sans avoir besoin d'intégrer les images en pièces jointes. On ne peut utiliser le SVG ou le base64 sur toutes les plateformes.

🎯 Pourquoi MJML ?

Je l'utilise au quotidien pour faire des campagnes de mail responsive ou même de petits sites internet sur un seul fichier HTML. MJML résout les problèmes de compatibilité que l'on rencontre habituellement en générant automatiquement le HTML compatible avec tous les clients de messagerie.

Fonctionnalité Description
mj-section Conteneur principal de mise en page responsive
mj-column Colonne flexible adaptée à tous les écrans
mj-text Bloc de texte stylisé et compatible
mj-button Bouton cliquable rendu correctement sur tous les clients
mj-image Image responsive avec lien et alt text

📄 Exemple — Structure de base d'un email MJML

Voici un exemple minimal d'un email MJML complet avec un header, un corps de texte et un bouton d'appel à l'action :

<mjml>
  <mj-head>
    <mj-title>Mon Email Responsive</mj-title>
    <mj-attributes>
      <mj-all font-family="Roboto, Arial, sans-serif" />
      <mj-text font-size="15px" color="#444444" line-height="1.6" />
    </mj-attributes>
  </mj-head>

  <mj-body background-color="#f4f4f4">

    <!-- Header -->
    <mj-section background-color="#2c3e50" padding="20px">
      <mj-column>
        <mj-text color="#ffffff" font-size="24px" font-weight="bold" align="center">
          Mon Blog — Newsletter
        </mj-text>
      </mj-column>
    </mj-section>

    <!-- Corps -->
    <mj-section background-color="#ffffff" padding="30px 40px">
      <mj-column>
        <mj-text font-size="18px" font-weight="bold" color="#2c3e50">
          Bonjour 👋
        </mj-text>
        <mj-text>
          Voici le contenu principal de votre email. MJML génère automatiquement
          le HTML compatible avec Outlook, Gmail, Apple Mail et tous les autres clients.
        </mj-text>
        <mj-image src="https://i.ibb.co/votre-image.png" alt="Image descriptive" width="600px" />
        <mj-button background-color="#2980b9" color="#ffffff" href="https://blog.delacourt.ovh">
          Lire l'article complet
        </mj-button>
      </mj-column>
    </mj-section>

    <!-- Footer -->
    <mj-section background-color="#ecf0f1" padding="16px">
      <mj-column>
        <mj-text align="center" font-size="12px" color="#999999">
          © 2026 blog.delacourt.ovh — Vous recevez cet email car vous êtes abonné.
        </mj-text>
      </mj-column>
    </mj-section>

  </mj-body>
</mjml>

⚙️ Utilisation avec PowerShell — Compiler un fichier MJML

MJML s'installe via Node.js / npm. Une fois installé, il est possible de l'appeler directement depuis PowerShell pour compiler vos fichiers .mjml en HTML prêt à l'envoi :

# ── Prérequis : Node.js installé ─────────────────────────────────────────────
# Installer MJML globalement via npm
npm install -g mjml

# ── Compiler un fichier MJML en HTML ─────────────────────────────────────────
$inputFile  = "C:\Emails\newsletter.mjml"
$outputFile = "C:\Emails\newsletter.html"

mjml $inputFile -o $outputFile

Write-Output "Compilation terminée : $outputFile"

# ── Vérifier que le fichier HTML a bien été généré ────────────────────────────
if (Test-Path $outputFile) {
    Write-Output "✅ Fichier HTML généré avec succès."
    $size = (Get-Item $outputFile).Length / 1KB
    Write-Output "   Taille : $([math]::Round($size, 2)) Ko"
} else {
    Write-Warning "❌ La compilation a échoué. Vérifiez votre fichier MJML."
}

🔁 Compiler tous les fichiers MJML d'un dossier

# ── Compiler tous les fichiers .mjml d'un dossier ────────────────────────────
$sourceFolder = "C:\Emails\Sources"
$outputFolder = "C:\Emails\Output"

# Créer le dossier de sortie s'il n'existe pas
if (-not (Test-Path $outputFolder)) {
    New-Item -ItemType Directory -Path $outputFolder | Out-Null
}

# Boucle sur tous les fichiers .mjml
Get-ChildItem -Path $sourceFolder -Filter "*.mjml" | ForEach-Object {
    $inputFile  = $_.FullName
    $outputFile = Join-Path $outputFolder ($_.BaseName + ".html")

    Write-Output "Compilation : $($_.Name)"
    mjml $inputFile -o $outputFile

    if (Test-Path $outputFile) {
        Write-Output "  ✅ OK → $outputFile"
    } else {
        Write-Warning "  ❌ ERREUR → $($_.Name)"
    }
}

Write-Output ""
Write-Output "Compilation terminée pour tous les fichiers."

📧 Partie 4 — Envoyer un email avec un body MJML et des données PowerShell

Une fois le fichier MJML compilé en HTML, il est possible d'injecter dynamiquement des données PowerShell dans le template avant l'envoi. L'idée est simple : on utilise des marqueurs de substitution dans le fichier MJML (ex : {{NOM}}, {{TABLEAU}}), puis on les remplace via PowerShell avant d'envoyer l'email.

🏗️ Étape 1 — Créer le template MJML avec des marqueurs

Dans votre fichier rapport.mjml, placez des marqueurs aux endroits où les données seront injectées :

<mjml>
  <mj-head>
    <mj-title>Rapport automatique</mj-title>
    <mj-attributes>
      <mj-all font-family="Roboto, Arial, sans-serif" />
      <mj-text font-size="15px" color="#444444" line-height="1.6" />
    </mj-attributes>
  </mj-head>

  <mj-body background-color="#f4f4f4">

    <!-- Header -->
    <mj-section background-color="#2c3e50" padding="20px">
      <mj-column>
        <mj-text color="#ffffff" font-size="22px" font-weight="bold" align="center">
          📊 Rapport — {{DATE_RAPPORT}}
        </mj-text>
      </mj-column>
    </mj-section>

    <!-- Introduction personnalisée -->
    <mj-section background-color="#ffffff" padding="30px 40px">
      <mj-column>
        <mj-text font-size="18px" font-weight="bold" color="#2c3e50">
          Bonjour {{PRENOM_DESTINATAIRE}},
        </mj-text>
        <mj-text>
          {{TEXTE_INTRO}}
        </mj-text>
      </mj-column>
    </mj-section>

    <!-- Tableau de données -->
    <mj-section background-color="#ffffff" padding="0 40px 30px 40px">
      <mj-column>
        <mj-text font-size="16px" font-weight="bold" color="#2c3e50">
          📋 Détail des éléments :
        </mj-text>
        <mj-text>
          {{TABLEAU_HTML}}
        </mj-text>
      </mj-column>
    </mj-section>

    <!-- Résumé chiffré -->
    <mj-section background-color="#eaf4fb" padding="20px 40px">
      <mj-column>
        <mj-text align="center" font-size="14px" color="#2980b9">
          Total traité : <strong>{{TOTAL_ELEMENTS}}</strong> éléments
          &nbsp;|&nbsp;
          Erreurs : <strong>{{TOTAL_ERREURS}}</strong>
        </mj-text>
      </mj-column>
    </mj-section>

    <!-- Bouton -->
    <mj-section background-color="#ffffff" padding="20px 40px">
      <mj-column>
        <mj-button background-color="#2980b9" color="#ffffff" href="{{LIEN_RAPPORT}}">
          Consulter le rapport complet
        </mj-button>
      </mj-column>
    </mj-section>

    <!-- Footer -->
    <mj-section background-color="#ecf0f1" padding="16px">
      <mj-column>
        <mj-text align="center" font-size="12px" color="#999999">
          Rapport généré automatiquement par PowerShell — {{DATE_RAPPORT}}
        </mj-text>
      </mj-column>
    </mj-section>

  </mj-body>
</mjml>

⚙️ Étape 2 — Script PowerShell : compiler, injecter et envoyer

Le script suivant effectue les opérations dans l'ordre :

  1. Compile le fichier .mjml en HTML via mjml
  2. Charge le HTML compilé
  3. Génère un tableau HTML à partir de données PowerShell
  4. Injecte toutes les données dans le template via -replace
  5. Envoie l'email via Send-MailMessage ou SMTP
#Requires -Version 5.1

# =============================================================================
# CONFIGURATION
# =============================================================================

$mjmlFile   = "C:\Emails\rapport.mjml"
$htmlFile   = "C:\Emails\rapport.html"
$smtpServer = "smtp.votreserveur.com"
$smtpPort   = 587
$smtpFrom   = "rapport@votredomaine.com"
$smtpTo     = "destinataire@exemple.com"
$smtpUser   = "rapport@votredomaine.com"
$smtpPass   = ConvertTo-SecureString "VotreMotDePasse" -AsPlainText -Force

# =============================================================================
# ÉTAPE 1 — Compiler le fichier MJML en HTML
# =============================================================================

Write-Output "Compilation MJML en cours..."
mjml $mjmlFile -o $htmlFile

if (-not (Test-Path $htmlFile)) {
    Write-Error "La compilation MJML a échoué. Vérifiez le fichier source."
    exit 1
}
Write-Output "✅ Compilation réussie : $htmlFile"

# =============================================================================
# ÉTAPE 2 — Charger le HTML compilé
# =============================================================================

$htmlBody = Get-Content -Path $htmlFile -Raw -Encoding UTF8

# =============================================================================
# ÉTAPE 3 — Préparer les données dynamiques
# =============================================================================

# ── Données textuelles ────────────────────────────────────────────────────────
$dateRapport   = Get-Date -Format "dd/MM/yyyy à HH:mm"
$prenom        = "Jean"
$texteIntro    = "Veuillez trouver ci-dessous le rapport automatique généré ce jour. " +
                 "Ce rapport récapitule l'ensemble des opérations traitées par le système."
$lienRapport   = "https://blog.delacourt.ovh"

# ── Données tabulaires (exemple : liste de machines/statuts) ──────────────────
$donnees = @(
    [PSCustomObject]@{ Machine = "SRV-DC01";    Statut = "✅ OK";      Derniere_Sync = "06/03/2026 08:00" },
    [PSCustomObject]@{ Machine = "SRV-FILE02";  Statut = "✅ OK";      Derniere_Sync = "06/03/2026 08:05" },
    [PSCustomObject]@{ Machine = "SRV-PRINT03"; Statut = "⚠️ Warning"; Derniere_Sync = "05/03/2026 22:00" },
    [PSCustomObject]@{ Machine = "SRV-APP04";   Statut = "❌ Erreur";  Derniere_Sync = "04/03/2026 14:30" },
    [PSCustomObject]@{ Machine = "SRV-DB05";    Statut = "✅ OK";      Derniere_Sync = "06/03/2026 07:55" }
)

$totalElements = $donnees.Count
$totalErreurs  = ($donnees | Where-Object { $_.Statut -like "*Erreur*" }).Count

# =============================================================================
# ÉTAPE 4 — Générer le tableau HTML depuis les données PowerShell
# =============================================================================

function New-HtmlTable {
    param (
        [Parameter(Mandatory)]
        [object[]]$Data
    )

    $style = @"

"@

    # En-têtes à partir des propriétés du premier objet
    $headers = $Data[0].PSObject.Properties.Name
    $headerRow = ($headers | ForEach-Object {
        "$($_ -replace '_', ' ')"
    }) -join ""

    # Lignes de données
    $rows = $Data | ForEach-Object {
        $row = $_
        $cells = ($headers | ForEach-Object {
            "$($row.$_)"
        }) -join ""
        "$cells"
    }

    return "$style$headerRow$($rows -join '')
" } $tableauHtml = New-HtmlTable -Data $donnees # ============================================================================= # ÉTAPE 5 — Injecter les données dans le template HTML # ============================================================================= $htmlBody = $htmlBody ` -replace '\{\{DATE_RAPPORT\}\}', $dateRapport ` -replace '\{\{PRENOM_DESTINATAIRE\}\}', $prenom ` -replace '\{\{TEXTE_INTRO\}\}', $texteIntro ` -replace '\{\{TABLEAU_HTML\}\}', $tableauHtml ` -replace '\{\{TOTAL_ELEMENTS\}\}', $totalElements ` -replace '\{\{TOTAL_ERREURS\}\}', $totalErreurs ` -replace '\{\{LIEN_RAPPORT\}\}', $lienRapport Write-Output "✅ Injection des données terminée." # ============================================================================= # ÉTAPE 6 — Envoyer l'email via SMTP # ============================================================================= $credential = New-Object System.Management.Automation.PSCredential($smtpUser, $smtpPass) $mailParams = @{ SmtpServer = $smtpServer Port = $smtpPort UseSsl = $true Credential = $credential From = $smtpFrom To = $smtpTo Subject = "Rapport automatique — $dateRapport" Body = $htmlBody BodyAsHtml = $true Encoding = [System.Text.Encoding]::UTF8 } try { Send-MailMessage @mailParams Write-Output "✅ Email envoyé avec succès à $smtpTo" } catch { Write-Error "❌ Erreur lors de l'envoi : $_" }

🔄 Principe de fonctionnement

Marqueur dans le MJML Valeur injectée par PowerShell Type
{{DATE_RAPPORT}} Date/heure d'exécution du script Texte
{{PRENOM_DESTINATAIRE}} Prénom issu d'Active Directory ou d'un CSV Texte
{{TEXTE_INTRO}} Paragraphe généré dynamiquement Texte
{{TABLEAU_HTML}} Tableau HTML généré depuis un PSCustomObject[] HTML
{{TOTAL_ELEMENTS}} Comptage automatique des lignes Nombre
{{TOTAL_ERREURS}} Filtrage des lignes en erreur Nombre
{{LIEN_RAPPORT}} URL vers le rapport complet ou SharePoint URL
💡 Astuce : Pour envoyer le même email à plusieurs destinataires avec des données personnalisées, il suffit de boucler sur une liste (CSV, Active Directory, SQL...) et de relancer les étapes 3 à 6 pour chaque destinataire en modifiant les marqueurs à chaque itération.
⚠️ Sécurité : Ne stockez jamais votre mot de passe SMTP en clair dans le script. Préférez Get-Credential en interactif, ou stockez le mot de passe chiffré via Export-Clixml / Import-Clixml pour les exécutions automatisées.

🔗 Liens utiles

✅ Conclusion

MJML est un outil incontournable pour quiconque souhaite créer des emails responsives sans se perdre dans les subtilités de compatibilité entre clients de messagerie. Associé à PowerShell pour l'automatisation de la compilation, il devient un véritable atout dans un pipeline de communication.

Que ce soit pour des campagnes marketing, des notifications automatisées ou même de petits sites HTML monofichier, MJML simplifie considérablement le travail tout en garantissant un rendu professionnel sur tous les appareils.


💬 Vous utilisez MJML dans vos projets ? Partagez vos retours d'expérience en commentaires !

Commentaires

Posts les plus consultés de ce blog

MDT - Guide de résolution des problèmes courants de configuration lors du déploiement d'un système d'exploitation Microsoft

PowerShell - Active Directory - Désactiver automatiquement les comptes expirés

Workspace One - Utilisation de réseaux Wi-Fi WPA3 avec Workspace ONE UEM