Configurer un relais SMTP transactionnel pour Odoo 19, c'est cinq champs dans le backend — et trois enregistrements DNS bien posés en amont. Tout le reste, c'est de la maîtrise du pivot from_filter et de la chaîne d'alignement DKIM. Brevo (ex-Sendinblue) reste en 2026 l'option la plus simple côté RGPD pour une PME francophone : compte gratuit jusqu'à 300 emails/jour, infrastructure européenne, et un mécanisme de DKIM par CNAME qui permet à Brevo de rotater les clés de signature sans intervention manuelle.
Cet article décrit la chaîne complète, de la création de la clé SMTP côté Brevo jusqu'à l'inspection de la queue mail.mail en cas d'échec. Il s'inscrit dans la série Tech-Email après l'article HUB sur les 4 couches mail et avant l'article dédié à DKIM/SPF/DMARC — qui couvre le détail cryptographique des records DNS.
1. Pourquoi un SMTP transactionnel et pas Gmail
Pour des envois ponctuels, un compte Gmail ou un SMTP personnel peut suffire. Dès que le volume dépasse quelques centaines d'emails par jour, ou que la production tourne sur un serveur qui n'a pas un IP « propre », un relais transactionnel dédié devient nécessaire pour trois raisons : la délivrabilité (l'IP du relais est notée par les fournisseurs), la visibilité (logs, bounces, opens consultables), et la conformité 2026 (Google, Yahoo et Microsoft imposent SPF + DKIM + DMARC pour tout expéditeur >5 000 emails/jour depuis février 2024, étendu à tous depuis mai 2025).
Brevo se positionne sur la même catégorie que Mailjet et Amazon SES. Les trois sont des relais SMTP transactionnels. Brevo se distingue par :
- Free tier 300 emails/jour sans limite de durée — suffisant pour une PME en démarrage.
- Infrastructure EU (datacenter Paris) — RGPD natif sans déclaration.
- DKIM par CNAME avec rotation automatique des clés (sélecteurs
brevo1/brevo2). - Setup SMTP standard — pas d'IAM AWS, pas de domaine à vérifier hors interface Brevo.
Le tableau ci-dessous résume les positionnements vérifiés en janvier 2026 — utile pour situer ce que cet article configure, avant que la Série Tech-Email revienne en détail sur Mailjet et SES dans l'article suivant.
| Critère | Brevo | Mailjet | Amazon SES |
|---|---|---|---|
| Free tier | 300/jour (~9k/mois) | 200/jour (~6k/mois) | 3 000/mois (12 mois seulement) |
| Prix Starter | 9$/mois — 5k emails | 15$/mois — 15k emails | 0,10$ / 1 000 emails |
| Data EU par défaut | Oui (Paris) | Oui (EU) | Non — multi-régions explicites |
| Setup Odoo | Simple — SMTP standard | Simple — SMTP standard | Complexe — IAM + sandbox |
| DKIM rotation auto | Oui (CNAME natif) | Non natif | Manuel via Route 53 |
2. L'endpoint Brevo en 2026 — ce qui a changé
Le service a été renommé Brevo en mai 2023 (anciennement Sendinblue). En 2026, toute documentation qui mentionne smtp.sendinblue.com ou un port 25 doit être considérée obsolète. Les bons paramètres :
- SMTP host :
smtp-relay.brevo.com - Port 587 : STARTTLS — recommandé (standard moderne)
- Port 465 : SSL/TLS — accepté en alternative
- Port 2525 : fallback si 587 bloqué par l'hébergeur
- Authentification : login = email du compte Brevo, password = clé SMTP (pas la clé API REST)
smtp_pass d'ir.mail_server. Une clé API REST utilisée comme mot de passe SMTP retournera l'erreur 535 5.7.8 Authentication credentials invalid. L'ancien « master password » a été supprimé pour les nouveaux comptes depuis 2024.
La clé SMTP existe en deux formats : Standard (64 caractères) ou Short (15 caractères). Le format Standard est recommandé pour les usages serveur. Elle s'affiche une seule fois à la génération — la copier immédiatement dans un coffre-fort (Bitwarden, 1Password) ou dans la config Odoo.
3. Le diagramme du flux Brevo → Odoo → destinataire
4. DNS : valider son domaine côté Brevo
Avant toute configuration Odoo, le domaine d'envoi doit être validé dans l'interface Brevo. Sans cette étape, Brevo substitue @brevosend.com au From utilisateur depuis février 2024, cassant l'identité d'envoi de manière irréversible côté destinataire.
From: visible au destinataire (le « From » utilisateur) et le Return-Path / Envelope From (RFC 5321) utilisé pour les bounces et l'alignement SPF. Avec Brevo en IPs partagées, le Return-Path appartient à Brevo (@sender-sib.com), pas au domaine d'envoi — ce qui rend l'alignement SPF strict structurellement impossible et impose de passer par DKIM pour DMARC.
Le workflow côté Brevo : Senders & IP → Domains → Add a domain. Brevo affiche les enregistrements à ajouter dans la console DNS du domaine. Trois familles d'enregistrements :
1. Vérification de propriété (TXT). Brevo génère un code unique à coller en TXT sur le domaine racine. C'est l'enregistrement qui prouve qu'on contrôle le domaine.
2. DKIM par CNAME (recommandé). Deux CNAME délégués à Brevo, avec rotation automatique des clés côté serveur :
brevo1._domainkey.example.com CNAME brevo1._domainkey.brevo.com
brevo2._domainkey.example.com CNAME brevo2._domainkey.brevo.com
Avantage du CNAME sur le TXT historique (mail._domainkey) : Brevo fait tourner les clés sans demander d'intervention manuelle. Mise en garde Cloudflare : si l'option CNAME flattening est activée sur la zone, désactiver le flattening pour ces enregistrements spécifiques, sinon Cloudflare convertit le CNAME en TXT et DKIM échoue.
3. DMARC (TXT). Démarrer en p=none (monitoring seul), puis progresser vers quarantine après 2-4 semaines, puis reject en cible finale. Une politique p=none minimum est obligatoire pour tout domaine envoyant 5 000+ emails/jour depuis les exigences Google/Yahoo de février 2024.
_dmarc.example.com TXT v=DMARC1; p=none; rua=mailto:rua@dmarc.brevo.com; ruf=mailto:ruf@dmarc.brevo.com
Une fois les enregistrements ajoutés, attendre la propagation DNS (15 min à 48h selon TTL), puis revenir dans Brevo et cliquer Authenticate this email domain. Les checkmarks verts confirment la validation. Pour le détail cryptographique de chaque enregistrement (sélecteurs, signatures, alignement strict vs relâché), l'article DKIM/SPF/DMARC de la série creuse le sujet.
5. ir.mail_server : la configuration côté Odoo
Une fois le domaine validé côté Brevo et la clé SMTP générée, la création du serveur sortant Odoo prend cinq champs critiques. Chemin backend : Settings → Technical (mode debug activé) → Email → Outgoing Mail Servers → New.
| Champ Odoo | Valeur Brevo recommandée |
|---|---|
name | Brevo — example.com |
from_filter (« FROM Filtering ») | example.com (le domaine validé Brevo, exact) |
smtp_host | smtp-relay.brevo.com |
smtp_port | 587 |
smtp_encryption | starttls_strict (production) |
smtp_authentication | login |
smtp_user | email du compte Brevo |
smtp_pass | clé SMTP générée (Standard 64 chars) |
sequence | 10 (ou plus petit pour priorité haute) |
Le champ smtp_encryption en Odoo 19 accepte cinq valeurs : none, starttls, starttls_strict, ssl, ssl_strict. Le suffixe _strict active la validation du certificat serveur — recommandée en production. starttls_strict est le bon choix pour le port 587 Brevo en production.
Pour automatiser la création (utile en déploiement CI/CD ou via un module custom), un snippet Python utilisant le moteur ORM :
# Lancer le shell Odoo sur la base de production (mode debug actif)
$ ./odoo-bin shell -c config/odoo.conf -d ma_base_production
# À exécuter dans odoo-bin shell, ou depuis une migration de module custom.
# Pré-requis : avoir un compte Brevo avec domaine validé et clé SMTP générée.
server = env['ir.mail_server'].create({
'name': 'Brevo — example.com',
'from_filter': 'example.com', # CRITIQUE : domaine exact validé Brevo
'smtp_host': 'smtp-relay.brevo.com',
'smtp_port': 587,
'smtp_encryption': 'starttls_strict', # validation certificat en prod
'smtp_authentication': 'login',
'smtp_user': 'votrecompte@example.com',
'smtp_pass': '', # clé SMTP (pas API REST)
'sequence': 10,
})
# Test de connexion immédiate (équivalent du bouton "Test Connection" du backend)
try:
server.test_smtp_connection()
env.cr.commit()
print(f"Serveur Brevo configuré : id={server.id}")
except Exception as e:
# Sur erreur SMTP, Odoo lève une exception détaillée (auth, TLS, DNS…)
print(f"Échec de connexion : {e}")
raise
from_filter jamais vide ni *. Si plusieurs serveurs sortants coexistent dans Odoo (par exemple un serveur Brevo et un Gmail personnel), un from_filter vide ou catch-all (*) provoque le routage de tous les emails vers le premier serveur de la liste classé par sequence, indépendamment du domaine du From. Conséquence : un email From: alice@gmail.com envoyé via Brevo n'est pas signé DKIM par Brevo (le domaine ne match pas) et casse le DKIM Gmail (puisque ce n'est pas Gmail qui envoie).
6. _find_mail_server() : l'algorithme de sélection en 5 étapes
Quand Odoo a un email à envoyer, la méthode _find_mail_server() (couche transport, modèle ir.mail_server) sélectionne le serveur sortant par priorité décroissante. Comprendre les cinq étapes évite les surprises de routage.
- Match exact sur l'adresse From. Cherche un serveur dont le
from_filtercontient l'adresse normalisée exacte (ex:notifications@example.com). - Match sur le domaine du From. Cherche un serveur dont le
from_filtercontient juste le domaine (ex:example.com). C'est le cas le plus courant pour Brevo. - Fallback notifications. Si pas de match, bascule sur l'adresse de notifications définie dans
mail.alias.domain.default_from(ex:notifications@example.com) et reprend la recherche de l'étape 1 avec cette adresse. L'adresse From visible au destinataire change dans ce cas. - Catch-all. Prend le premier serveur sans
from_filterdu tout, classé parsequence. Un warning « No mail server matches the from_filter » est loggé. - CLI args. Dernier recours : utilise les paramètres
smtp_server/smtp_userdeodoo.confsi aucunir.mail_serverne convient.
Ce séquencement explique pourquoi un from_filter mal réglé peut silencieusement réécrire l'adresse From et casser DKIM. Le mécanisme est traité plus en profondeur dans l'article DKIM/SPF/DMARC, où chaque étape est mise en regard de la chaîne d'alignement.
7. mail.alias.domain : cohérence multi-société et bounces
Depuis la v17, le modèle mail.alias.domain remplace les anciens paramètres système (mail.catchall.domain, mail.bounce.alias, mail.default.from) et porte la configuration mail au niveau de chaque société. Chemin backend : Settings → Technical → Email → Alias Domains.
| Champ | Rôle | Valeur recommandée |
|---|---|---|
name | Domaine email | example.com |
bounce_alias | Local-part du Return-Path | bounce → bounce@example.com |
catchall_alias | Local-part du Reply-To catchall | catchall → catchall@example.com |
default_from | From par défaut | notifications → notifications@example.com |
company_ids | Sociétés rattachées | [société courante] |
La règle de cohérence à retenir : le domaine du from_filter de l'ir.mail_server Brevo doit correspondre au name du mail.alias.domain. Sinon, l'adresse notifications@example.com ne sera pas routée vers Brevo et tombera en étape 4 de _find_mail_server(), perdant l'alignement DKIM.
Pour la réception des bounces, le bounce_alias doit aussi être configuré comme un alias entrant dans Odoo si l'on souhaite tracker les rebonds dans mail.notification. Le détail du gateway entrant est couvert dans l'article dédié à fetchmail de cette série.
8. Tester l'envoi et inspecter en cas d'échec
Une fois la configuration en place, deux tests à enchaîner :
Test de connexion SMTP. Sur la fiche ir.mail_server, bouton Test Connection : vérifie que la connexion STARTTLS s'établit et que l'authentification passe. Un échec ici signale en général une clé SMTP incorrecte (confondue avec une clé API) ou un port bloqué par l'hébergeur.
Test fonctionnel complet. Ouvrir une commande de vente (sale.order) → bouton Send & Print → envoyer à une adresse réelle. Vérifier dans l'en-tête source du mail reçu (option « Afficher l'original » dans Gmail) :
DKIM-Signature: v=1; a=rsa-sha256; d=example.com; s=brevo1; ...
Authentication-Results: mx.google.com;
dkim=pass header.i=@example.com header.s=brevo1;
dmarc=pass action=none header.from=example.com
Les deux lignes critiques : dkim=pass et dmarc=pass sur le From: header du domaine d'envoi (pas sur celui de Brevo). Si dkim=fail ou si la signature est sur un autre domaine (ex: @brevosend.com), la configuration est cassée — revenir au workflow DNS section 4.
En cas d'échec à l'envoi, le diagnostic se fait sur deux tables :
mail.mail(Settings → Technical → Email → Emails). Liste tous les emails sortants avec leur état (outgoing,sent,exception,cancel). Le champfailure_reasoncontient le retour SMTP brut en cas d'erreur (ex:550 5.7.1 This domain is not authorized to send mail through Brevo).mail.notification. Statuts par destinataire :sent,bounce,exception,canceled. C'est ici que les NDR (Non-Delivery Reports) retournés via lebounce_aliasOdoo se reflètent côté analytique.
Les emails restés en outgoing indéfiniment trahissent un cron arrêté — le job Mail: Fetchmail / Email Queue Manager doit tourner. La gestion de la queue par cron est détaillée dans l'article sur les actions serveur et crons.
9. Cinq pièges spécifiques Brevo + Odoo
Les erreurs récurrentes en production avec Brevo + Odoo se concentrent sur cinq points :
-
Domaine non validé chez Brevo. Bounce systématique avec
550 5.7.1 This domain is not authorized to send mail through Brevo. Toujours s'assurer que les checkmarks verts apparaissent côté Brevo Domains avant de configurer le serveur sortant Odoo. -
SMTP key vs API REST key. Erreur
535 5.7.8 Authentication credentials invalid. Les deux clés sont générées dans la même section du backoffice Brevo mais ne sont pas interchangeables — seule la clé SMTP (onglet SMTP Keys) fonctionne pour le relais STARTTLS. -
SPF Brevo mis en avant comme garantie DMARC. L'include
include:spf.brevo.comest optionnel et n'aligne pas DMARC, car l'Envelope From appartient à Brevo (@sender-sib.com) et non au domaine d'envoi. Seul DKIM aligne avec Brevo en IPs partagées. C'est le point qui surprend le plus en sortie d'audit DMARC. -
Cloudflare CNAME flattening activé. Cloudflare convertit alors les CNAME
brevo1/brevo2._domainkeyen TXT statiques, et DKIM échoue à la première rotation de clé Brevo. Désactiver le flattening pour ces enregistrements spécifiques (ou utiliser une zone DNS sans flattening). - Brevo SMTP utilisé pour des campagnes de masse. Brevo limite le relais SMTP transactionnel et impose des temporisations en cas de rafale. Pour des campagnes de plus de quelques milliers d'envois, utiliser l'API REST marketing de Brevo (ou un autre canal dédié), pas le relais SMTP transactionnel.
À retenir : Brevo se configure en cinq champs Odoo, mais la qualité de la délivrabilité dépend de trois enregistrements DNS et d'un from_filter aligné. Tout le reste — multi-société, bounces, monitoring — est une mécanique de cohérence entre ir.mail_server et mail.alias.domain.
L'article suivant de cette série traitera des autres relais transactionnels (Mailjet, Amazon SES, serveurs SMTP personnels) avec leurs spécificités et leurs cas d'usage typiques.
Voir aussi dans ce parcours Infrastructure
Architecture mail Odoo — les 4 couches
HUB de la série Tech-Email : cartographie transport / message / template / mass et flux complet message_post → SMTP.
DKIM, SPF, DMARC pour Odoo
Détail cryptographique des records DNS, pivot from_filter, et 5 erreurs fréquentes à éviter.
Série Tech-Email — Article 2/14 — Parcours Infrastructure emailing Odoo 19.
Articles complémentaires
Email templates et mail.thread
Envoi automatique depuis create et write — patterns chatter et templates Odoo 19.
Actions serveur, cron et automations
ir.cron et base.automation — le moteur qui processe la queue mail.mail.
Sources officielles : Brevo Help — SMTP relay · Odoo 19 — Outgoing mail servers.