GRC Oversight

SPF, DKIM & DMARC, in plain language

Three DNS records decide whether mail claiming to be from your domain is trustworthy. Here's what each one actually does, how they fit together, and the one DMARC setting people most often get wrong.

Why this matters

Anyone can say they're you, unless your DNS says otherwise

Email has no built-in sender verification. Without these records, anyone can put your domain in the 'From' field of an email. Mailbox providers (Gmail, Outlook, etc.) look at SPF, DKIM, and DMARC to decide whether to trust that claim, flag the message as suspicious, or reject it outright.

Record 1

SPF: which servers are allowed to send

Sender Policy Framework is a TXT record at your domain's apex that lists the mail servers authorized to send on your behalf.

What it looks like
A TXT record starting with v=spf1, e.g. v=spf1 include:_spf.google.com ~all. This says "trust Google Workspace's servers; be cautious about anything else."
What it checks
The receiving mail server compares the IP address the message actually came from against the list your SPF record authorizes. If it isn't on the list, that's a signal the message may be spoofed.
What it doesn't do
SPF only validates the envelope sender's server, not the human-visible 'From' address, and it breaks when mail is forwarded (the forwarding server isn't on your list). That's part of why DKIM and DMARC exist alongside it.
Record 2

DKIM: a cryptographic signature on the message

DomainKeys Identified Mail signs outgoing mail with a private key; the matching public key is published in DNS so receivers can verify the signature wasn't tampered with.

Where the key lives
At <selector>._domainkey.<yourdomain>, a TXT record. The "selector" is a name your mail provider chooses (e.g. google, s1, k1), so there's no single fixed location the way there is for SPF or DMARC.
Why selectors matter
Because the selector is provider-chosen and not listed anywhere else in public DNS, nobody outside your mail provider can guess it or enumerate it: you have to already know it (your provider's setup docs will tell you) to look up the record at all.
What a valid record needs
It should start with v=DKIM1 and include a p= tag holding the public key. A record with an empty p= tag means the key has been revoked: mail signed with the old key will now fail verification.
What it proves
That the message body and headers weren't altered in transit, and that whoever holds the private key (your mail provider, on your behalf) actually sent it. It doesn't, on its own, say anything about who's authorized to use that key.
Record 3

DMARC: the policy that ties SPF and DKIM together

Domain-based Message Authentication, Reporting & Conformance is a TXT record at _dmarc.<yourdomain> that tells receivers what to do when a message fails SPF and DKIM alignment, and where to send reports about it.

What it looks like
A TXT record starting with v=DMARC1, with a p= tag set to none, quarantine, or reject.
p=none: monitor only
Tells receivers to apply no special treatment to messages that fail (deliver them as normal) but, if rua= is configured, send aggregate reports back to you about who's sending mail as your domain and whether it's passing. This is a visibility mode, not protection: a spoofed email that fails SPF/DKIM still lands in the recipient's inbox exactly as if DMARC didn't exist.
p=quarantine
Asks receivers to treat failing messages with suspicion (typically routing them to spam/junk) rather than blocking them outright.
p=reject
Asks receivers to refuse failing messages outright. This is the only setting that actually stops spoofed mail from being delivered.

The standard rollout path is p=none first (watch the reports, confirm your legitimate senders all pass) and then tighten to p=quarantine and eventually p=reject once you're confident nothing legitimate will be blocked.

What our scanner flags

Exactly what the DNS check looks at

Grounded in the scanner's actual detection logic (src/lib/scanner/dns.ts), not a general description of DMARC.

  • No SPF (v=spf1 TXT record) found at the apex domain: flagged medium severity.
  • No DMARC record (v=DMARC1 TXT at _dmarc.<domain>) found: flagged medium severity.
  • DMARC record present but its policy is p=none: flagged low severity as "DMARC policy is monitor-only," with remediation to move to p=quarantine then p=reject once aligned. This is the exact p=none behavior described above: published, but not enforcing.
  • DKIM is opt-in: by default, no selector is checked (selectors can't be enumerated from public DNS, so there's nothing to look up without knowing the name). If you supply a selector on the scan form, the scanner performs one additional passive TXT lookup at <selector>._domainkey.<domain> and reports whether a record exists, starts with v=DKIM1, and carries a non-empty public key.
Try it

Check your own domain's records

Our free scanner checks SPF, DMARC, CAA, and DNSSEC for any public domain, and can check a DKIM selector too if you know it. Passive only: the same DNS lookups anyone can run, nothing sent to the target site itself.

Run a free scan of your domain

Get a guided demo, or start by scanning any domain for free.