Engineering
SPF, DKIM and DMARC: Getting Email Authentication Right
Why your invoices land in spam, and how anyone can currently send email as your company. Configuring SPF, DKIM and DMARC without breaking mail.
Two things are probably true of your domain right now, and both cost money.
Anyone can send email pretending to be you. Unless you have a DMARC policy set to quarantine or reject, a receiving server has no instruction to refuse a forged message from your domain. Invoice fraud against your customers works this way.
Some of your legitimate email is going to spam. Since February 2024, Google and Yahoo require authentication for bulk senders. Microsoft followed. Domains without correct SPF, DKIM and DMARC are increasingly filtered or rejected outright.
This is not an IT hygiene issue. If you send order confirmations, invoices, password resets or marketing email, it is revenue infrastructure.
Here is how the three records work and how to configure them without breaking anything.
SPF: which servers may send as you
SPF is a DNS TXT record listing the servers authorised to send email from your domain.
v=spf1 include:_spf.google.com include:servers.mcsv.net ~all
Reading that: SPF version 1; authorise Google Workspace's servers; authorise Mailchimp's servers; anything else is a soft fail.
The three ways SPF goes wrong
Too many DNS lookups. Each include, a, mx, ptr, exists and redirect mechanism costs a lookup, and nested includes count too. The RFC limit is 10. Exceed it and SPF returns permerror — which most receivers treat as a failure, so your legitimate mail starts being rejected.
This creeps up on you. Google Workspace plus a CRM plus a marketing platform plus a helpdesk plus an invoicing tool, each with nested includes, silently crosses 10.
Fix it by flattening — replacing include: mechanisms with the IP ranges they resolve to — or by removing services that no longer send mail. Flattening has a maintenance cost: if the provider changes IPs, your SPF is now wrong. Prefer removing unused includes first.
Multiple SPF records. A domain may have exactly one. Two TXT records both beginning v=spf1 is a permerror. This happens when a second vendor is onboarded and adds their own record instead of editing the existing one. Merge them into one.
Ending in +all. This authorises the entire internet to send as your domain. It is worse than having no SPF at all, because it actively asserts that forgeries are legitimate. It usually appears when someone was debugging a delivery problem and never reverted it.
Use ~all (soft fail) while you are still discovering senders, and -all (hard fail) once you are confident the list is complete.
DKIM: cryptographic proof
DKIM adds a signature to outgoing mail, computed with a private key held by your email provider. The matching public key lives in your DNS. A receiving server verifies the signature, which proves the message genuinely came from your domain and was not altered in transit.
The record lives at selector._domainkey.yourdomain.com, where the selector is chosen by the provider — google, selector1, k1, s1, and so on.
Two practical points:
There is no way to enumerate selectors from outside. Any tool that says "DKIM missing" is really saying "not found on the selectors I tried." Your provider's documentation tells you yours. Treat a public checker's DKIM result as inconclusive, not definitive.
Every sending service needs its own DKIM. Google Workspace signs mail sent through Gmail. It does not sign your Mailchimp campaigns. Each platform that sends on your behalf must be configured separately.
DMARC: the policy that ties it together
SPF and DKIM produce results. DMARC says what to do with them — and, critically, requires alignment: the domain that passed SPF or DKIM must match the domain in the visible From: header.
Alignment is what makes DMARC meaningful. Without it, a forger could pass SPF for their own domain while displaying yours in the From: field.
v=DMARC1; p=reject; rua=mailto:dmarc@yourdomain.com; pct=100; adkim=s; aspf=s
p=— the policy:none,quarantineorrejectrua=— where aggregate reports are sentpct=— percentage of messages the policy applies to, for staged rolloutadkim=/aspf=— alignment strictness:sstrict,rrelaxed
The p=none trap
A large share of domains with DMARC are sitting at p=none. Many have been for years.
p=none means: evaluate, report, and deliver anyway. It blocks nothing. Spoofed mail claiming to be your domain still arrives in your customers' inboxes.
It is the correct starting point — you need the reports to discover every legitimate sender before you start rejecting. It is not a finished configuration. A domain at p=none has the appearance of protection without the substance, which is arguably worse than having no record, because it stops people from looking further.
Rolling out safely
The risk in moving to enforcement is breaking legitimate mail you forgot about — the invoicing system, the recruitment platform, the ten-year-old server that sends nightly reports. The staged path exists to find those before they break.
- Publish
p=nonewithrua=. Collect reports for 2–4 weeks. - Read the reports. They are XML; use a free parser or a service like Postmark's DMARC digests. You are looking for sources that send as you and fail alignment.
- Fix or authorise every legitimate source. Add it to SPF, configure its DKIM, or move it to a subdomain.
- Move to
p=quarantine; pct=10. Watch for a week. Raise to 50, then 100. - Move to
p=reject. Only once the reports are clean.
Expect this to take one to three months for an organisation of any size. Rushing step 3 is how you discover that your accounting system stopped delivering invoices.
Two things people miss
Subdomains. DMARC applies to subdomains via the sp= tag. If you do not set it, subdomains inherit the parent policy. Attackers specifically use unused subdomains — mail.yourdomain.com, billing.yourdomain.com — because they are frequently unprotected. Set sp=reject on domains that should never send from subdomains.
Parked domains. Every domain you own that sends no email should still publish v=spf1 -all and v=DMARC1; p=reject;. Defensive registrations and old brand domains are attractive spoofing targets precisely because nobody thinks to protect them.
BIMI, briefly
Once you are at p=quarantine or p=reject, BIMI lets your logo appear next to your messages in supporting clients. It requires a Verified Mark Certificate, which costs roughly $1,000–1,500 per year.
It is a reasonable brand investment for high-volume senders. It is not a deliverability improvement — it is a display feature that requires you to have already done the authentication work.
Checking your own configuration
You can inspect any domain's live records with our free email deliverability checker. It queries DNS directly from your browser and shows the actual record text, so you can see exactly what is published rather than a score.
Or query directly:
dig +short TXT yourdomain.com # SPF among the results
dig +short TXT _dmarc.yourdomain.com # DMARC
dig +short TXT google._domainkey.yourdomain.com # DKIM, if that selector
dig +short MX yourdomain.com # inbound mail servers
Priority order
If you are starting from nothing:
- Publish SPF listing every service that sends as you, ending
~all - Enable DKIM on every one of those services
- Publish DMARC at
p=nonewith arua=address - Read the reports for a month, fixing what fails
- Move to
p=quarantine, thenp=reject - Protect subdomains and parked domains
- Tighten SPF to
-all
Steps 1 to 3 are an afternoon. Steps 4 and 5 are where the actual work is, and where most organisations stop. Finishing is the part that stops your domain being spoofed.