If your transactional emails are landing in spam, your DMARC report is full offail verdicts, or Gmail just started bouncing 5% of your sends withthis message does not have authentication information, this guide is the fix. We'll set up SPF, DKIM, and DMARC the way they actually work in 2026 — post Google & Yahoo's February 2024 sender requirements, with the modern defaults receivers expect.
I'll skip the textbook history (you don't need to know that SPF was specified in 2006). What you need: exact records, alignment rules, the gotchas that quietly kill deliverability, and the verification commands that prove it's wired up correctly before you push to production.
The 30-second mental model
Three records, three jobs:
- SPF answers "is this server allowed to send mail claiming to be from
yourdomain.com?" A TXT record on the apex lists every IP / hostname / include that's authorized. - DKIM cryptographically signs each outbound message with a key whose public half you publish on a dedicated subdomain. Receivers verify the signature to prove the message wasn't modified in transit and really came from your authorized sender.
- DMARC is the policy layer. It tells receivers what to do when SPF and DKIM both fail (or don't align) — quarantine, reject, or just report. DMARC also asks for failure reports so you find out before users do.
All three are TXT records on your DNS provider. None of them touch your application code. None of them require SSL, ports, or firewall rules. Once published and propagated, they're passive — receivers consult them on every inbound message from your domain.
SPF: Authorize who can send for you
The record
Single TXT record on the apex (root) of your domain. Use exactly one — duplicates cause the protocol to return permerror and your mail is treated as unauthenticated for every recipient. We've written about this specific misconfiguration; it's the most common deliverability bug we see in production: teams add a second SPF record for a new sender instead of merging.
TYPE HOST VALUE
TXT @ (or apex) v=spf1 include:_spf.sendr365.com include:_spf.google.com ~allThe mechanism after each include: looks up the SPF record at that domain and chains its rules into yours. ~all at the end is a soft-fail catch — anyone not explicitly authorized is suspicious but not outright rejected. Most receivers treat -all (hard fail) the same way today, but soft-fail is the safer default while you stabilize.
The 10-lookup limit (the silent killer)
RFC 7208 §4.6.4 caps SPF at 10 DNS lookups total. Eachinclude:, a:, mx:, exists:, and redirect= counts. If your record blows past 10, receivers returnpermerror and your SPF is treated as if it doesn't exist.
This is sneaky because lookups recurse. include:_spf.google.com is one lookup, but it itself includes 4 others — so a single Google include actually burns 5 of your 10. Add Salesforce + Zendesk + Mailchimp + your own sender and you're permerror'd before noon. The fix: SPF flattening (resolve nested includes once, paste the IP ranges directly), or move marginal senders to subdomains with their own SPF.
Sendr365 surfaces this as a structural-health lint on every domain — if your record requires more than 10 lookups, we flag it before it breaks production.
DKIM: Sign every outbound message
How it works
Your sending platform generates a 2048-bit RSA keypair. The private half stays on the sender; the public half is published as a TXT record on a dedicated subdomain like resend._domainkey.yourdomain.com. Each outbound message gets a DKIM-Signature header with a hash signed by the private key. Receivers fetch the public key, verify the signature, and confirm the headers + body weren't tampered with.
The selector matters
The selector is the subdomain prefix — resend in the example above, or google for Google Workspace, or k1 / s1for SES. Receivers use the selector specified in the message'sDKIM-Signature: s=... header to find the public key. Your job is to publish the right selector for the platform you're actually signing with. Publishing a stale selector you no longer sign with is harmless but useless — receivers will look for the active selector and fail if it isn't there.
The record value looks like:
TYPE HOST VALUE
TXT resend._domainkey.yourdomain.com v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w...Most DNS providers have a 255-character limit per TXT chunk. If the public key is longer (2048-bit keys usually are), the value must be split into multiple quoted strings — your DNS provider will handle this transparently when you paste the full value, but watch for providers that silently truncate. dig +short TXT resend._domainkey.yourdomain.com after publishing is the sanity check.
1024 vs 2048 bits
2048-bit RSA is the modern minimum. 1024-bit is deprecated; Gmail treats it as neutral, not pass — you lose the deliverability signal. Anyone still on 1024 should rotate the keypair this quarter.
DMARC: The policy + the reports
The record
Single TXT record on a dedicated subdomain, _dmarc.yourdomain.com. RFC 7489 §6.6.3 allows exactly one — duplicates fail DMARC for every message regardless of how SPF and DKIM did.
TYPE HOST VALUE
TXT _dmarc.yourdomain.com v=DMARC1; p=none; rua=mailto:[email protected]; fo=1; aspf=r; adkim=rPolicy progression: none → quarantine → reject
Don't start at p=reject. You'll bounce legitimate mail for two weeks while you find every misconfigured sender on your team. The standard progression:
p=nonefor 2-4 weeks. Collect aggregate reports (rua) — they tell you every IP claiming to send for your domain and whether SPF/DKIM aligned. Find every sender you forgot about (the legacy PHP form-mailer, the marketing tool the previous CMO subscribed to, the monitoring system that emails alerts).p=quarantine; pct=25. Quarantine 25% of unaligned mail to spam. Watch the reports; nothing legitimate should be hitting spam. Rollpctup to 100 over a week.p=reject. Final state. Anyone spoofing your domain gets bounced at the SMTP layer.
Alignment: the part everyone misses
SPF and DKIM both passing isn't enough. DMARC requires alignment— the domain that authenticated must match the From: header domain. If your From: is [email protected] but SPF passes for amazonses.com (because that's theReturn-Path), SPF passes technically but fails to align. DMARC then fails too unless DKIM is aligned.
Two flavors of alignment, both controlled in the DMARC record:
aspf=r(relaxed) accepts subdomains:mail.yourdomain.comaligns withyourdomain.com.aspf=s(strict) requires exact match.adkim=r/adkim=sworks the same way for the DKIM signing domain.
Default to relaxed for both. Strict alignment breaks legitimate use cases (subdomain mail) without meaningful security upside.
Verifying it actually works
DNS panels lie. The record-publication confirmation in your provider's UI is not the same as receivers actually reading the right value. Verify against DNS directly.
SPF
dig +short TXT yourdomain.com | grep spf1
# expected: exactly one line starting with "v=spf1"Two lines = duplicate, fix immediately. Zero lines = not propagated, wait 5-10 minutes (TTL).
DKIM
dig +short TXT resend._domainkey.yourdomain.com
# expected: long string starting with "v=DKIM1"Replace resend with whatever selector your platform uses. If the result is empty but you definitely published, you may have published it on the wrong subdomain (e.g. resend._domainkey on a subdomain instead of the apex).
DMARC
dig +short TXT _dmarc.yourdomain.com
# expected: exactly one line starting with "v=DMARC1"End-to-end check
The real test is sending a message and reading the headers in the recipient's client. Send to a Gmail account, click "Show original", and look forspf=pass, dkim=pass, and most importantlydmarc=pass. If dmarc=fail shows up alongside passing SPF and DKIM, you have an alignment problem — the From: domain doesn't match the authenticating domain.
Common mistakes that quietly destroy deliverability
1. Two SPF records (the most frequent bug)
Adding a new sender by appending a second TXT record starting withv=spf1. RFC 7208 says exactly one. Two = permerror. The fix: merge the includes into a single record.
2. SPF lookup count over 10
Common with stacks that use Google + Salesforce + a marketing tool + a sender. Run an SPF flattening tool (dmarcian SPF Surveyor is free) and merge nested includes if you go over.
3. DMARC at p=reject on day one
Bounces every legitimate sender you forgot to align. Always start at p=noneand progress.
4. Missing rua= in DMARC
Without an aggregate report address, you have no visibility into what's actually happening. rua reports tell you every IP claiming to be you and whether they aligned. Free parsers (postmark's, dmarcian's) make the XML readable.
5. Trusting the platform UI over DNS
Vendor dashboards report cached state. dig tells you what receivers will see right now. When in doubt, dig.
What modern receivers actually require (2024+ rules)
Google and Yahoo's February 2024 sender requirements made the implicit explicit. For senders pushing more than 5,000 messages/day to Gmail or Yahoo:
- SPF or DKIM must align with the
From:domain. - DMARC record must be present, even at
p=none. - One-click List-Unsubscribe header for marketing mail (
List-Unsubscribe-Post: List-Unsubscribe=One-Click). - Spam complaint rate under 0.3%; ideally under 0.1%.
Microsoft (Outlook / Office 365) followed the same pattern in 2025 with similar thresholds. Treat all four bullets as table stakes for any volume above 1,000/day.
How Sendr365 handles this
When you sign up and add a sending domain, we generate the right records, surface them on the senders page with one-click copy, and structurally lint your live DNS for duplicate SPF, duplicate DMARC, and lookup-count blow-ups before you ever send a message. The poller re-checks every 3 minutes during onboarding so the transition from pending to active is automatic.
DKIM is signed upstream with a Resend selector — so the only DKIM record you publish is the one we tell you about, no legacy junk. DMARC alignment is checked on every send and surfaced if anything drifts.
If you'd rather wire it up by hand, the developer docs have the exact records, header values, and verification commands. Either way, you should be at dmarc=passwithin an hour of starting.
The 10-minute checklist
- Publish one SPF record with all senders included; verify with
dig. - Publish your sending platform's DKIM selector; verify it resolves.
- Publish DMARC at
p=nonewith a workingrua=address. - Send a test to Gmail, view headers, confirm
dkim=pass spf=pass dmarc=pass. - Wait 2-4 weeks, read the DMARC reports, fix any unaligned senders.
- Move to
p=quarantine; pct=25, then 100, thenp=reject.
That's it. Your domain is now properly authenticated, the major receivers will trust your mail, and anyone trying to spoof you gets bounced at the door.
