Pre-Black Friday: 20% off, for as long as you stayEARLYBFon Solo and AgencyEnds Nov 28Start free

How-to guide

How to Set Up DMARC (Monitor, Align, Enforce)

Three stages, four DNS changes and the dig queries that prove each one worked. Then a list check before the first send.

Get your free API key →Free to start. No credit card. 1,000 records to spend whenever you like.

TL;DR

  • Publish one TXT record at _dmarc.yourdomain.com with p=none, wait for reports, fix every sender that fails alignment, then move to quarantine and reject.
  • The first record takes about 30 minutes. Enforcement takes 2 to 4 weeks of report data.
  • DMARC spends 0 LeadOcean records. The optional list check in Step 6 spends 25.

Prerequisites

  • Access to DNS for each sending domain.
  • A list of everything that sends mail as that domain: your mailbox provider, your sequencer, your CRM, billing and support tools.
  • dig (macOS and Linux ship it) or any online DNS lookup.
  • A mailbox for reports, for example dmarc@yourdomain.com, or a report-parsing service.
  • Optional, for Step 6: a LeadOcean key exported as $LEADOCEAN_API_KEY. The free plan works.

A message passes DMARC when SPF or DKIM passes and the passing domain matches the visible From domain (RFC 7489, September 2026). That match is called alignment. Passing SPF on a vendor's domain does not count.

Google lists SPF, DKIM and DMARC as requirements for bulk senders, and unauthenticated mail can be spam-foldered or rejected with a 5.7.26 error (Google sender guidelines, October 2026). For background see What Is DMARC?.

Step 1: Check what exists

Query the three records before you change anything. Replace acme.com with your domain.

bash
dig +short TXT acme.com | grep -i spf
dig +short TXT _dmarc.acme.com
dig +short TXT google._domainkey.acme.com   # use your DKIM selector

An empty answer for _dmarc means no policy is published. Receivers then apply none.

If SPF returns two v=spf1 lines, merge them into one. Two SPF records is a permanent error. SPF is also limited to 10 DNS lookups, so remove include: entries for tools you no longer use.

Step 2: Publish p=none with reporting

Add one TXT record. Host: _dmarc. Value:

text
v=DMARC1; p=none; rua=mailto:dmarc@acme.com; adkim=r; aspf=r
  • p=none asks receivers to take no action on failures. You are collecting data only.
  • rua is where aggregate reports go. Reports are XML, sent daily by large receivers.
  • adkim=r and aspf=r are relaxed alignment: a subdomain such as mail.acme.com aligns with acme.com. Relaxed is the default and the right start.

Confirm it is live:

bash
dig +short TXT _dmarc.acme.com

Expected output (illustrative):

text
"v=DMARC1; p=none; rua=mailto:dmarc@acme.com; adkim=r; aspf=r"

If you send cold email from lookalike domains, publish this record on each one, not just the main domain.

Step 3: Read the reports and align every sender

Wait 7 days, then open the aggregate reports. Each <record> shows a sending IP, a count, and the SPF and DKIM results.

xml
<record>
  <row>
    <source_ip>203.0.113.25</source_ip>
    <count>412</count>
    <policy_evaluated>
      <disposition>none</disposition>
      <dkim>fail</dkim>
      <spf>pass</spf>
    </policy_evaluated>
  </row>
  <identifiers><header_from>acme.com</header_from></identifiers>
  <auth_results>
    <spf><domain>bounce.vendor.example</domain><result>pass</result></spf>
  </auth_results>
</record>

This row is the classic miss. SPF passed, but for bounce.vendor.example, not acme.com, so it is not aligned. DKIM failed. The fix is to turn on custom-domain DKIM in that vendor's settings so it signs with d=acme.com.

Work through the list:

  1. Group rows by source_ip and identify each sender.
  2. For every legitimate sender, enable DKIM signing with your domain.
  3. Add its SPF include: only if it sends from its own envelope domain and you need SPF alignment.
  4. Delete senders you do not recognise from your plans. Unknown IPs in the reports are the spoofing you are trying to stop.

Aim for every legitimate volume passing DMARC for two full weeks before moving on. Google requires a DKIM key of at least 1024 bits for mail to personal Gmail accounts, and recommends 2048 bits where the provider supports it (Google sender guidelines, October 2026).

Step 4: Enforce in stages

Move the policy up one level at a time. Use pct to apply it to a share of mail first (RFC 7489, September 2026).

text
; Week 1: quarantine a quarter of failing mail
v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc@acme.com

; Week 2: all failing mail to spam
v=DMARC1; p=quarantine; rua=mailto:dmarc@acme.com

