// technical deep dive

SPF synthesis, explained. No hand-waving.

Here is exactly how UglyDMARC defeats the 10-lookup limit, how the DMARC reporting pipeline works, and what happens at every step between a sending MTA and a receiver's SPF evaluation.

// part 1

SPF synthesis — the 10-lookup problem, solved

RFC 7208 limits SPF to 10 DNS-resolving mechanisms per evaluation. UglyDMARC re-architects how answers are generated so the receiver only ever needs one.

// step 1

You publish one include on your domain

Replace every vendor include in your SPF record with a single UglyDMARC macro include. That's the only change you make to your DNS.

Your new SPF record

Publish this on your domain (e.g. acme-corp.com):

# Before: vendor soup that blows the limit
v=spf1 include:_spf.google.com include:spf.protection.outlook.com
       include:sendgrid.net include:mailgun.org include:amazonses.com
       include:_spf.salesforce.com include:mail.zendesk.com -all
       ^ 7+ includes, each expands to more lookups

# After: one include, all senders handled
v=spf1 include:%{ir}.%{v}.%{d}.spf.uglydmarc.com -all
Macro expansion

What the macros mean

When a receiving MTA evaluates this record, it expands the macros before querying. For sender IP 1.2.3.4 sending as acme-corp.com:

  • %{ir} → sender IP reversed: 4.3.2.1
  • %{v} → IP version token: in-addr
  • %{d} → sending domain: acme-corp.com

The resulting query is:

4.3.2.1.in-addr.acme-corp.com.spf.uglydmarc.com
// step 2

UglyDMARC pre-flattens your entire include tree

Before any MTA ever queries us, a background DAG builder recursively resolves every include:, ip4:, ip6:, and a: mechanism in your chain — across every vendor — into a flat, deduplicated CIDR set stored in cache.

Always fresh

The builder watches TTLs and refreshes each node before it expires. When Google or SendGrid updates their IP ranges, UglyDMARC picks it up automatically — no manual action required.

Never in the query path

The DAG builder is strictly background. It never runs during a DNS query. Query-time is always O(1) — a single CIDR membership test against the cached set.

# What the background builder resolves for you
# (all happening before any MTA queries)

acme-corp.com_spf.google.com
  → 35.190.247.0/24
  → 64.233.160.0/19
  → 66.102.0.0/20
  → ... 12 more ranges

acme-corp.comspf.protection.outlook.com
  → 40.92.0.0/15
  → 40.107.0.0/16
  → ... 8 more ranges

acme-corp.comsendgrid.net
  → 167.89.0.0/17
  → 198.37.144.0/20
  → ... 4 more ranges

# Flattened result: deduplicated CIDR set
spf:domain:acme-corp.com:dag  → 47 CIDRs, cached
// step 3

At query time: one lookup, one answer, always clean

When the receiving MTA queries for a specific sender IP, UglyDMARC's synthesizer does a single CIDR membership test against the pre-built set and returns the appropriate answer immediately.

# IP in the cached CIDR set → pass
4.3.2.1.in-addr.acme-corp.com.spf.uglydmarc.com.
  IN TXT "v=spf1 ip4:1.2.3.4 -all"

# IP NOT in the set → softfail (unknown sender)
8.7.6.5.in-addr.acme-corp.com.spf.uglydmarc.com.
  IN TXT "v=spf1 -all"

The result

The receiver evaluates exactly 1 DNS lookup — the top-level include — regardless of how many vendors are in your tree. No permerror. No SPF failures caused by lookup count. Deterministic, always.

Query-time invariants

What never happens at query time

  • No live DNS resolution — ever
  • No recursive SPF evaluation
  • No blocking on a cache rebuild
  • No network calls outside the cache lookup

What does happen

  • Parse the qname to extract the sender IP and domain
  • Load the domain's pre-built CIDR set from cache
  • O(1) CIDR membership test
  • Return a minimal synthesized TXT record

P99 query latency: < 2 ms

// part 2

The DMARC reporting pipeline

SPF synthesis solves the lookup problem. DMARC reporting solves the visibility problem — and together they give you a safe, data-driven path to p=reject.

📬 Collection

Reports come straight to UglyDMARC

You set your domain's DMARC rua= to a UglyDMARC reporting address. From then on, mailbox providers (Google, Microsoft, Yahoo, and others) send their daily aggregate reports directly to UglyDMARC — there's no mailbox of yours to connect and no MX changes. We receive every report and process it for you.

🔬 Parsing

From raw XML to a clear picture

Reports arrive as gzip-compressed XML. UglyDMARC parses every record — sender IP, SPF result, DKIM result, DMARC alignment and disposition, and the sending source — then normalizes and stores it for display in UglyDMARC.

# What a DMARC aggregate report tells you (simplified)
# Reporter: google.com | Period: 2026-06-01

Source IP          Count  SPF        DKIM       DMARC
192.0.2.10         1,482  pass       pass       pass   ← Google Workspace, all good
198.51.100.20        341  pass       pass       pass   ← SendGrid, configured correctly
203.0.113.42          12  fail       fail       fail   ← unknown sender — investigate
203.0.113.99           3  fail       fail       fail   ← potential spoofing attempt

# Without this data, you can't safely move to p=reject
Dashboards

SPF & DKIM pass rates

Per-domain charts for SPF pass, DKIM pass, and DMARC alignment over time. See trends by reporter, by source IP, and by disposition.

Multi-domain search

Search across everything

Cross-domain record search with predicate filters — find any IP, ESP, or sending source across every domain in your account. Export to CSV.

Alerts

Anomaly detection

Get notified when a new unknown sender appears, pass rates drop, or your DMARC policy is overriding SPF failures. Route alerts to email or webhook.

// the safe path

From p=none to p=reject, with data

Most domains stay at p=none indefinitely because enforcing is too risky without visibility. UglyDMARC closes that gap.

Learn why it matters →

Phase 1

p=none — observe

Turn on DMARC reporting. Every ISP starts sending you aggregate data. No mail is affected. UglyDMARC collects and parses all of it.

Phase 2

p=quarantine — tighten

Once you've identified all legitimate senders and resolved SPF issues (with synthesis handling the lookup limit), move to quarantine. Monitor for false positives.

Phase 3

p=reject — enforce

When DMARC reports show all your legitimate mail passing, flip to reject. Spoofed mail is rejected at the receiver. Your domain is protected.

// ready to start

Add your domain and publish one record.

Setup takes minutes. No agents, no MX changes, no complex configuration — just add your domain and update one DNS record.

Get started ↗