DMARC Record Generator
Compose or check DMARC, SPF and DKIM records with the risky terms named and the SPF lookup count shown — on this device, with nothing resolved.
The domain the record protects, for example example.com.
v=DMARC1; p=none
No domain has been entered yet, so there is no name to publish the record at. A record lives at a name derived from the domain it protects. Enter the domain, for example example.com.
This page never queries DNS. It reads only the text in front of it.
| Tag | Value |
|---|---|
| v | DMARC1 |
| p | none |
- Note
7 tags are left out because they are already the default in RFC 7489 §6.3: sp (subdomains follow "p="), adkim (relaxed), aspf (relaxed), fo (0), pct (100), ri (86400), rf (afrf). A shorter record says exactly the same thing to a receiver. Add any of them explicitly if your change process prefers it.
RFC 7489 §6.3
- Warning
"p=none" asks receivers to take no action of their own. RFC 7489 §6.3 defines it as the Domain Owner requesting no specific handling, so it is a monitoring position: reports arrive, nothing is quarantined or rejected. Move to quarantine and then reject once the reports show your legitimate mail passing.
RFC 7489 §6.3
- Warning
There is no "rua=" tag, so no aggregate reports are requested. RFC 7489 §6.3 makes rua the address receivers send their daily aggregate feedback to, and without it there is no way to see who is sending as this domain. Add "rua=mailto:dmarc@example.com" before tightening the policy.
RFC 7489 §6.3
- Note
7 tags are absent, so RFC 7489 §6.3's default applies: sp (subdomains follow "p="), pct (100), adkim (r, relaxed), aspf (r, relaxed), fo (0), ri (86400 seconds), rf (afrf). Absent and explicitly-default mean the same thing to a receiver. Add them only if you want the record to state them.
RFC 7489 §6.3
Press ? for shortcuts · Copy the record, then copy the owner name — they go in separate zone fields.
Do it offline:$ dig _dmarc.google.com TXT +short
How to use it
- Choose the record type. In Check mode it is read from the version tag of what you paste and shown as a badge you can override; in Build mode you pick it yourself.
- Fill in the form, or paste a record. The domain and, for DKIM, the selector build the owner name, never the record text.
- Read the findings. Each names the clause behind it, and the table lists every term in the order written.
- Copy the two halves separately: the record goes in a TXT record's value, the owner name — _dmarc.example.com, or selector._domainkey.example.com — in its name.
Pick a record type, then fill in the form or paste what your zone already holds. DMARC, SPF and DKIM each get their own grammar check: every term and tag is listed beside the clause it comes from, the SPF terms that cost a lookup are counted against the limit of ten, and the owner name to publish at is spelled out. No query is sent.
Examples
DMARC · p=none · rua=mailto:dmarc@example.comv=DMARC1; p=none; rua=mailto:dmarc@example.comThe starting position for a domain that has never published DMARC: report on everything, act on nothing. Seven tags are left out because the form holds RFC 7489 §6.3's default for each. The owner name, _dmarc.example.com, is a separate field.
v=spf1 include:_spf.google.com include:spf.protection.outlook.com include:mail.zendesk.com include:_spf.salesforce.com include:sendgrid.net include:servers.mcsv.net include:spf.mandrillapp.com include:_spf.intercom.io include:mailgun.org a mx ~all11 of 10 DNS-lookup terms usedNine include terms plus a and mx come to eleven, and RFC 7208 §4.6.4 caps an evaluation at ten. Past the cap an evaluator returns permerror, failing every message rather than the doubtful ones. The real total is higher still if an included domain has its own.
v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyqO5jkF4mt9ttdAYEU0AENE6pKh2M7zoy2Qrmv5ZcCOD8KfM9hT/Q/vKR1es5NkMVvMpx9jmJzfWWMXlRkXT2tVArDuB0I0J0KDbGJEZV374yRGeg6LVgvzQ14JtwBF/2IqdgWGb7N4zNRjdS4QpQh+Hmtitepv1Nkp+KHUDaFYN35tMC+yMNbZfFn8EUmDdwFV6orQEuk0D3Boshwh1LdY6PQPbMWmzJIIvVAn3GXQR16iBER0pjYqmPUx7qeFi6VtEYAs+o/jDykXXaHjfEhJRskMTmEj/4bfnfG8qP1c0917yh2qOQ8FJsjV9Fi2pr9IcLAeytBGzHUroyH/lYQIDAQABRSA, 2048-bit key · 410 characters, published as 2 quoted stringsThe key size appears nowhere in the record; it is read out of the base64 by walking the key structure to the RSA modulus and measuring it. Nothing here is secret, and the split into two strings is forced by the length.
v=spf1 +allThis record ends in "+all", which tells receivers that every host on the internet is authorised to send as this domain. RFC 7208 §5.1 makes "all" always match, so the "+" qualifier passes anything the earlier terms did not already cover. Use "-all" to state that nothing else is authorised, or "~all" while you are still finding senders.Syntactically perfect and operationally the worst record you can publish, which is why it is a warning and not an error — the grammar has nothing to object to. It usually arrives by copying a placeholder.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
Past 255 characters a record is published as several strings
RFC 1035 §3.3.14 gives a character-string one length byte, so 255 is the ceiling for a string — not for the record, which may hold several that a reader joins with nothing between them. A 2048-bit key record runs to 410 characters, so it ships as two.
-all, ~all and ?all are three different requests
The qualifier on the final all mechanism is an SPF record's whole policy statement. A minus asks for fail on anything not already matched, a tilde asks for softfail — failed, but do not reject on that alone — and a question mark asks for neutral, which RFC 7208 §5.1 treats as no opinion.
p=none is a monitoring position, and pct only samples the policy
A record with p=none asks for reports and no handling change, so it shows who sends as your domain before you decide. The pct tag looks like a way to ramp reporting up gradually; RFC 7489 §6.3 makes it a sampling rate for the policy alone, and the unsampled remainder gets the next weaker policy.
Lookup terms are counted here, never resolved
The figure printed here counts the include, a, mx, ptr, exists and redirect terms in the text in front of it. No name is queried, so terms pulled in by an included domain are invisible: a record showing four can still exceed ten in a real evaluation.
Common errors
This record has no "p=" tag. RFC 7489 §6.3 requires a policy on a DMARC policy record, and §6.6.3 ignores a record without one. Add "p=none" to start in monitoring mode, or "p=quarantine" / "p=reject" to ask receivers to act. A record carrying only "v=DMARC1" is the separate third-party reporting authorisation of §7.1, published at a different name.- The commonest way a DMARC record does nothing: it parses, it looks published, and a receiver discards it anyway.
"pct=101" is outside the range this tag allows. RFC 7489 §6.3 defines pct as a percentage from 0 to 100 of the messages the policy is applied to. Use a value from 0 to 100.- Out-of-range values are rejected rather than clamped: reading 101 as 100 would hide a typo where 10 and 100 separate a trial from full enforcement.
The "p=" value is not valid base64. RFC 6376 §3.6.1 stores the public key as base64, which uses only A-Z, a-z, 0-9, "+", "/" and trailing "=" padding — whitespace inside the value is allowed and ignored. Re-copy the key from the key file, taking the lines between the BEGIN and END markers.- Nearly always a copy that swept up the BEGIN and END marker lines. Line breaks inside the value are legal and stripped before the key is read, so wrapping is not the cause.
"bogus" is not one of the mechanisms defined by RFC 7208 §5 (all, include, a, mx, ptr, ip4, ip6, exists). An unrecognised mechanism is a syntax error rather than something an evaluator can skip. Correct the spelling, or write it as a "name=value" modifier if that is what it is.- SPF has no room for an unknown mechanism: RFC 7208 §12 lists eight and stops. Unknown modifiers are the opposite case — written name=value, and skipped by evaluators that do not know them.
FAQ
Does this page look up my domain's records?
No. It reads the text you give it and nothing else — no DNS query, no API call, no upload — so it cannot tell you what is currently published. Read the live TXT value with a DNS client such as dig, then bring it back here.
Why does it say 10 lookups when my record has fewer includes?
Because a, mx, ptr, exists and redirect count against the same limit — RFC 7208 §4.6.4 counts terms that cause a lookup, so four includes plus a and mx is already six. The reverse surprise matters more: an included domain's terms add to the total, unseen here.
Do I paste my DKIM private key here?
Never — not here and not into any web page. The p= tag holds the public half of the pair, which is why it is safe to publish in DNS for the world to read; the private half stays on the machine that signs your mail. This page makes no keys either — that is openssl's job.
Keyboard shortcuts
- ⌘/Ctrl + C
- With nothing selected, copies the record; a live selection copies itself instead.
- ⌘/Ctrl + Shift + C
- Copies the findings list, whatever the selection.
- ⌘/Ctrl + S
- Downloads the state as a reopenable .json file, overriding the browser dialog.
- ? or ⌘/Ctrl + /
- Opens the shortcut help overlay.
- Esc
- Closes the topmost overlay and restores focus.