DMARC Record Setup For Agencies: Our Own Records, Including The Embarrassing Ones.

Seven domains we own, read live. Two enforce on only 5 percent of failing mail and one publishes a quarantine policy with no SPF at all.

Aditya Sharma·Updated ·10 min read

Short answer: dmarc record setup is a sequence, not a switch. Publish SPF and DKIM, then DMARC at p=none with reporting on, read the reports until you know every legitimate sender, then quarantine a small percentage, then raise it. Skipping to p=reject destroys legitimate mail. Stopping halfway leaves a record that reads like protection and is not.

Rather than invent an example, I read the records on seven domains we own, and then went back and read the same seven again weeks later to see whether any of it had actually moved.

What a real portfolio looks like mid-rollout

Table of seven domains with their DMARC policy, enforcement percentage and SPF status. sitea.example, siteb.example and sitec.example enforce p=reject at 100 percent. sited.example and sitee.example use p=quarantine with pct=5. sitef.example is p=none. siteg.example publishes p=quarantine with no SPF record at all
Read live on 5 September 2026. Three domains enforcing, two paused at five percent,

one monitoring, and one enforcing with only DKIM to align against. This is what a genuine rollout looks like partway through.*

DomainPolicyEnforced onReading
sitea.examplep=reject100%enforcing
siteb.examplep=reject100%enforcing, sends no mail
sitec.examplep=reject100%enforcing, sends no mail
sited.examplep=quarantinepct=595% of failing mail unaffected
sitee.examplep=quarantinepct=5same
sitef.examplep=nonen/amonitoring only
siteg.examplep=quarantine100%enforcing with only DKIM, no SPF

Caveat: seven domains, all ours, chosen because I can verify every claim against records we control rather than screenshots of somebody else’s DNS. It is not a claim about typical agency DMARC hygiene. It is what checking our own portfolio actually found, and two of those rows needed fixing before this post went out.

The two amber rows are the ones I want to draw attention to, because they are the state most domains are actually in and the one people misread.

p=quarantine sounds like enforcement. With pct=5, the policy applies to five percent of failing messages. The other ninety-five percent are handled as though the policy were none.

That is a correct, deliberate rollout step. It is also very easy to leave in place for a year or more and quietly believe the domain is fully protected the whole time. Ours genuinely have.

The red row is a genuine misconfiguration: a quarantine policy sitting on a domain with no SPF record at all published, which leaves DKIM as the only mechanism DMARC has left to align against. It is on the list, and it has been for a while now.

Re-read weeks later, and nothing moved at all

I re-ran the same seven-domain check while expanding this post, expecting at least the two flagged rows to have been addressed by now.

for d in sitea.example siteb.example sitec.example sited.example 
         sitee.example sitef.example siteg.example; do
  echo -n "$d: "; dig +short TXT "_dmarc.$d"
done

Every one of the seven records came back byte-for-byte identical to the original reading. The three p=reject domains still enforce fully. sitef.example still monitors only. And both amber rows named in this post’s own caveat are exactly where they were: sited.example and sitee.example still capped at pct=5, siteg.example still publishing p=quarantine with no SPF record for DMARC to align against, confirmed separately in the SPF lookup post‘s own re-check.

Zero drift is not, on its own, good news here. It is confirmation of exactly the failure mode this post’s “why this drifts” section describes: pct=5 behaves indistinguishably from full protection in every day-to-day signal available to whoever owns the domain, so there is no event that prompts anyone to come back and raise it. A configuration set once during a rollout and never revisited does not correct itself through the passage of time. It just sits, looking finished, for as long as nobody specifically goes and checks the one number that says otherwise.

Reading a DMARC record setup, tag by tag

Annotated breakdown of the sited.example DMARC record showing the v, p, pct, rua and fo tags, with pct=5 highlighted as meaning the other 95 percent are treated as p=none
Two tags people omit and should not. Without rua you receive no reports, so you are

enforcing blind. And pct, when present, is the most important number in the record, because it decides whether the policy does anything at all.*

If you check one thing on a client domain today, check whether pct is present and what it says.

The rollout, and the mistake at each step

Five-step DMARC rollout table. Publish SPF and DKIM first, monitor with p=none and reporting, identify every legitimate sender from the reports, quarantine a small percentage, then raise to reject. Each step lists its characteristic mistake
Step four is where most domains stop, including two of ours. It is a legitimate place

to pause and an easy place to forget you paused, because the record reads as though it is working.*

#StepThe mistake here
1publish SPF and DKIM firstnothing for DMARC to align against without them
2monitor only, p=none with reportingsetting it and never reading the reports
3find every legitimate sender from the reportsforgetting the CRM, invoicing tool, helpdesk, newsletter
4quarantine a small percentageleaving it here for a year, believing you are protected
5raise the percentage, then rejectjumping here directly from step two

Step three is the one that costs agencies real goodwill when skipped. The senders you forget are never the mail server. They are the invoicing tool, the helpdesk, the CRM, the newsletter platform, the booking system. Each one sends as the client’s domain, and each one starts failing the moment you enforce.

