Configuring SPF and DKIM at Gandi
By Thomas · virtual CISO · 2026-07-24
A domain registered at Gandi starts with a quiet head start: the DNS zone does not arrive empty. The MX records point to the in-house mail service from day one, and an SPF record referencing _mailcust.gandi.net sits in the default zone template before the first webmail login. That is better than the blank page many hosts deliver — but the head start feeds an illusion, the illusion of a domain "already authenticated". A default SPF with a neutral qualifier, no DKIM enabled and no DMARC published protects close to nothing: it documents, it forbids nothing.
This guide walks the full path on the Gandi side: what GandiMail and LiveDNS actually cover, what the default SPF is worth and at which point it stops being enough, how DKIM gets enabled and what hides behind the gm1 to gm3 selectors, how the zone gets edited — web interface, text mode or API — and how to handle the very common case of a domain registered at Gandi whose mailboxes actually live at Microsoft 365 or Google Workspace.
The logic would be identical at any registrar: one SPF record to merge, DKIM keys to publish, a zone to edit cleanly, a check at the end. The equivalent guide for OVHcloud follows the very same outline; here, the focus is on what makes Gandi specific.
GandiMail and LiveDNS: two building blocks to keep apart
Gandi plays three distinct roles, best kept separate mentally. The first is registrar: renting the domain name itself. The second is LiveDNS, the in-house DNS platform — name servers in ns-…-a/b/c.gandi.net, offered by default on every new domain — which hosts the zone and its records. The third is GandiMail, the mail service: mailboxes, webmail, IMAP and SMTP through mail.gandi.net. These three bricks combine freely: a domain registered at Gandi can delegate its zone to another DNS host, and a LiveDNS zone can perfectly well serve a third-party mail provider. The cardinal point of the whole topic fits in one sentence: SPF and DKIM get published where the DNS zone lives, not where the mailboxes live.
A note on timing is in order. The two mailboxes historically bundled with every domain are gone from the offer: since late 2023, GandiMail has been a paid option. Many Gandi domains therefore no longer have an active Gandi mailbox — yet the zone still carries the records from the original template: MX entries toward spool.mail.gandi.net and fb.mail.gandi.net, the in-house SPF. The result is a population of zones advertising a mail service that no longer exists. Cleaning up those leftovers is an integral part of the authentication work: every record that no longer matches a real use is one wasted DNS lookup and one extra line of confusion in the inventory.
The SPF Gandi proposes: when it is enough, when it needs extending
The Gandi zone template places a record of this kind at the apex of the domain:
@ 10800 IN TXT "v=spf1 include:_mailcust.gandi.net ?all"
Decoded: the include delegates to Gandi the list of IP addresses allowed to send — GandiMail's outbound relays, which Gandi updates without the customer's zone ever moving. The trailing ?all is a neutral qualifier: it asserts nothing about servers outside the list. That is a prudent choice for a record installed by default, but a neutral SPF authorizes no rejection on the receiving side — it observes without committing.
When is this SPF enough? As long as all of the domain's mail leaves through GandiMail — webmail, IMAP/SMTP client via mail.gandi.net — the include covers every emission. The only remaining work is hardening the qualifier: ~all (softfail) during the observation phase, then -all once the inventory has been confirmed by DMARC reports.
When does it stop being enough? The moment an external router enters the picture: a newsletter through Mailjet or Brevo, transactional mail through SendGrid or Amazon SES, a CRM sending "on behalf of" the domain. The golden rule then is merging, never adding: a single v=spf1 record whose list of mechanisms grows.
v=spf1 include:_mailcust.gandi.net include:spf.mailjet.com ~all
A second v=spf1 TXT placed next to the first one produces a permerror — SPF failure for everyone, legitimate flows included. And the ten-DNS-lookup limit looms: every include counts, and the ones shipped by ESPs often nest several more.
DKIM on GandiMail: one activation, three selectors
SPF authenticates the sending server; DKIM signs the message itself, and the signature survives forwarding. On GandiMail, activation starts from the Email section of the domain's administration — a dedicated button triggers everything; the exact path through the interface shifts with each redesign, and Gandi's documentation remains the only up-to-date reference on that point. What the activation produces, on the other hand, is stable: three CNAME records.
gm1._domainkey 10800 IN CNAME gm1.gandimail.net.
gm2._domainkey 10800 IN CNAME gm2.gandimail.net.
gm3._domainkey 10800 IN CNAME gm3.gandimail.net.
If the zone sits on LiveDNS, those three lines are added automatically. If the DNS is delegated elsewhere, they must be created by hand at the zone host — same names, same targets. The elegance of the setup lies in the CNAME: the public key stays hosted at Gandi, which can renew it without the domain's zone ever changing. The three selectors gm1, gm2 and gm3 exist precisely for that rotation: while one key signs, the next one gets ready. That is a real operational advantage over the frozen TXT pasted once and then forgotten for years — DKIM key rotation is a hygiene habit few teams keep up when it stays manual.
Editing the LiveDNS zone: interface, text mode, API
LiveDNS offers three doors in, and each has its trap. The web interface presents the zone record by record: type, name, TTL, value. A TXT gets added in a few clicks, quoting is handled, and strings beyond 255 characters — a 2048-bit DKIM key, typically — are split automatically. Text mode displays the whole zone as a zone file: convenient for pasting several records at once, but it enforces zone-file syntax rules, trailing dot included (the blooper list below comes back to it). The LiveDNS REST API (v5), finally, opens the door to automation: authentication via a personal access token, one HTTP request to write a record — the natural route for managing SPF and DKIM as infrastructure-as-code, with the Terraform and Ansible connectors that build on it.
One cross-cutting setting deserves attention: the TTL, at 10800 seconds (three hours) by default. Before any operation on SPF or DKIM, lowering it to 300 seconds shortens the correction window if a mistake slips in; it goes back up afterwards. As for domains registered at Gandi whose zone is delegated to Cloudflare, the same exercise on the Cloudflare side — with its own traps, the orange proxy first among them — is covered in the dedicated Cloudflare guide.
Domain at Gandi, mailboxes elsewhere: only the values change
This is probably the most widespread case: the domain and its zone live at Gandi, the mailboxes at Microsoft 365 or Google Workspace. Nothing changes in the method — only the records change.
On the Microsoft 365 side, the SPF becomes v=spf1 include:spf.protection.outlook.com -all, and DKIM takes the form of two CNAMEs, selector1._domainkey and selector2._domainkey, pointing at the tenant under onmicrosoft.com; signing is switched on in the Defender portal. On the Google Workspace side: SPF v=spf1 include:_spf.google.com ~all, and DKIM as a google._domainkey TXT whose key — 2048 bits recommended — is generated in the admin console before being pasted into LiveDNS, which handles the splitting of the long string.
Two reflexes complete the picture. First, removing include:_mailcust.gandi.net when no message leaves through GandiMail anymore: a dead include burns one DNS lookup out of the ten allowed and widens the authorized surface for nothing in return. Second, replacing the template's Gandi MX records with those of the actual provider — MX entries pointing at spool.mail.gandi.net while the mailboxes sit at Microsoft misroute inbound mail and muddy the diagnosis.
The common mistakes, from duplicate SPF to the trailing dot
DMARC reports and community forums keep telling the same stories. A short blooper list:
- The duplicate SPF. The pre-filled zone already contains a
v=spf1; an ESP's setup wizard recommends adding its own; the two coexist, and the outcome is apermerror. Merging into a single record is the only way out. - The old SPF type. Zones inherited from Gandi's "classic" DNS infrastructure may still carry a record of type SPF (type 99), long deprecated by RFC 7208: only the TXT counts, and the type-level duplicate sows confusion and should go.
- The trailing dot. In text mode,
gm1.gandimail.netwithout a final dot becomesgm1.gandimail.net.example.com.— a CNAME that resolves nothing. The web form completes the name implicitly, text mode does not: the rule depends on the editor in use, hence the surprises when copying a line from one context to another. - Impatience. With a default TTL of three hours, the old value keeps being served by resolvers until the cache expires. Testing thirty seconds after the change and concluding failure is a DNS-propagation classic.
- The forgotten subdomain. SPF is not inherited: a sending subdomain (
newsletter.example.com) needs a record of its own.
The next step has a blooper list of its own: DMARC syntax, with its semicolons and trap tags, catalogued in the syntax errors of a DMARC record.
Checking, then plugging in DMARC
Verification is not guessed, it is measured. On the command line, two queries cover the essentials:
dig TXT example.com +short
dig CNAME gm1._domainkey.example.com +short
The first must return a single v=spf1…, the second the target gm1.gandimail.net.. The reality test completes the check: a message sent to a Gmail mailbox, then a read of the Authentication-Results header — spf=pass and dkim=pass with one of the gm1 to gm3 selectors are the signature of a healthy configuration.
With SPF and DKIM in place, what remains is plugging in the layer that exploits them: DMARC, as a TXT on _dmarc.example.com, starting with v=DMARC1; p=none; rua=mailto:… to observe without blocking anything. Rather than improvising the syntax, the safer start is a set of annotated DMARC record examples to adapt. The aggregate reports then reveal what the inventory missed — the old server still sending, the tool wired up by a subsidiary — and guide the climb toward p=quarantine then p=reject, the point where spoofing the domain stops being profitable.
In summary
Gandi ships a pre-filled zone that buys ten minutes, not a complete authentication. The in-house SPF include:_mailcust.gandi.net covers GandiMail and nothing else: it gets hardened (~all, then -all) and merged — never duplicated — when an ESP joins the mix. DKIM switches on with one button and rests on three gm1 to gm3 CNAMEs that leave key rotation in Gandi's hands. The zone can be edited by form, text mode or API, with the trailing dot and the three-hour TTL as recurring traps. And when the mailboxes live at Microsoft 365 or Google Workspace, the method stands: only the values change, provided the GandiMail leftovers get purged. For the precise interface paths, likely to move with every redesign, Gandi's documentation is the authority.
The final check costs nothing: one pass of the domain through the free DMARC analysis shows at a glance the real state of SPF, DKIM and DMARC as receiving servers see them. And to convert the try — following the reports, spotting the forgotten source, driving the policy all the way to p=reject — creating an account opens continuous monitoring, right where zone editing stops.
Enforcing DMARC, in practice
Thomas, the virtual CISO of DMARC.com, identifies every legitimate sending source, writes the exact DNS records, and takes a domain from p=none to p=reject — without breaking its mail.
Get to p=reject — freeRelated guides
- Setting up SPF and DKIM on OVHcloud
MX Plan, Email Pro or Exchange: each OVHcloud email plan has its own SPF and DKIM records. DNS zone, the default SPF trap, CNAME selectors and verification.
- Configuring the DMARC rua address (without getting tripped up)
The rua address receives the DMARC aggregate reports. The syntax is simple, but sending to an external domain hides an authorization trap many discover too late.
- DMARC record examples to copy (and understand)
Ready-to-paste DMARC record templates — monitoring, quarantine, reject, parked domain — with per-provider settings and the publishing pitfalls to avoid.
About the author
Thomas — Thomas is the virtual CISO of DMARC.com: a copilot specialized in email authentication that walks organizations from p=none to p=reject without breaking their mail. His guides draw on real data from the DMARC Observatory and the RUA reports the platform analyzes.
