What no DMARC record found means
A free checker or a receiving mail server tells you "no DMARC record found" for your domain. The receiver looked up a TXT record at _dmarc.<your-domain> and got an empty or non-existent answer, then walked up the DNS tree without finding a record at the organizational domain either. Under RFC 9989 (DMARCbis), when policy discovery returns no record the receiver does not apply the DMARC mechanism to the message. There is no policy to enforce, no quarantine or reject on DMARC grounds, and no aggregate or failure reports, because nothing tells receivers where to send them.
This is a different state from a published p=none policy. With p=none the record exists and DMARC is applied, the policy just requests no disposition change (RFC 9989 §4.7). The owner still receives reports. With no record at all, the owner gets nothing. If you want visibility into who sends as your domain, "no record" is the state you have to leave first.
Confirm the record really is absent
DMARC always lives at the _dmarc label of the domain in the visible From: header (RFC 9989 §4.10), never at the apex. Query that exact name:
dig TXT _dmarc.example.com +short
Query public resolvers directly to bypass a possibly stale local cache and see what other resolvers return:
dig TXT _dmarc.example.com @1.1.1.1 +short
dig TXT _dmarc.example.com @8.8.8.8 +short
A genuine "no record" returns empty output. A valid record returns one quoted string beginning with v=DMARC1:
"v=DMARC1; p=none; rua=mailto:[email protected]"
On a Windows host without dig, use nslookup:
nslookup -type=TXT _dmarc.example.com 1.1.1.1
Rule out the false negatives
Before you conclude the record is missing, eliminate the lookups that look like "no record" but are really a query or publishing mistake.
You queried the apex, not _dmarc
A TXT lookup on the bare domain returns your SPF record and any verification strings, never DMARC. DMARC is only ever at the _dmarc subdomain. These are different names:
# SPF and other TXT live here (NOT where DMARC is found)
dig TXT example.com +short
# DMARC lives here
dig TXT _dmarc.example.com +short
A CNAME sits at _dmarc instead of a TXT record
Some DNS panels let you point _dmarc at another name with a CNAME. DMARC discovery looks for a TXT resource record. Check for a CNAME explicitly, then confirm you end on a TXT, not just a CNAME alias:
dig CNAME _dmarc.example.com +short
dig TXT _dmarc.example.com +short
If the final answer is a CNAME with no TXT at the target, receivers see no policy. Either publish the TXT directly at _dmarc, or make sure the CNAME target actually serves the v=DMARC1 TXT.
The record is split into multiple quoted strings
Long TXT values are sometimes stored as several quoted strings. DNS concatenates the strings with no separator (RFC 1035), so a stray space at the join corrupts the policy. Reassemble the value and inspect it. Separately, if a large TXT answer is truncated over UDP (the TC flag is set in the reply), force TCP so you read the full record:
dig TXT _dmarc.example.com +tcp +short
The reassembled value must read as one clean v=DMARC1; ... string with no doubled or missing spaces at the join.
Propagation has not finished
If you just published the record and a checker still reports nothing, it may have cached the previous negative answer for the duration of the _dmarc name's TTL. Query the authoritative answer with a trace, which follows delegations from the root and bypasses local caching:
dig TXT _dmarc.example.com +trace
If the authoritative server returns the record but a public resolver does not yet, you are waiting out a cached negative. Re-check after the TTL elapses.
The record is on the wrong subdomain
DMARC is evaluated against the domain in the From: header. If your mail sends as news.example.com but you published only at _dmarc.example.com, the subdomain has no direct record. Under RFC 9989 §4.10, when no record exists at _dmarc.news.example.com the receiver walks up the DNS tree and queries _dmarc.example.com at the organizational domain. That organizational record applies to subdomains unless it sets an sp= (subdomain policy) tag, which overrides p= for subdomains (RFC 9989 §4.7). Check both names if your sending From domain is a subdomain:
dig TXT _dmarc.news.example.com +short
dig TXT _dmarc.example.com +short
Organizational domain lookup and the tree walk
Under RFC 9989 (DMARCbis), a receiver that finds no record at the full From domain discovers the organizational domain with a DNS tree walk (RFC 9989 §4.10). It queries the _dmarc label at each parent in turn, climbing the label hierarchy until it finds a published policy or runs out of labels, and the first policy it finds applies. For a.b.c.d.example.com the tree walk lands on example.com. This also folds in policy at the public-suffix level, the role the experimental PSD DMARC of RFC 9091 used to play (RFC 9091 is now obsoleted by RFC 9989).
Historically, under RFC 7489 the organizational domain was computed with the Public Suffix List: count labels right to left, find the longest matching public suffix, and add one more label. The Public Suffix List is no longer part of the specification. For a flat domain the tree walk reaches the same answer, so for "no record found" the result is unchanged: publish a discoverable TXT at the _dmarc label of the domain you actually send from, or at its organizational domain, and confirm it resolves.
Publish a safe first record
Once you have confirmed the record is genuinely missing, publish a monitoring-mode policy. A p=none policy requests no disposition change (RFC 9989 §4.7), so it cannot break delivery, and it starts the flow of aggregate reports.
Create a TXT record:
-
Type:
TXT -
Name / host:
_dmarc(your DNS panel appends the domain; the full name is_dmarc.example.com) - Value: the policy string below
v=DMARC1; p=none; rua=mailto:[email protected]
v=DMARC1 is mandatory and must appear first. p=none is monitoring mode. rua=mailto:... is the address that receives aggregate report XML, which receivers SHOULD send once per day (RFC 9990 §3.1.4; the per-record ri interval tag was removed in DMARCbis). If that rua address is on a different organizational domain than the one publishing the policy, the receiving domain must publish an external authorization record or the report generator ignores the URI (RFC 9990 §4 says that where the algorithm fails to confirm the reporting was authorized by the Report Consumer, "the URI MUST be ignored by the Mail Receiver generating the report"). The verification query a receiver runs takes the form <policy-domain>._report._dmarc.<external-domain>, and the answer must contain v=DMARC1:
dig TXT example.com._report._dmarc.reports.vendor.net +short
The DMARC record generator builds a syntactically valid first policy and explains each tag, so you can paste a known-good value into DNS rather than hand-typing it.
Validate the fix
After publishing, wait at least one TTL, then confirm the record resolves from public resolvers:
dig TXT _dmarc.example.com @1.1.1.1 +short
dig TXT _dmarc.example.com @8.8.8.8 +short
You want exactly one quoted string beginning with v=DMARC1. Then run the domain through the free DMARC checker for a read-only snapshot of the published DMARC, SPF, and DKIM posture in one place. The checker reads the same live DNS a receiver would.
Once reports begin arriving (usually within a day), you can see every source sending as your domain before tightening the policy. For more on what those reports reveal, see how DMARCTrust turns DMARC aggregate reports into a per-source view.
Related fixes
- If a record exists but is stuck in monitoring mode, read DMARC policy not enabled.
- If a bounce reads 554 5.7.5, read permanent error evaluating DMARC policy.
- If a lookup intermittently fails rather than returns empty, read DMARC temperror and DNS timeouts.
- If the record exists but reports never arrive, read not receiving DMARC reports.
- If mail passes DMARC for the wrong reasons, read DMARC alignment issues.