Ce que tu vas apprendre
Les 3 protocoles
SPF, DKIM, DMARC — leur rôle, leur articulation, ce qu'Odoo fait (et ne fait pas).
Le pivot from_filter
Pourquoi ce champ d'ir.mail_server conditionne l'alignement DKIM.
3 records DNS prêts
Setup type Brevo + Odoo : TXT SPF, CNAME DKIM, TXT DMARC.
5 pièges fréquents
Encapsulation From, Return-Path mal aligné, ICPs legacy, SPF > 10 lookups…
Prérequis
- Une instance Odoo 19 fonctionnelle (cf. installer Odoo 19 sur Ubuntu).
- Accès admin Odoo : menu Settings → Technical → Email (mode développeur activé).
- Accès au panneau DNS du domaine expéditeur (registrar OVH, Cloudflare, Gandi, Route 53…).
- Un compte chez un relais SMTP transactionnel (Brevo, Mailjet, SES, Postmark…) ou un serveur Postfix dédié avec OpenDKIM.
- Notions de base des enregistrements DNS : TXT, CNAME, MX.
1. Pourquoi trois protocoles complémentaires ?
SMTP a été conçu en 1982 sans aucune notion d'authentification. N'importe quel serveur peut prétendre envoyer du courrier au nom de n'importe quel domaine. Trois RFC successives ont rebouché ce trou : RFC 7208 pour SPF, RFC 6376 pour DKIM, RFC 7489 pour DMARC. Aucune ne suffit seule. Combinées, elles offrent une chaîne d'identité solide.
L'analogie qui aide à les retenir : imagine un envoi recommandé à la frontière.
- SPF = la liste des transporteurs autorisés à présenter un colis au nom de l'expéditeur. Le douanier vérifie que le camion qui se présente figure bien sur la liste publique.
- DKIM = un cachet cryptographique apposé sur l'enveloppe au départ. Le destinataire vérifie que le cachet est intact et que la clé publique correspond au domaine annoncé.
- DMARC = l'instruction laissée au guichet : « si ni la liste ni le cachet ne sont alignés avec le nom du domaine sur le colis, alors mets-le en quarantaine ou rejette-le, et envoie-moi un rapport quotidien. »
From.Le rôle d'Odoo dans cette chaîne
Odoo 19 ne signe pas DKIM et ne publie pas tes records DNS.
Il prépare correctement les headers From, Return-Path et
Reply-To — les mêmes mécaniques que celles utilisées par les
templates email et le mixin mail.thread,
sélectionne le bon relais SMTP via from_filter, et délègue ensuite l'envoi.
C'est le relais transactionnel (Brevo, Mailjet, SES…) qui appose la signature DKIM, et
c'est ton DNS qui publie SPF / DKIM / DMARC. La référence officielle :
la documentation Odoo 19 sur les serveurs sortants.
Le développeur Odoo a donc deux interfaces à maîtriser : ir.mail_server côté Odoo,
et le panneau DNS côté domaine.
2. SPF — autoriser les IPs sortantes
SPF (Sender Policy Framework) publie dans le DNS la liste des IPs et des domaines autorisés à envoyer du courrier au nom du domaine. Côté destinataire, le serveur de réception lit l'enregistrement TXT et vérifie que l'IP source de la connexion SMTP s'y trouve.
L'enregistrement est un TXT à la racine du domaine :
; Type : TXT
; Nom : @ (ou example.com.)
; Valeur :
"v=spf1 include:spf.brevo.com include:_spf.google.com ip4:91.121.55.78 ~all"
Lecture mécanique :
v=spf1— version du protocole (toujours 1).include:spf.brevo.com— inclut récursivement le SPF du relais Brevo (autorise toutes les IPs Brevo).include:_spf.google.com— autorise les IPs Google Workspace si une partie du trafic part par Gmail.ip4:91.121.55.78— autorise explicitement un serveur dédié (Postfix sur VPS, par exemple).~all— softfail pour toute autre source (recommandé en démarrage). Une fois sûr, passe à-all(hardfail).
Le Return-Path (l'enveloppe SMTP MAIL FROM) est l'adresse que SPF
vérifie, pas le header From visible. Côté Odoo 19, le
Return-Path est généré à partir de mail.alias.domain.bounce_email
(typiquement bounce@example.com). Si ce domaine n'est pas couvert par le SPF
publié, le check SPF échoue.
⚠️ Piège classique — la limite des 10 lookups DNS
SPF impose un maximum de 10 résolutions DNS (incluant les
include: récursifs). Chaque include compte ; un
include:_spf.google.com en consomme déjà entre 3 et 5 à lui seul. Si tu
cumules Brevo, Google, Microsoft et un fournisseur newsletter, tu dépasses vite.
Conséquence : PermError et SPF traité comme un échec. Outil de
diagnostic : dig +short TXT example.com puis comptage manuel, ou
un service tiers de validation SPF (MXToolbox, dmarcian).
3. DKIM — signature cryptographique du message
DKIM (DomainKeys Identified Mail, RFC 6376) ajoute un header DKIM-Signature au
message au moment de l'envoi. Cette signature est calculée par le relais SMTP sortant à
partir d'une clé privée. La clé publique correspondante est publiée dans le DNS sous un
sélecteur (par exemple brevo._domainkey.example.com). Le serveur destinataire
récupère la clé publique, vérifie la signature, et obtient deux informations critiques :
le message n'a pas été altéré en transit, et il a bien été émis avec l'autorisation du
propriétaire de la clé privée associée au domaine annoncé dans d=.
Exemple de header généré par un relais transactionnel :
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com;
s=brevo; t=1748241600; h=from:to:subject:date:message-id;
bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=;
b=ZjC3rW7w9Yc... (signature base64 tronquée)
Les champs qui comptent côté setup :
d=example.com— domaine signataire. C'est ce domaine qui doit être aligné avec le headerFrompour que DMARC valide.s=brevo— sélecteur. Pointe vers l'enregistrement DNSbrevo._domainkey.example.comqui publie la clé publique.h=from:to:subject:date:message-id— liste des headers couverts par la signature. Si l'un d'eux est modifié en transit, la signature casse.
L'enregistrement DNS chez ton registrar est typiquement un CNAME qui pointe vers le DNS du relais (le relais gère la clé) :
; Type : CNAME
; Nom : brevo._domainkey
; Valeur : brevo.brevo-1k.com. (fourni par le provider)
Certains providers exposent directement la clé publique en TXT au lieu d'un CNAME. La procédure est identique du point de vue Odoo : rien à configurer côté Odoo, tout côté DNS et côté compte provider.
4. DMARC — politique d'alignement et reporting
DMARC (RFC 7489) est la colle entre SPF et DKIM. Il répond à deux questions :
« que fait-on si l'email passe SPF ou DKIM mais que le domaine signataire n'est pas
aligné avec le From visible ? » et « à qui envoyer le rapport
quotidien des emails reçus en mon nom ? ».
L'enregistrement est un TXT sur le sous-domaine _dmarc :
; Type : TXT
; Nom : _dmarc
; Valeur :
"v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com; pct=100; aspf=r; adkim=r"
Décryptage :
p=none— politique observative en démarrage. Ne rejette rien, collecte les rapports. Puisp=quarantine, enfinp=rejectquand tous les flux sortants sont identifiés et alignés.rua=mailto:dmarc-reports@…— adresse de réception des rapports agrégés (Reporting URI Aggregate). Un rapport XML quotidien y atterrit, signé par chaque opérateur de boîtes de réception (Gmail, Outlook, Yahoo…).pct=100— pourcentage d'emails auxquels la politique s'applique. Utile pour un déploiement progressif (pct=10= 10% des emails non conformes sont rejetés, le reste est observé).aspf=retadkim=r— mode d'alignement relaxed. Tolère quemail.example.comaligne avecexample.com.s(strict) exige une correspondance exacte.
Industrie 2026 — l'enforcement Google/Yahoo/Microsoft
Depuis février 2024 chez Google et Yahoo, et mai 2025 chez Microsoft Outlook, les
expéditeurs qui dépassent 5 000 messages/jour vers leurs boîtes doivent
impérativement publier SPF, DKIM et DMARC alignés, sous peine de rejet
SMTP direct. PCI DSS v4.0 impose également DMARC depuis 2026 pour toute organisation
traitant des paiements par carte. Un déploiement p=none est tolérable
quelques semaines en démarrage, mais la cible production est p=quarantine
au minimum — ce qui s'inscrit dans une démarche plus large de
sécurisation d'une instance Odoo en production.
5. Setup type — Brevo + Odoo 19 + 3 records DNS
Cas concret : domaine example.com, relais transactionnel Brevo, instance
Odoo 19 envoyant les notifications, les emails de devis et les newsletters. Cinq étapes,
pas une de plus.
Étape 1 — Valider le domaine dans le compte Brevo
Dans l'interface Brevo : Senders, Domains & Dedicated IPs → Domains → Add a new
domain. Saisir example.com. Brevo fournit immédiatement :
- 1 TXT de vérification de propriété (à supprimer une fois validée).
- 1 valeur SPF à inclure (
spf.brevo.com). - 2 CNAME DKIM (
brevo1._domainkeyetbrevo2._domainkey— 2 sélecteurs pour rotation de clés).
Étape 2 — Publier les 3 records DNS
Chez le registrar (OVH, Cloudflare, Gandi…) :
; SPF
example.com. IN TXT "v=spf1 include:spf.brevo.com ~all"
; DKIM
brevo1._domainkey IN CNAME brevo1.brevo-1k.com.
brevo2._domainkey IN CNAME brevo2.brevo-1k.com.
; DMARC
_dmarc.example.com. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com; pct=100"
Propagation DNS : de quelques minutes à 24h selon le TTL configuré. Brevo détecte automatiquement la validation et marque le domaine « authenticated ».
Étape 3 — Configurer le serveur SMTP sortant dans Odoo
Settings → Technical → Email → Outgoing Mail Servers → Create :
| Champ | Valeur | Pourquoi |
|---|---|---|
name | Brevo Transactionnel | Libellé interne. |
smtp_host | smtp-relay.brevo.com | Hôte SMTP fourni par Brevo. |
smtp_port | 587 | STARTTLS standard. |
smtp_encryption | starttls | Chiffrement à la connexion. |
smtp_authentication | login | Authentification login/password (pas OAuth2 pour Brevo). |
smtp_user | login Brevo fourni | Identifiant compte SMTP. |
smtp_pass | clé API SMTP Brevo | Pas le mot de passe du compte web. |
from_filter | example.com | Point critique pour l'alignement DKIM — voir ci-dessous. |
Étape 4 — Configurer le mail.alias.domain
Depuis Odoo 17, la configuration des adresses de bounce, catchall et default_from est centralisée
dans le modèle mail.alias.domain (et non plus dans l'ancien paramètre système
mail.catchall.domain — voir piège n° 3 plus bas).
Settings → Technical → Email → Alias Domains :
| Champ | Valeur |
|---|---|
name | example.com |
bounce_alias | bounce → bounce@example.com |
catchall_alias | catchall → catchall@example.com |
default_from | notifications → notifications@example.com |
L'effet : tout email sortant utilisera notifications@example.com comme
expéditeur par défaut, et bounce@example.com comme Return-Path.
Le domaine example.com est couvert par le SPF, donc le check SPF passe. Le
domaine est signé DKIM par Brevo, donc d=example.com. Les deux sont
alignés avec le header From : DMARC valide.
from_filter détermine quel ir.mail_server traite le message.
S'il matche le domaine du header From, l'expéditeur est conservé, le relais signe
avec le bon d=, et DMARC valide. Sinon, Odoo encapsule l'adresse et l'alignement
casse.Étape 5 — Tester la chaîne complète
Bouton Test Connection sur la fiche ir.mail_server — vérifie l'authentification
SMTP. Puis envoi d'un email réel vers un service de validation externe
(check-auth@verifier.port25.com, mail-tester.com) qui renvoie un rapport
détaillé sur SPF, DKIM et DMARC en quelques secondes. Score cible : 10/10.
6. Vérification — les outils du DevOps email
Trois familles d'outils, à utiliser dans cet ordre : validation des records DNS, test d'envoi réel, lecture des rapports DMARC.
Validation des records DNS
- MXToolbox (
mxtoolbox.com) — lookup SPF, DKIM, DMARC. Affiche en clair le nombre de lookups SPF (alerte si proche de 10). - Google Admin Toolbox — Check MX — diagnostic complet du domaine côté Gmail.
digen CLI :dig +short TXT example.compour SPF,dig +short CNAME brevo1._domainkey.example.compour DKIM,dig +short TXT _dmarc.example.compour DMARC.
Test d'envoi réel
- mail-tester.com — envoie un email à l'adresse fournie, retourne un score /10 avec détail SPF, DKIM, DMARC, contenu, blacklist.
check-auth@verifier.port25.com— répond automatiquement avec un rapport SMTP brut très complet.- Bouton « Tester la connexion » sur
ir.mail_serverdans Odoo — valide uniquement l'authentification SMTP, pas la signature DKIM. Toujours doubler avec un test réel externe.
Analyse des rapports DMARC
- dmarcian.com — interface web qui agrège les rapports XML reçus à l'adresse
rua=. Affiche un dashboard par source, IP, taux d'alignement. - PowerDMARC — alternative SaaS, freemium jusqu'à 10 000 messages/mois.
- Parseur Python maison — les rapports DMARC sont des fichiers ZIP contenant un XML normalisé ;
parsedmarc(PyPI) parse et exporte vers Elasticsearch / Splunk pour les setups internes.
7. Lire un rapport DMARC agrégé
Un rapport agrégé arrive quotidiennement à l'adresse rua=. Format : XML
compressé en GZIP ou ZIP, envoyé par chaque opérateur (Google, Microsoft, Yahoo…). Extrait
représentatif d'un rapport Google :
<feedback>
<report_metadata>
<org_name>google.com</org_name>
<email>noreply-dmarc-support@google.com</email>
<report_id>14831284727584810532</report_id>
<date_range>
<begin>1748131200</begin>
<end>1748217599</end>
</date_range>
</report_metadata>
<policy_published>
<domain>example.com</domain>
<adkim>r</adkim>
<aspf>r</aspf>
<p>none</p>
<pct>100</pct>
</policy_published>
<record>
<row>
<source_ip>185.34.32.7</source_ip>
<count>42</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>pass</dkim>
<spf>pass</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<dkim><domain>example.com</domain><result>pass</result></dkim>
<spf><domain>example.com</domain><result>pass</result></spf>
</auth_results>
</record>
</feedback>
Lecture utile :
source_ip+count— quelle IP envoie en mon nom, combien de messages.policy_evaluated/dkimetspf— verdict DMARC pour chaque protocole.auth_results— résultats bruts, avant prise en compte de l'alignement.header_from— domaine présenté dans le headerFrom.
Pattern à surveiller : une source_ip inconnue qui envoie en quantité avec
dkim=fail ou spf=fail. C'est soit un ancien relais oublié dans le
SPF, soit une newsletter tierce non autorisée, soit un usurpateur. Réaction : identifier
l'IP, l'ajouter au SPF si légitime, ou passer la politique à p=quarantine si
illégitime.
8. Cinq erreurs fréquentes (et comment les détecter)
1 — from_filter vide ou trop large
Symptôme : les emails partent, mais Gmail affiche « envoyé par brevo.com au nom de example.com »
et le header From est encapsulé (« Notifications via … <notifications@brevo.com> »).
Cause : from_filter vide → Odoo sélectionne le premier serveur disponible, qui ne signe pas
forcément le domaine du From. Fix : renseigner précisément
from_filter = example.com sur le serveur SMTP qui correspond au domaine signé DKIM.
2 — bounce_email sur un domaine différent du from_filter
Symptôme : SPF passe sur le header From, mais DMARC en mode strict
échoue car le Return-Path (utilisé pour SPF identifier alignment) pointe sur un
autre domaine. Fix : aligner le domaine de mail.alias.domain avec le
from_filter. C'est presque toujours le même.
3 — ICP legacy mail.catchall.domain encore actif
Symptôme : les emails partent avec un From incohérent, le menu
Settings → Technical → Email → Alias Domains affiche un domaine, mais le code
utilise encore l'ancien paramètre système. Cause : une base migrée depuis v15/v16
garde l'ICP mail.catchall.domain qui prend le pas. Ce piège est typique
d'une migration mal nettoyée vers Odoo 19.
Fix : vérifier dans Technical → Parameters → System Parameters que
mail.catchall.domain, mail.bounce.alias,
mail.default.from n'existent plus, ou supprimer ces lignes. Odoo 19 migre
automatiquement via _migrate_icp_to_domain() mais certains scripts d'import
peuvent les recréer.
4 — SPF qui dépasse 10 lookups DNS
Symptôme : rapport DMARC affiche spf=permerror (erreur permanente — le
nombre de résolutions DNS imbriquées dépasse la limite de 10 fixée par la RFC 7208, le
check SPF est abandonné). Aucun email n'est rejeté par SPF lui-même, mais l'alignement
DMARC échoue systématiquement. Fix : simplifier le SPF — remplacer les
include: par des ip4: directs quand possible, ou consolider
plusieurs relais sur un seul. Outil utile : dmarcian.com/spf-survey/.
5 — p=reject activé trop tôt
Symptôme : une newsletter Mailchimp envoyée par le service marketing arrête de
livrer chez Gmail. La newsletter signait d=mailchimp.com sans alignement
avec From: …@example.com. Fix : revenir à p=quarantine
ou p=none, identifier toutes les sources légitimes dans le rapport
DMARC, les ajouter au SPF, faire signer DKIM avec un domaine aligné, puis ré-escalader.
Règle : 2 semaines minimum à p=quarantine avant de passer à
p=reject.
Récapitulatif
- SPF autorise les IPs sortantes au nom du domaine — TXT à la racine, attention aux 10 lookups.
- DKIM signe le message cryptographiquement — CNAME ou TXT sous le sélecteur, géré par le relais transactionnel.
- DMARC arbitre l'alignement et collecte les rapports — TXT sur
_dmarc, démarre toujours enp=none. - Côté Odoo 19, le pivot est
from_filtersurir.mail_server. Aligne-le avec le domaine signé par le relais. - Le modèle
mail.alias.domain(depuis v17) centralise bounce, catchall et default_from. Plus d'ICPmail.catchall.*à manipuler. - Industrie 2026 : Google, Yahoo et Microsoft imposent SPF + DKIM + DMARC aux expéditeurs > 5 000/jour. Pas négociable.
Le couplage Odoo ↔ relais SMTP est plus subtil qu'un simple branchement de serveur. Une fois
les 3 records DNS publiés et le from_filter aligné, les rapports DMARC
convergent vers 100% d'authentification en quelques jours. Et le développeur Odoo récupère
une chaîne d'envoi vérifiable, traçable et conforme.
Pour la suite : la prochaine fois qu'un ticket « les emails Odoo finissent en
spam » arrive, le réflexe est de vérifier dans cet ordre — record SPF / record DKIM /
enregistrement DMARC / champ from_filter / mail.alias.domain.
Quatre-vingt-quinze pour cent des cas se résolvent dans ces cinq points.
Voir aussi dans le parcours Infrastructure
Installer Odoo 19 sur Ubuntu / Debian
Mettre en place une instance Odoo 19 propre — service systemd, utilisateur dédié, base PostgreSQL.
Sécuriser Odoo en production
HTTPS, reverse proxy, hardening PostgreSQL, dbfilter, désactivation de la liste des bases.
Migration Odoo 18 → 19
Hooks pre_init / post_init, stages de migration, 7 breaking changes v18 → v19.
Série Tech-Email — Article 4/14 — Parcours Infrastructure emailing Odoo 19.
Articles complémentaires
Email templates et mail.thread en Odoo
Une fois la chaîne d'authentification posée, place à la rédaction : templates QWeb, héritage mail.thread, chatter custom.
Actions serveur, cron et automations
Déclencher l'envoi d'emails sur événement, planifier des relances automatiques, router les messages entrants vers les bons modèles.
Aller plus loin avec le Guide Technique OdooSkills
Le guide complet de la stack Odoo 19 — installation, modélisation, vues, héritage, tests, déploiement. Plus de 100 articles techniques structurés en parcours.
Explorer le parcours technique