That is why p=none with rua exists. It generates the list for you, from real traffic, over a few weeks. There is no way to produce that list by thinking hard about it.

A tag pattern in our own records worth naming precisely

Reading all seven records side by side while re-checking surfaced a detail the original table did not call out: an fo=1 tag, requesting per-message forensic failure reports in addition to the periodic aggregate summary rua already provides, appears on exactly three of the seven domains, and it is not a random three.

sitea.example               fo: absent
siteb.example               fo: absent
sitec.example    fo: absent
sited.example               fo=1
sitee.example          fo=1
sitef.example                fo: absent
siteg.example             fo=1

fo=1 sits on sited.example, sitee.example and siteg.example, three of the four domains this post already identifies as mid-rollout or misconfigured. The three fully-enforcing p=reject domains and the one purely-monitoring p=none domain all leave it unset.

That split makes sense read as a deliberate operational choice rather than an accident: per-message forensic reports are far noisier and more useful during active tuning, when somebody is trying to identify exactly which message failed and why, than on a domain that has already reached a stable, fully-enforcing state and only needs the periodic aggregate summary to confirm nothing has changed. Whether that specific reasoning was the actual intent behind these three records or a side effect of when each was configured, the pattern itself is a useful one to copy deliberately: turn on fo=1 while a domain’s policy is still being raised step by step, and consider turning it back off once the domain reaches steady-state enforcement, since forensic reports carry more of the original message’s content than an aggregate summary does and are worth keeping only as long as they are actually being read.

The DKIM half, briefly

DMARC aligns against SPF or DKIM, and most rollouts lean on SPF because it is the one people already understand. DKIM is worth the extra hour for one reason: it survives forwarding.

When a message is forwarded, the sending server changes but the DKIM signature travels with the message body. SPF breaks in that situation and DKIM does not. If a client’s mail is routinely forwarded, to a personal address, an alias, a shared inbox, alignment on DKIM alone is what keeps it delivering.

Check whether a selector is publishing at all:

dig +short TXT google._domainkey.example.com | head -c 120
dig +short TXT selector1._domainkey.example.com | head -c 120

Selector names vary by provider, which is the genuinely annoying part. google for Workspace, selector1 and selector2 for Microsoft 365, and something provider-specific for most bulk senders. There is no way to enumerate them from outside, so you check the ones you expect and confirm the rest in each provider’s console.

Checking a portfolio

Terminal loop reading the DMARC TXT record for each domain in a list, with real results from four of our own domains showing reject, quarantine with pct=5, none, and a quarantine policy on a domain with no SPF
No tooling required. It is a TXT lookup on a fixed subdomain, so a whole portfolio

takes seconds.*

Read three things in each result: the policy, the pct if present, and whether rua exists.

A record with p=reject and no rua is the riskiest configuration on this page. It is enforcing, and nobody can see what it is refusing.

What it protects, and what it does not

Worth being precise here, because DMARC gets oversold.

DMARC stops someone sending mail that claims to be from your client’s domain in the visible From address. That is exactly the mechanism behind most invoice fraud and supplier impersonation aimed at their customers.

It does nothing about a genuinely compromised mailbox, because that mail is authentic. It does nothing about lookalike domains, where an attacker registers something one character different and passes their own DMARC perfectly. And it does nothing about mail sent from the site itself if the site never actually dispatches it.

So it is worth doing and it is not a mail security strategy on its own. Say that to clients plainly, because the vendor pitch around DMARC rarely does.

Why this drifts

DMARC does not fail loudly. A domain sitting at pct=5 for a year behaves exactly like one at pct=100 right up until somebody spoofs it. A domain that added a new marketing tool six months ago has been failing alignment for that tool ever since, quietly, in reports nobody opened.

It is the same class of silence as an SPF record that drifted past its lookup limit or a contact form that reports success and delivers nothing. Mail problems almost never announce themselves at the sending end.

Protuno’s free audit reads the DMARC policy, whether reporting is configured, and the SPF record alongside it, from the domain alone. That is how the table above was built. Straight with you as on every post here: Echo, the Marketing agent that would watch these records for drift, is built and named but not live yet.

One note on selling this, because it is genuinely hard to charge for. DMARC produces no visible improvement. Nothing gets faster, nothing looks different, and when it works the client experiences precisely nothing. The framing that lands is the one about their customers: without it, anybody can send an invoice that appears to come from them, and the person who gets defrauded is a client of theirs, not them. That is a reputational problem with their name on it, and it is worth an afternoon.

Run the loop on your client domains this afternoon. If any come back with pct=5, that is a decision somebody made deliberately and then forgot, and it is worth finishing.

Ours included. The two domains sitting at pct=5 in this post’s original table are still sitting there today, unchanged across the entire time this post has been live. Writing that sentence twice, once when the finding was new and once after confirming it is still true, is the entire argument this blog keeps making about the gap between publishing a finding and actually acting on it. The record is correct either way. The honesty is in saying so.

Comments