How You Lose Domain Reputation (and How to Get It Back)

Receivers judge your domain on whether each message authenticated, how recipients reacted to it, and how you behave over time. No provider publishes that judgement as a number. Infer it from DMARC aggregate reports, blocklist listings and complaint logs.

Do you need this?

Your domain Do this
Sends mail SPF, DKIM, DMARC, and read the rua= reports
Sends no mail Lock it down: MX 0 ., v=spf1 -all, p=reject. No DKIM needed

A domain that sends nothing still needs the lockdown, or anyone can send as it.

What breaks

Cause In the report Fix
ESP sends from its own envelope domain auth_results/spf=pass, policy_evaluated/spf=fail Bounce domain under your org domain, or DKIM d= yours
Key never published policy_evaluated/dkim=fail, no auth_results/dkim Publish <selector>._domainkey
Selector left with empty p= same A revoked key (RFC 6376 §3.6.1). Publish a real one
p=none reports arrive, nothing is blocked Move to quarantine, then reject
Forwarding SPF fails at the second hop Nothing. DKIM survives it, SPF does not

The alignment trap. Adding include: to your SPF record does not fix an ESP that sends from its own envelope domain: the receiver evaluates that domain’s SPF and never reads yours. Fix it at the sender, not in your record.

policy_evaluated is the aligned verdict, auth_results the raw one. Read the first, or you will edit the wrong record.

Losing reputation when authentication is fine

  • Complaints. “Report spam” is the strongest negative signal, measured against volume.
  • Unengaged or purchased lists. Complaints, spam-trap hits and bounces, together.
  • Sudden volume. 200 messages a day, then 40,000, reads as suspicious whatever the authentication.
  • A compromised mailbox or form relay. A common source of a new failing source_ip.
  • Shared IPs. Your reputation is partly your neighbours’ until you have the volume for your own.
  • No bounce hygiene. Backscatter and repeated hard bounces both count against you.

Reading the reports

Per day, from rua=:

  • Unauthenticated volume — rows where both mechanisms are fail.
  • Which source_ip + header_from pairs fail, and whether each is expected.
  • The policy actually in force, from policy_published.

Four limits belong with any conclusion:

  1. One report is one provider’s partial view. Two providers, same window, are not duplicates.
  2. count is per window, not per day. Normalise.
  3. A source that stops appearing may have been blocked, not fixed — ambiguous under reject or quarantine, clearer under none.
  4. Weight by volume. Ten messages a day is not ten thousand.

Fix order

  1. Inventory every sender: ESPs, transactional, ticketing, printers, CRMs, forms, alerts.
  2. Get each into SPF and signing with aligned DKIM, one selector per sender.
  3. Stay at p=none until every legitimate sender passes consistently.
  4. Ramp none → quarantine → reject, sampling with pct.
  5. Set sp= and np= (RFC 9091) on purpose.
  6. Watch per-day failures per source after each step. A rise means you enforced early.
  7. Fix the behaviour too: suppress hard bounces, stop mailing the unengaged, close the form relay.

pct is the share of failing mail the receiver may act on. The only hard rule is that it must not apply the policy to more than pct percent; the usual fallbacks (remainder quarantined under reject, untouched under quarantine) are SHOULD-level in RFC 7489 §6.6.4, so do not rely on them.

The records

; SPF — exactly one. Two v=spf1 records is a permerror, not a merge (RFC 7208 §4.5)
vibhuvioio.com.  300 IN TXT "v=spf1 include:_spf.example.net ip4:192.0.2.10 -all"

; DKIM — one per selector. Strings hold 255 octets, so long keys are concatenated
sel2026._domainkey.vibhuvioio.com. 300 IN TXT ( "v=DKIM1; k=rsa; "
    "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...w==" )

; A deliberately revoked selector: empty p= (RFC 6376 §3.6.1)
sel2025._domainkey.vibhuvioio.com. 300 IN TXT "v=DKIM1; k=rsa; p="

; DMARC
_dmarc.vibhuvioio.com. 300 IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc@vibhuvioio.com"

; An rua outside your domain must authorise the reports (RFC 7489 §7.1)
vibhuvioio.com._report._dmarc.reports.example.net. 300 IN TXT "v=DMARC1"

; MX, and a null MX for a domain that must not receive (RFC 7505)
vibhuvioio.com.          300 IN MX 10 mx1.mail.example.net.
no-reply.vibhuvioio.com. 300 IN MX 0 .
dig +short TXT vibhuvioio.com
dig +short TXT sel2026._domainkey.vibhuvioio.com
dig +short TXT _dmarc.vibhuvioio.com
dig +short MX vibhuvioio.com

Is your setup current?

Standard Current Note
SPF RFC 7208 Obsoletes 4408. 10-term limit, at most 2 void lookups
DKIM RFC 6376 Updated by RFC 8301 (keys ≥1024, prefer 2048) and RFC 8463 (Ed25519)
DMARC RFC 7489 Informational, not a standard. The DMARCbis revision is in progress and clarifies alignment — track it
np= RFC 9091 Policy for non-existent subdomains. Newer; worth adopting
ARC RFC 8617 Carries authentication across a forwarder
MTA-STS RFC 8461 The layer past DMARC: enforces TLS to your MX
TLS-RPT RFC 8460 Reporting for MTA-STS and TLS failures
DANE for SMTP RFC 7672 TLS pinning in DNS. Needs DNSSEC
DNSSEC RFC 4033–4035 Makes the answers SPF and DKIM depend on verifiable

The common gap: DMARC alone, no MTA-STS or TLS-RPT, and SPF/DKIM set once and never re-checked. DKIM keys age, selectors get retired, and a sender appears that nobody inventoried.

Checklist

  • One SPF record, under 10 terms, ending -all.
  • Every selector published; retired ones revoked with an empty p=.
  • adkim/aspf chosen on purpose.
  • Unauthenticated volume per day, per source, and its direction.
  • sp= and np= deliberate.
  • Complaints and bounces reviewed alongside authentication.
  • DNSSEC automated and owned, or consciously off.