Email Authentication, End to End: SPF, DKIM & DMARC With Real Config
Every email you send makes a claim: “I’m allowed to send on behalf of this domain.” SPF, DKIM, and DMARC are the three DNS records that let receiving servers check that claim. Get them right and your mail lands in the inbox; get them wrong — or leave them out — and Gmail, Yahoo, and Outlook increasingly send it to spam or reject it outright.
Since 2024, Gmail and Yahoo require SPF, DKIM, and a DMARC policy for bulk senders. This is the practical, copy-paste guide to setting up all three correctly, verifying them from the command line, and rolling out a DMARC policy without breaking your existing mail.
If you want the conceptual background on each one first, see What is DKIM?, What is an SPF record?, and What is DMARC?. This post is the hands-on companion to those three.
The 90-second mental model
The three records answer three different questions about a message:
- SPF — “Is this server allowed to send for this domain?” A DNS
TXTrecord listing the servers/services authorized to send. Checked against the envelope-from (Return-Path), not the visible From:. - DKIM — “Was this message actually authorized by the domain, and did it arrive unmodified?” The sender cryptographically signs each message; the public key lives in DNS. A valid signature proves authenticity and integrity.
- DMARC — “What should I do if SPF or DKIM fails, and where do I report it?” A policy record that ties SPF and DKIM to the visible From: domain (this tie is called alignment), tells receivers whether to quarantine or reject failures, and requests reports.
SPF and DKIM do the checking; DMARC turns those checks into a policy and gives you visibility. You need all three.
SPF: authorize your senders
SPF is a single TXT record at the domain that appears in your envelope-from. If you send through MailerToGo from mtg.yourdomain.com:
mtg.yourdomain.com. TXT "v=spf1 include:_spf.mailertogo.net ~all"
include:_spf.mailertogo.netpulls in MailerToGo’s authorized sending IPs (managed and kept current by us — you never hardcode IPs).~allis a softfail (mark-but-accept unauthorized senders); tighten to-all(hardfail) once you’re confident every legitimate sender is listed.
Two rules that trip people up:
- One SPF record per domain. Never publish two
v=spf1records on the same name — that’s a permerror and SPF fails. Merge them into one:"v=spf1 include:_spf.mailertogo.net include:_spf.google.com ~all". - The 10-lookup limit. SPF allows at most 10 DNS lookups while evaluating. Every
include:counts. Stacking your ESP, Google, Microsoft, and MailerToGo onto one root record can blow past it and break SPF for everything — which is a big reason to send app mail from a dedicated subdomain. (See Why MailerToGo sends from mtg.yourdomain.com.)
DKIM: sign every message
DKIM signs each message with a private key; receivers fetch the matching public key from DNS. With MailerToGo you don’t generate or paste keys — you publish a CNAME that points a per-account selector at our key, and we rotate the underlying key for you:
; Selector is specific to your account — use the exact value from your dashboard
mtg1._domainkey.mtg.yourdomain.com. CNAME mtg1.dkim.mailertogo.net.
Because it’s a CNAME to a record we control, key rotation is automatic: when we roll the key, the published public key changes on our side and your DNS needs no edits. If you ever inspect the resolved record, you’ll see a standard DKIM public key:
mtg1._domainkey.mtg.yourdomain.com. TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSq...QAB"
A valid DKIM signature is also what makes your mail survive forwarding, where SPF often breaks — so DKIM is the more durable of the two authentication signals.
DMARC: set a policy and get reports
DMARC lives at a fixed name, _dmarc.<domain>, and ties SPF/DKIM results to the visible From: domain. Start in monitor mode so you learn what’s actually sending before you enforce anything:
_dmarc.yourdomain.com. TXT "v=DMARC1; p=none; rua=mailto:dmarc-reports@yourdomain.com; fo=1; adkim=s; aspf=s"
Tag by tag:
p=none— monitor only; take no action on failures (yet).rua=mailto:...— send aggregate reports here (daily XML summaries of who’s sending as you). This is the whole point of starting atnone— you get visibility with zero risk.fo=1— request failure details when either SPF or DKIM fails.adkim=s/aspf=s— strict alignment (the signing/envelope domain must match the From: domain exactly). Use relaxed (r, the default) if you sign with a parent domain.- Add
sp=to set a separate policy for subdomains if you need one.
DMARC alignment is the subtle part: it’s not enough for SPF or DKIM to pass — the domain they pass for must align with the domain in the visible From:. This is why sending architecture matters, and why a subdomain that you fully control makes alignment straightforward.
Verify everything from the command line
Never assume a record is live — check it. dig (or nslookup on Windows) shows you exactly what resolvers see:
# SPF — expect a single v=spf1 line
dig +short TXT mtg.yourdomain.com
# DKIM — follow the CNAME to the published key
dig +short CNAME mtg1._domainkey.mtg.yourdomain.com
dig +short TXT mtg1._domainkey.mtg.yourdomain.com
# DMARC — always at _dmarc.<domain>
dig +short TXT _dmarc.yourdomain.com
Then send yourself a real message and read the receipts. In Gmail, open the message → ⋮ → Show original. You want to see:
SPF: PASS with domain mtg.yourdomain.com
DKIM: PASS with domain mtg.yourdomain.com
DMARC: PASS
If all three say PASS with an aligned domain, you’re done.
Roll out DMARC enforcement without breaking mail
The mistake that takes down legitimate email is jumping straight to p=reject. Ramp instead, watching your rua reports at each step:
p=none— monitor for 1–2 weeks. Read the aggregate reports; confirm every legitimate sender is passing and aligned.p=quarantine; pct=25→ gradually raisepcttoward 100. Failures go to spam, not the void, so mistakes are recoverable.p=reject— full enforcement. Only get here once your reports are clean. This is the level Gmail/Yahoo reward and that stops exact-domain spoofing.
Common failures and what they mean
- SPF permerror / “too many DNS lookups” — you exceeded 10 lookups. Consolidate includes or move app mail to a subdomain.
- Two SPF records — merge into one
v=spf1string. - DKIM “body hash did not verify” — something modified the message in transit (a mailing list footer, a scanner). DKIM is working; the content changed after signing.
- DMARC fails though SPF/DKIM pass — an alignment problem: the passing domain doesn’t match the From: domain. Check that your envelope-from/DKIM domain and your From: share an organizational domain.
The short version, and how MailerToGo helps
SPF says who may send, DKIM proves the message is genuine and unmodified, and DMARC ties both to your visible domain and tells receivers what to do. Configure all three, verify with dig and Gmail’s Show original, and ramp DMARC from none → quarantine → reject.
With MailerToGo, the DKIM key and its rotation are handled for you, and your dashboard shows the exact SPF/DKIM/DMARC records to publish. If you use the delegated mtg.yourdomain.com subdomain, we publish and maintain all of them from a single NS record — no manual DNS at all. Prefer to own the records yourself? The manual subdomain setup guide walks through the application config (envelope-from vs. From:) step by step.
For the underlying standards, MailerToGo also maintains plain-English references for SPF, DKIM, DMARC, and how they fit together.