How to check SPF, DKIM, and DMARC for a domain
SPF, DKIM, and DMARC are three DNS records that decide whether your email is trusted or dropped in spam. This guide shows you how to read all three with dig, interpret the output, and fix the misconfigurations that hurt deliverability.
Short answer: query the domain's DNS TXT records — SPF lives at the root (example.com), DMARC at _dmarc.example.com, and DKIM at <selector>._domainkey.example.com. Each record type and the exact commands are below.
What SPF, DKIM, and DMARC do
| Record | Answers the question | DNS location |
|---|---|---|
| SPF | Which servers are allowed to send mail for this domain? | example.com (TXT) |
| DKIM | Was this message signed by the domain, and is it unaltered? | <selector>._domainkey.example.com (TXT) |
| DMARC | What should a receiver do when SPF/DKIM don't align with the From domain? | _dmarc.example.com (TXT) |
Step 1 — Check the SPF record
SPF is a single TXT record at the domain root that starts with v=spf1:
$ dig +short TXT example.com "v=spf1 include:_spf.google.com ~all"
Read it right to left at the end:
-all— hard fail: reject anything not listed. Strongest.~all— soft fail: accept but mark suspicious. Most common.?all/+all— neutral / allow-all: effectively no protection.
Watch the 10-lookup limit. SPF allows at most 10 DNS lookups (each include:, a, mx counts). Exceed it and SPF returns permerror and silently stops working — a very common cause of sudden deliverability drops.
Step 2 — Check the DMARC record
DMARC is a TXT record at the _dmarc subdomain:
$ dig +short TXT _dmarc.example.com "v=DMARC1; p=reject; rua=mailto:dmarc@example.com; adkim=s; aspf=s"
p=none— monitor only, no enforcement. Reporting starting point.p=quarantine— send failing mail to spam.p=reject— reject failing mail outright. The goal state.rua=— where aggregate reports are sent (turn these on early).
If this record is missing entirely, the domain has no DMARC policy and is trivially spoofable.
Step 3 — Check the DKIM record
DKIM is the tricky one: the record lives under a selector you can't guess from DNS. Find it in the DKIM-Signature header of a real message the domain sent, in the s= tag:
DKIM-Signature: v=1; a=rsa-sha256; d=example.com; s=selector1; ...
Then query that selector:
$ dig +short TXT selector1._domainkey.example.com "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQ..."
A present p= public key means DKIM is published. An empty p= means the key was revoked.
How to read the results together
DMARC only passes when SPF or DKIM passes and aligns with the visible From domain. The most common reasons legitimate mail still lands in spam:
- DMARC is stuck at
p=none, so receivers apply no trust signal. - A third-party sender (newsletter, CRM, invoicing) isn't in SPF or isn't DKIM-signing with your domain, so it fails alignment.
- SPF quietly broke by exceeding the 10-lookup limit.
- DKIM selector rotated and the old key was removed while messages still reference it.
Doing this for many domains, repeatedly? Checking three records by hand is fine once. Across a fleet, and after every provider change, it doesn't scale.
Automate it with Wildbox
Wildbox is a self-hosted, open-source security platform. Its email security analyzer resolves SPF, DKIM, and DMARC for a domain in one pass, flags a permissive +all or an unenforced p=none, checks the sending IP against public DNS blocklists (DNSBL), and can run on a schedule so you catch regressions instead of discovering them from a bounce. It runs on your own infrastructure — the domains and results never leave your environment.
FAQ
Why do my emails still go to spam even though SPF passes?
SPF passing isn't enough. Receivers increasingly require DMARC alignment — the visible From domain must match the domain validated by SPF or DKIM. A message can pass raw SPF for the sending server yet fail DMARC because the From domain doesn't align. Missing DKIM and a p=none policy weaken this further.
What does DMARC p=none mean?
Monitor-only: the receiver enforces nothing and just reports. It's the right first step to collect rua aggregate reports, but it offers no anti-spoofing protection. Once your legitimate senders pass, move to p=quarantine, then p=reject.
How do I find the DKIM selector for a domain?
You can't enumerate selectors from DNS. Read the DKIM-Signature header of a message the domain actually sent and take the s= value, then query <selector>._domainkey.<domain>.
How often should I check?
After any mail-provider or sending-service change, and then continuously — records drift as senders are added, and the SPF lookup limit is easy to exceed over time.
Related
- JWT Decoder — decode and inspect a JSON Web Token in your browser
- Wildbox documentation — deploy the full platform with Docker Compose