; Week 4+: reject
v=DMARC1; p=reject; rua=mailto:dmarc@acme.com

Two traps catch people here. Forwarded mail often breaks SPF, so a small failure rate from forwarders is normal and DKIM carries those messages. And a monthly sender, such as an invoicing tool, may not appear in a one-week sample, so check the full month before reject.

Watch the reports after each change. If a legitimate sender starts failing, drop back one step, fix it and retry.

Subdomains inherit the policy. To set a different one, add sp=, for example sp=reject once the parent is stable.

For cold outbound, p=quarantine is the practical minimum. p=reject is safer for your main domain, because it is the one a spoofer would use.

Step 5: Read the tags you will meet

Reports and receivers use a few tags again and again. Know these before you edit a live record.

TagMeaningTypical value
pPolicy for the domainnone, quarantine, reject
spPolicy for subdomainsSame values. Defaults to p.
pctShare of failing mail the policy applies to25, 100
ruaWhere aggregate reports gomailto:dmarc@acme.com
adkim, aspfAlignment mode for DKIM and SPFr relaxed, s strict

Strict alignment (s) requires an exact domain match. Use it only when you control every sender and have a reason. Most cold outbound setups stay on relaxed.

Step 6: Check the list before the first send

Authentication gets you to the inbox door. The list decides whether you stay there. Size the audience first with a free count (the same body with ?count=true and limit 1), then pull a small page and read email_status.

bash
curl -s -X POST "https://api.leadocean.io/v1/people/search" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jobLevel": ["VP"],
    "jobFunction": ["Sales & Business Development"],
    "country": ["US"],
    "emailStatus": ["verified"],
    "limit": 25
  }'

A 25-row page spends 25 records. Sizing with a count spends none. Send only to verified addresses while a new domain builds reputation, and ramp volume slowly. LeadOcean does not refund bounces, so read email_status before you send (pricing). More on the sending side in DMARC for outbound, and more guides on the blog.

What you get

Three outputs tell you the setup works.

The live record, from dig (illustrative, with a placeholder domain):

text
$ dig +short TXT _dmarc.acme.com
"v=DMARC1; p=reject; rua=mailto:dmarc@acme.com"

A header in a received test message. Look for dmarc=pass in Gmail's "Show original":

text
Authentication-Results: mx.google.com;
  dkim=pass header.d=acme.com;
  spf=pass smtp.mailfrom=acme.com;
  dmarc=pass (p=REJECT) header.from=acme.com

And the audience size, from the free leadocean_count_leads MCP tool on 2026-10-21. Filters: jobLevel VP, jobFunction Sales & Business Development, country US, emailStatus verified.

json
{ "total": 31141, "totalIsExact": true, "distinctCompanies": 18563, "credits": 0 }

That is a count of verified-email people only, not everyone matching the other filters. Pulling the list is a separate step. For a recurring list, see monitor startup growth signals.

Troubleshooting

ErrorCauseFix
dig returns nothing for _dmarcRecord added at the wrong host, or DNS not propagatedHost must be _dmarc (some panels want the full _dmarc.acme.com). Wait for the TTL.
No reports arriverua address is wrong, or the report mailbox rejects large XMLCheck the mailto: address and mailbox size. Large receivers send once a day.
SPF passes but DMARC failsSPF passed on the vendor's domain, so it is not alignedEnable custom-domain DKIM at the vendor so d= matches your From domain.
Two SPF recordsSeveral tools each told you to add oneMerge into a single v=spf1 line and stay under 10 lookups.
429 from LeadOceanAbove the plan's rate limit (5 a second on Free, 200 on Agency)Back off and honour the Retry-After header.
402 from LeadOceanThe 1,000 free records are spentMove to a paid plan or narrow the search.

FAQ

How long should I stay on p=none?

Two to four weeks, long enough to see every monthly sender such as invoicing tools. Move on only when legitimate mail passes consistently in the reports.

Do I need DMARC if I send fewer than 5,000 emails a day?

Google's bulk rules start at 5,000 messages a day to personal Gmail accounts (Google sender guidelines, October 2026). Below that you only need SPF or DKIM. Publish DMARC anyway, since reports show who else uses your domain.

Should cold outreach domains have DMARC too?

Yes. Publish a record on every sending domain, including secondary ones. A lookalike domain with no policy is the weakest link in your setup.

Can LeadOcean set up DMARC for me?

No. DMARC is DNS on your side. LeadOcean covers the list: filters, email_status and free counts before you spend a record.

Authenticate the domain, then fill it with verified contacts

Free to start. No credit card. 1,000 records to spend whenever you like.

Get your free API key →