Email was designed with no way to prove who sent a message. SPF, DKIM and DMARC are the three DNS records that fix that. Together they let a mailbox provider check that mail claiming to be from your domain came from a service you approved.
When they are missing or wrong, your real email gets filtered as suspicious and criminals can send invoices in your name.
How the three records work together
SPF is the guest list, DKIM is a tamper-evident seal, and DMARC is the policy at the door that decides what happens to anyone who fails both.
| Record | Where it lives | What it checks |
|---|---|---|
| SPF | TXT record on your domain | Is the sending server on the list of approved senders for the envelope (bounce) domain? |
| DKIM | TXT or CNAME at selector._domainkey.yourdomain | Does the message carry a valid cryptographic signature from that domain, and is it unchanged? |
| DMARC | TXT record at _dmarc.yourdomain | Did SPF or DKIM pass for a domain that matches the visible From address? If not, what should happen? |
Alignment: the part most people miss
SPF and DKIM on their own do not check the From address your recipient sees. SPF checks the hidden envelope sender (the Return-Path, where bounces go), and DKIM checks whichever domain signed the message (the d= value in the signature).
DMARC closes that gap with alignment. A message passes DMARC if at least one of these is true:
- SPF passed, and the Return-Path domain matches the From domain.
- DKIM passed, and the signing
d=domain matches the From domain.
With the default relaxed alignment, "matches" means the same organisational domain, so bounce.example.com aligns with example.com. That is why a newsletter platform can pass SPF and DKIM yet fail DMARC: it passes for its own domain until you set up DKIM for yours in its settings.
SPF: the list of approved senders
An SPF record is a single TXT record on your domain that starts with v=spf1, lists the servers allowed to send, and ends with a rule for everyone else.
Example SPF records
Google Workspace only:
v=spf1 include:_spf.google.com ~all
Microsoft 365 only:
v=spf1 include:spf.protection.outlook.com -all
Mailbox at your web host (Hostinger shown; other hosts publish their own include in their email DNS settings, so copy the exact value your control panel gives you):
v=spf1 include:_spf.mail.hostinger.com ~all
Google Workspace plus a newsletter platform and a transactional service, merged into one record:
v=spf1 include:_spf.google.com include:servers.mcsv.net include:sendgrid.net ~all
Those are Mailchimp's and SendGrid's includes, shown for illustration. Always copy includes from each provider's current documentation.
Only ever one SPF record
A domain must have exactly one TXT record beginning with v=spf1. When a new service tells you to "add this SPF record", it means add its include to your existing record, not create a second one. Two SPF records produce a permanent error, and SPF then fails for every message, including ones from your main mailbox.
The 10 DNS lookup limit
The standard (RFC 7208) caps evaluation at 10 DNS lookups. The mechanisms that count are include, a, mx, ptr, exists and the redirect modifier. Crucially, lookups inside each include count too. ip4, ip6 and all do not.
Google's include costs several lookups once its nested includes are followed, so a few marketing tools on top can push a domain over. Past 10, the result is a permanent error, which most receivers treat as a fail.
To stay under the limit:
- Remove includes for services you no longer use.
- Drop
aandmxunless your website or mail servers genuinely send mail directly. - Never use
ptr; the standard discourages it. - Move bulk and marketing mail to a subdomain such as
news.example.comwith its own SPF record. It has its own 10 lookup budget. - Rely on DKIM for services that support a custom DKIM domain. DMARC only needs SPF or DKIM to align, and many platforms use their own Return-Path anyway.
"SPF flattening" replaces includes with raw IP addresses. Providers change their ranges without notice, so only use a service that updates the record automatically.
~all versus -all
~all (soft fail) says mail from unlisted servers is probably not legitimate. -all (fail) says it definitely is not. Once DMARC is enforcing, DMARC makes the final decision anyway. Use ~all while you are still discovering who sends for you, and -all when you are confident the list is complete. Never use +all: it authorises the entire internet.
DKIM: the tamper-evident seal
DKIM has the sending service sign each message with a private key. The matching public key is published in your DNS, and the receiver uses it to check the signature. A valid signature proves the message came from someone holding your key and was not altered.
Unlike SPF, DKIM usually survives forwarding, because the signature travels with the message.
Selectors
Each key lives at a name made from a selector plus ._domainkey. The selector lets one domain have many keys, one per service. Some common ones:
| Provider | Typical selector | Record type |
|---|---|---|
| Google Workspace | google (default) | TXT, generated in the Admin console |
| Microsoft 365 | selector1 and selector2 | Two CNAMEs pointing at keys Microsoft hosts |
| Hosting mailboxes and email platforms | Varies by provider | TXT or CNAME, shown in the provider's DNS settings |
google._domainkey.example.com TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
DNS cannot list every selector on a domain, so checkers can only try common names. To find yours, open a message you sent, view the original headers, find the DKIM-Signature line and read the s= value (the selector) and d= value (the signing domain).
Two Google gotchas: after publishing the record, click Start authentication in the Admin console. And if your DNS panel rejects the long 2048-bit key, split it into multiple quoted strings in the same record rather than falling back to 1024-bit.
Key rotation
Use 2048-bit keys and rotate them periodically, especially after staff or agency changes. The safe method is to publish a new key under a new selector, switch signing to it, wait a few days for in-flight mail, then remove the old record. Microsoft 365 does this for you by alternating between its two selectors.
DMARC: the policy and the reports
DMARC is a TXT record at _dmarc.yourdomain. It tells receivers what to do with mail that fails alignment, and asks for reports that reveal every service sending as your domain.
_dmarc.example.com TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.com; adkim=r; aspf=r"
| Tag | What it does | Typical value |
|---|---|---|
p | Policy for failing mail: none (report only), quarantine (spam folder) or reject (refuse it) | Start at none |
rua | Where daily aggregate reports go (XML summaries of who sent as you and whether they passed) | A dedicated mailbox or a report service |
ruf | Where per-message failure reports go. Many large providers do not send these for privacy reasons | Optional |
pct | Percentage of failing mail the policy applies to, used to phase in enforcement | 100 (the default) |
adkim | DKIM alignment: r relaxed (subdomains match) or s strict (exact match) | r |
aspf | SPF alignment, same options | r |
sp | Policy for subdomains, if different from p | Usually omitted, or reject for unused subdomains |
If the rua address is on a different domain, that domain must publish a small authorisation record. Report services handle this for you.
A safe rollout plan
- Weeks 1 to 4:
p=nonewithrua. Read the aggregate reports. List every source sending as your domain and fix each legitimate one until it passes SPF or DKIM with alignment. - Next:
p=quarantine; pct=25. A quarter of failing mail goes to spam. After a week or two of clean reports, raisepctto 50 and then 100. - Finally:
p=reject. Failing mail is refused outright. This is full protection against exact-domain spoofing.
Keep rua reporting on permanently. Some receivers apply pct values between 0 and 100 inconsistently, and the revised DMARC specification moves away from it, so treat pct as a gentle phase-in rather than a precise dial.
Tip: Domains you own but never send from are easy spoofing targets. Protect them with v=spf1 -all and v=DMARC1; p=reject; straight away. There are no legitimate senders to break.
Google and Yahoo sender requirements
In February 2024 Google and Yahoo began enforcing new rules for anyone sending to their users. Microsoft announced similar rules for high-volume senders to Outlook.com in 2025. The core rules are:
- All senders must authenticate with SPF or DKIM (set up both), have valid forward and reverse DNS for sending servers, use TLS, and keep spam complaints low.
- Bulk senders, which Google defines as close to 5,000 or more messages a day to Gmail addresses, must have SPF, DKIM and a DMARC record (
p=noneis the minimum), and the From domain must align with SPF or DKIM. - Marketing and subscribed mail from bulk senders must support one-click unsubscribe (the
List-UnsubscribeandList-Unsubscribe-Postheaders) and honour requests within two days. - Spam complaint rates, as reported in Google Postmaster Tools, must stay below 0.3%, and Google recommends keeping them under 0.1%.
Reputable newsletter platforms add the unsubscribe headers for you. Publishing your DNS records is still on you.
Common mistakes
- Two SPF records, usually because a new service's instructions were followed literally.
- Over 10 SPF lookups from years of accumulated includes.
- DKIM published but not switched on in the sending service, so mail is still signed with the provider's domain.
- Website forms sending from the web server via PHP mail, which is not in SPF and does not sign with DKIM.
- Forms using the visitor's address in From. That is spoofing someone else's domain and will fail their DMARC. Put the visitor in Reply-To.
- Jumping straight to
p=rejectwithout reading reports first. - Records at the wrong name. Many DNS panels append the domain, so enter just
_dmarc, not_dmarc.example.com.
Troubleshooting
Start with the message headers
Send a message to a Gmail address, open it, and choose Show original. Gmail shows SPF, DKIM and DMARC results at the top, and the Authentication-Results header shows which domain each check passed for. This tells you whether the problem is the record, the alignment or the service.
Symptoms and likely causes
| What you see | Likely cause |
|---|---|
spf=permerror | Two SPF records, over 10 lookups, or a syntax error |
spf=pass but dmarc=fail | SPF passed for the provider's bounce domain, not yours, and DKIM is not aligned |
dkim=fail (body hash did not verify) | Something modified the message after signing, such as a mailing list footer or security gateway |
| No DKIM result for your domain | DKIM not enabled in the service, or the record is at the wrong selector |
| Passes everywhere except forwarded mail | Forwarding breaks SPF; make sure DKIM is signing and aligned |
| Record looks right but checks still fail | The DNS change has not propagated, or it was added at the wrong host or name |
For that last row, query the record directly. If public resolvers return the old value or nothing at all, the problem is DNS, not email.
Launching a new site too? See our website launch checklist.
Frequently asked questions
Do I need all three: SPF, DKIM and DMARC?
Yes, if you want reliable delivery. SPF and DKIM prove a message is authorised, and DMARC tells receivers what to do when neither proof lines up with the From address. Google and Yahoo require bulk senders to have all three, and smaller senders without them are far more likely to land in spam.
Can I have two SPF records?
No. A domain must publish exactly one TXT record starting with v=spf1. If there are two, receivers return a permanent error and SPF fails for everything. Merge every sender into one record with a single all at the end.
Will turning on DMARC stop my email being delivered?
Not if you start with p=none. That policy only asks receivers to send you reports and changes nothing about delivery. Problems only appear if you jump to quarantine or reject before every legitimate sender passes SPF or DKIM with alignment.
How long does it take for SPF, DKIM or DMARC changes to work?
As long as the record's TTL, which is often an hour or less but can be up to a day or two. Most receivers see a new record within an hour. Check the record with a public DNS lookup before assuming it is live, and expect the first DMARC aggregate reports the day after you publish.
Why does my contact form email fail DMARC when my normal email passes?
Usually because the form sends from your web server, which is not in your SPF record and does not sign with your DKIM key, or because it puts the visitor's address in the From field. Send form email through an authenticated SMTP or transactional service using an address on your own domain, and put the visitor's address in Reply-To.