isitdns? wiki/Records/MX, SPF, DKIM, DMARC: the four mail records
Records

MX, SPF, DKIM, DMARC: the four mail records

What it holds#

RecordLives atWhat it answers
MXexample.com (apex, or any name)Where inbound mail for @example.com goes
SPF (a TXT)example.com (apex)Which IPs are authorized to send as @example.com
DKIM (a TXT)<selector>._domainkey.example.comThe public key that verifies signatures on outbound mail
DMARC (a TXT)_dmarc.example.comWhat a receiver does when no SPF or DKIM pass aligns with the visible From: (RFC 9989 §4.1)

Each one without the others is brittle.

Defined in RFC 1035 (MX, sender behavior in RFC 5321 §5.1), RFC 7208 (SPF), RFC 6376 (DKIM), and RFC 9989 (DMARC, obsoletes RFC 7489).

When to use it#

  1. The domain receives mail: publish MX.
  2. The domain sends mail: publish SPF, DKIM, and DMARC so receivers can tell your mail from forgeries.
  3. The domain never touches mail: publish a null MX (MX 0 ., RFC 7505), an SPF of v=spf1 -all, and a DMARC of p=reject. A registered domain with no mail records is still a forgery target.

When not to use it#

  • No DKIM key on a receive-only domain. There is no outbound mail to sign, so there is no key to publish.
  • Never a second SPF record at the same name. Two SPF TXT records is a permerror (RFC 7208 §4.5); merge the mechanisms into one record.
  • Not p=reject on day one. Publish p=none with rua= set, read the aggregate reports until alignment is confirmed, then promote.

dig example#

Asks a domain apex for its published text, which is where SPF lives.

 dig @1.1.1.1 example.com TXT
; <<>> DiG 9.20.11-0ubuntu0.2-Ubuntu <<>> @1.1.1.1 example.com TXT
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22845
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;example.com. IN TXT
;; ANSWER SECTION:
example.com. 300 IN TXT "v=spf1 -all"
example.com. 300 IN TXT "_k2n1y4vw3qtb4skdx9e7dxt97qrmmq9"
;; Query time: 33 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Mon Sep 14 17:44:03 CDT 2026
;; MSG SIZE rcvd: 109

GO NOERROR and a string starting v=spf1

NO GO no v=spf1 string, which means the domain publishes no SPF record. DMARC is a separate lookup at _dmarc

run this query in the dig tool →

what each part of this output means →

MX, SPF, and DMARC can all be checked blind in one paste:

dig @1.1.1.1 cloudflare.com MX +short
dig @1.1.1.1 cloudflare.com TXT +short | grep v=spf1
dig @1.1.1.1 _dmarc.cloudflare.com TXT +short
5 mxa-canary.global.inbound.cf-emailsecurity.net.
5 mxb-canary.global.inbound.cf-emailsecurity.net.
10 mxa.global.inbound.cf-emailsecurity.net.
10 mxb.global.inbound.cf-emailsecurity.net.
"v=spf1 ip4:199.15.212.0/22 ip4:173.245.48.0/20 include:_spf.google.com include:spf1.mcsv.net include:spf.mandrillapp.com include:mail.zendesk.com include:stspg-customer.com include:_spf.salesforce.com -all"
"v=DMARC1; p=reject; sp=reject; adkim=r; aspf=r; pct=100; rua=mailto:<token>@dmarc-reports.cloudflare.net,mailto:rua@cloudflare.com"

An empty answer on the _dmarc. line means no DMARC record is published. The MX preference number, not the answer order, decides which server a sender tries first.

DKIM needs the selector from a received message's DKIM-Signature: header, so it cannot be queried blind:

dig @1.1.1.1 protonmail._domainkey.proton.me TXT +short
protonmail.domainkey.drfeyjwh4gwlal4e2rhajsytrp6auv2nhenecpzigu7muak6lw6ya.domains.proton.ch.
"v=DKIM1;k=rsa;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn46zCm3zHBmS
1zePKxA+RIXw41Nu6l91NpLLBnWnrcZ35H/843XNWPZEQ0OgGwx/yqTXETMLXIDjGEWlK1E1
mpdguqu+3s7SuIHoo5+i6mgyxJguljkwc3dk8ojnJ6VVUPnDh5GJArkAhXxEb1aOK1BVGM0y
DlmYdmaOfd48qcx5iODP/MFc8pivfxEXTIL+aUz"
"7+X69lMiwUSHpWYL3/a5X3nLD0zEntxv08xs8J/rpuRg4v+OXEOhcNvhkeiRZqJBdpJTkoEZ
fGvdTct+U0YYC69NW0ClUcKio2uDPmxU1xvfvHbSTW2gHYk8RpYZaxLACULdMo+Vt4Na/oIR
+swIDAQAB;"

The first line is a CNAME into Proton's own zone, so Proton can rotate the key without touching proton.me. The key exceeds the 255-byte TXT string limit and is split into two quoted strings, concatenated before use (RFC 6376 §3.6.2.2).

Gotchas#

  • MX targets must be A/AAAA, never a CNAME (RFC 2181 §10.3).
  • No MX does not stop mail. Senders fall back to an implicit MX at the domain's A/AAAA (RFC 5321 §5.1); publish a null MX (RFC 7505) if the domain sends no mail at all.
  • SPF checks the envelope MAIL FROM, not the visible From: header. A bounce with an empty MAIL FROM is checked as postmaster@<HELO hostname> instead (RFC 7208 §2.4).
  • SPF caps DNS lookups at 10 per evaluation; include: sprawl past the cap is a permerror (RFC 7208 §4.6.4).
  • An empty DKIM p= is a revoked key, not a broken record (RFC 6376 §3.6.1).
  • DMARC covers your exact domain and its subdomains only. Lookalike domains (examp1e.com) are outside its reach.
  • pct= is removed from the current DMARC spec (RFC 9989 Appendix A.6); records in the wild still carry it.

See also#