<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Denys Button</title>
    <description>The latest articles on DEV Community by Denys Button (@denys_button).</description>
    <link>https://dev.to/denys_button</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4146811%2Fb842ba37-0c6c-488e-8749-fa05204a3742.jpg</url>
      <title>DEV Community: Denys Button</title>
      <link>https://dev.to/denys_button</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/denys_button"/>
    <language>en</language>
    <item>
      <title>The Fake Complaint Spike: When "Spam Complaints" Aren't Real Complaints</title>
      <dc:creator>Denys Button</dc:creator>
      <pubDate>Mon, 28 Sep 2026 10:11:14 +0000</pubDate>
      <link>https://dev.to/denys_button/the-fake-complaint-spike-when-spam-complaints-arent-real-complaints-2fgc</link>
      <guid>https://dev.to/denys_button/the-fake-complaint-spike-when-spam-complaints-arent-real-complaints-2fgc</guid>
      <description>&lt;p&gt;Some providers log a complaint when a recipient just deletes unread. Here's how to tell a real spam complaint spike from a false one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fake Complaint Spike: Not Every "Complaint" Is a Complaint
&lt;/h2&gt;

&lt;p&gt;You check your feedback loop data or Google Postmaster Tools and see it: complaint rate jumped from 0.03% to 0.4% overnight. Panic sets in. You pause the campaign, start rewriting copy, maybe pull the list and re-verify it. Then two days later it settles back down on its own, and you're not sure what actually happened or what you fixed.&lt;/p&gt;

&lt;p&gt;Here's the piece almost nobody tells you, and it's the thing that separates a real deliverability problem from a false alarm: &lt;strong&gt;not every event a provider logs as a "complaint" is a recipient hitting "Report Spam."&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's actually happening
&lt;/h2&gt;

&lt;p&gt;Some mailbox providers' feedback loop (FBL) mechanisms are looser than the name implies. Depending on the provider and the exact UI flow, an action as passive as &lt;strong&gt;deleting a message without opening it&lt;/strong&gt;, or deleting it quickly after a glance, can get bucketed into the same complaint signal that a genuine "this is spam" click generates. The provider isn't lying to you — this is a real feedback signal reflecting real recipient disengagement — but it's not the same thing as "this recipient was offended enough to actively flag me," and treating it that way leads to the wrong fix.&lt;/p&gt;

&lt;p&gt;This distinction matters because the two causes point to completely different problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A real complaint spike&lt;/strong&gt; (recipients actively marking as spam) usually means your content, targeting, or send cadence crossed a line — wrong list segment, too aggressive a pitch, mismatched expectations from opt-in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A false spike driven by delete-without-open behavior&lt;/strong&gt; usually means something upstream changed engagement — a list segment that's gone cold, a subject line that stopped resonating, a send time that landed at a bad hour, or simply normal list fatigue on a long-running sequence.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gutting a campaign's copy in response to a false spike fixes nothing, because copy was never the cause. Worse, it burns a debugging cycle while the actual cause — say, a cold list segment that needed to be trimmed — keeps degrading your sender reputation untouched.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to tell the difference before you react
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Check the timing against your send, not just the daily aggregate.&lt;/strong&gt; A real complaint spike usually clusters tightly after send time — people react fast when something actively bothers them. A delete-driven signal tends to spread out more evenly over the following 24–48 hours, matching normal inbox-checking behavior rather than an immediate reaction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Cross-reference against open rate for that specific send.&lt;/strong&gt; If the "complaint" spike coincides with a lower-than-usual open rate on the same send, that's a strong signal you're looking at disengagement (deletes), not active complaints. A genuine complaint spike can happen even on a well-opened email — people open it, read it, then complain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Compare magnitude against list segment, not domain-wide.&lt;/strong&gt; Pull the complaint data by list segment or campaign, not just the domain aggregate. If the spike is concentrated in one old, rarely-engaged segment, that points to fatigue/deletes. If it's spread evenly across fresh and old segments alike, it's more likely a genuine content or targeting issue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Check Google Postmaster Tools' spam rate trend over a rolling window, not a single day.&lt;/strong&gt; A single-day blip that reverts within 2–3 days without any changes made is far more consistent with a noisy false signal than a real reputation hit. A real complaint-driven reputation problem tends to persist and compound if uncorrected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Look at unsubscribe rate alongside complaint rate.&lt;/strong&gt; A real jump in "this bothers me" sentiment usually shows up in both complaints and unsubscribes together. If unsubscribes stayed flat but the complaint metric alone spiked, lean toward the false-signal explanation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to actually do about each case
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;If it's a real complaint spike:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pause the specific segment or campaign, not necessarily everything.&lt;/li&gt;
&lt;li&gt;Review content against the specific segment's original opt-in context — did this list agree to this kind of email?&lt;/li&gt;
&lt;li&gt;Check send frequency — are you over-mailing this segment relative to what they signed up for?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If it's a false spike from disengagement:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Suppress or re-engage the specific cold segment rather than touching copy.&lt;/li&gt;
&lt;li&gt;Consider a sunset policy — stop mailing contacts who haven't opened in N sends.&lt;/li&gt;
&lt;li&gt;Review subject line and send-time performance for that segment specifically, since the underlying issue is attention, not offense.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The bigger point
&lt;/h2&gt;

&lt;p&gt;This is exactly why step 3 of any real deliverability diagnosis — engagement and list quality — comes before step 4, content. A complaint-rate metric looks like a content signal on the surface, but it's frequently a list-hygiene signal wearing a content-signal costume. Reacting to the surface-level number without checking what's actually driving it is how teams end up rewriting perfectly good copy while the real cause, a stale segment nobody's pruned in six months, keeps quietly dragging down domain reputation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick checklist before you react to a complaint spike
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Does the spike cluster right after send (real) or spread over 24–48 hrs (deletes)?&lt;/li&gt;
&lt;li&gt;Does it correlate with a lower open rate on that specific send?&lt;/li&gt;
&lt;li&gt;Is it concentrated in one old/cold segment, or spread evenly?&lt;/li&gt;
&lt;li&gt;Does it persist over a rolling window, or self-correct in a few days?&lt;/li&gt;
&lt;li&gt;Did unsubscribes move with it, or stay flat?&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Telling a real complaint problem from a false one is exactly the kind of nuance the technical diagnostic in the &lt;strong&gt;Cold Email Deliverability Kit&lt;/strong&gt; (&lt;a href="https://remixdenis.gumroad.com/l/kit" rel="noopener noreferrer"&gt;https://remixdenis.gumroad.com/l/kit&lt;/a&gt;) is built to catch before you burn a week second-guessing good copy. For the full breakdown of engagement signals and list-hygiene diagnostics, check out &lt;strong&gt;Deliverability Diagnostics: What Actually Gets Email to the Inbox&lt;/strong&gt; (&lt;a href="https://remixdenis.gumroad.com/l/mclaie" rel="noopener noreferrer"&gt;https://remixdenis.gumroad.com/l/mclaie&lt;/a&gt;).&lt;/p&gt;

</description>
      <category>email</category>
      <category>marketing</category>
      <category>analytics</category>
      <category>saas</category>
    </item>
    <item>
      <title>How to Read a DMARC Report (RUA) — A Practical Walkthrough</title>
      <dc:creator>Denys Button</dc:creator>
      <pubDate>Mon, 28 Sep 2026 10:08:54 +0000</pubDate>
      <link>https://dev.to/denys_button/how-to-read-a-dmarc-report-rua-a-practical-walkthrough-3ob0</link>
      <guid>https://dev.to/denys_button/how-to-read-a-dmarc-report-rua-a-practical-walkthrough-3ob0</guid>
      <description>&lt;p&gt;What a DMARC aggregate report actually shows, how to start collecting one, and why you should not jump straight to p=reject. Step by step.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Read a DMARC Report Without Guessing
&lt;/h2&gt;

&lt;p&gt;You set up a DMARC record, added a &lt;code&gt;rua=&lt;/code&gt; tag, and now you're staring at either nothing (no reports arriving yet) or an inbox full of XML attachments that look like a server log dumped from orbit. Neither state tells you what to do next. Here's how to actually get useful data out of DMARC and read it correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a DMARC aggregate (RUA) report actually is
&lt;/h2&gt;

&lt;p&gt;DMARC has two report types: aggregate (RUA) and forensic (RUF). RUA is what you want first — it's a daily XML digest, sent by every major receiving mailbox provider that supports DMARC (Google, Microsoft, Yahoo, etc.), summarizing every message they saw claiming to be from your domain: how many, from which sending IPs, and whether SPF and DKIM passed and aligned for each one.&lt;/p&gt;

&lt;p&gt;It is not a list of individual emails or recipient addresses — it's aggregated by source IP and result, once a day per reporting provider. RUF (forensic) reports individual failing messages but almost no major provider sends them anymore due to privacy constraints, so don't build a workflow around expecting RUF data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Start collecting reports
&lt;/h2&gt;

&lt;p&gt;Your &lt;code&gt;_dmarc&lt;/code&gt; TXT record needs a &lt;code&gt;rua=&lt;/code&gt; tag pointing to an address that can receive the reports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="n"&gt;dmarc&lt;/span&gt;.&lt;span class="n"&gt;yourdomain&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt;. &lt;span class="n"&gt;TXT&lt;/span&gt; &lt;span class="s2"&gt;"v=DMARC1; p=none; rua=mailto:dmarc-reports@yourdomain.com; fo=1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things matter here before you go further:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start at &lt;code&gt;p=none&lt;/code&gt;.&lt;/strong&gt; This tells receivers "report to me, but don't do anything differently with delivery." It's monitor-only mode. You need data before you can safely change enforcement — more on this below.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't point &lt;code&gt;rua=&lt;/code&gt; at a personal inbox.&lt;/strong&gt; Raw XML is unreadable at any real volume. Use a free parser like &lt;strong&gt;dmarcian's DMARC XML parser&lt;/strong&gt; (they offer a free tier for basic aggregate report parsing) or a similar tool that ingests the raw reports and renders them as a dashboard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're new to this, sign up for a free DMARC report parsing tool, get their provided &lt;code&gt;rua=&lt;/code&gt; address (many act as an intermediary and forward/parse automatically), and use that in your record instead of a raw mailbox.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Give it time
&lt;/h2&gt;

&lt;p&gt;Reports arrive roughly once every 24 hours per reporting provider, and you need enough volume and enough days to see a real pattern — a few days at minimum, ideally 1–2 weeks before drawing conclusions. A single day's report from a low-volume domain can be misleading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Read alignment, not just pass/fail
&lt;/h2&gt;

&lt;p&gt;This is where most people misread the report. DMARC doesn't just ask "did SPF pass" and "did DKIM pass" — it asks whether the &lt;strong&gt;domain that passed&lt;/strong&gt; matches the &lt;strong&gt;visible From domain&lt;/strong&gt;, a concept called alignment.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SPF alignment (&lt;code&gt;aspf&lt;/code&gt;)&lt;/strong&gt; — does the domain in the Return-Path (envelope from) match the visible From domain? Under relaxed alignment (default), a subdomain match counts; under strict, it must match exactly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DKIM alignment (&lt;code&gt;adkim&lt;/code&gt;)&lt;/strong&gt; — does the &lt;code&gt;d=&lt;/code&gt; domain in the DKIM signature match the visible From domain? Same relaxed/strict distinction.&lt;/li&gt;
&lt;li&gt;DMARC passes if &lt;strong&gt;either&lt;/strong&gt; SPF or DKIM passes &lt;strong&gt;and&lt;/strong&gt; is aligned. A message can have SPF technically pass while failing DMARC, if the SPF-passing domain doesn't align with the From header.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the parsed report, look at each row's source IP alongside its &lt;code&gt;dkim&lt;/code&gt; and &lt;code&gt;spf&lt;/code&gt; result columns and their alignment flags. Group by source IP first — this is usually the fastest way to spot the real issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Identify every source IP, then sort them
&lt;/h2&gt;

&lt;p&gt;For every unique sending IP in the report, ask: do I recognize this?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Known senders failing alignment&lt;/strong&gt; — your ESP, CRM, or transactional provider is sending on your behalf but SPF/DKIM isn't aligned to your domain. This is a configuration fix, not a threat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unknown senders passing SPF but not DKIM (or vice versa)&lt;/strong&gt; — could be a legitimate forwarder, could be a spoofing attempt. Cross-reference against your actual vendor list.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unknown senders failing everything&lt;/strong&gt; — likely spoofing attempts being reported to you as evidence DMARC is doing its job, even at &lt;code&gt;p=none&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 5: Why you must not jump straight to p=reject
&lt;/h2&gt;

&lt;p&gt;Once you see failures, the instinct is to lock it down immediately — flip to &lt;code&gt;p=reject&lt;/code&gt; and stop the bad traffic. Don't, until every legitimate source in your reports is passing and aligned.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;p=reject&lt;/code&gt; tells every receiving provider to drop, outright, any message claiming your From domain that fails DMARC. If a legitimate but misconfigured sender — a support tool, a CRM, an internal system, an old marketing platform — is still in your sending mix and not yet aligned, &lt;code&gt;p=reject&lt;/code&gt; will silently kill their mail with zero warning. You won't find out until someone asks why their emails never arrived.&lt;/p&gt;

&lt;p&gt;The correct progression:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;p=none&lt;/code&gt; — monitor only, collect reports, identify every legitimate sending source.&lt;/li&gt;
&lt;li&gt;Fix SPF/DKIM alignment for each legitimate source (usually via custom DKIM selectors and adjusting SPF includes).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;p=quarantine&lt;/code&gt; at a low percentage (&lt;code&gt;pct=&lt;/code&gt;) — start enforcing softly, on a fraction of traffic, watch for unexpected impact.&lt;/li&gt;
&lt;li&gt;Increase &lt;code&gt;pct=&lt;/code&gt; and move to &lt;code&gt;p=reject&lt;/code&gt; only once reports show 100% of legitimate traffic passing and aligned, consistently, over multiple weeks.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Skipping straight to step 4 is the single most common way DMARC rollouts break legitimate mail flows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;rua=&lt;/code&gt; set, pointed at a parser, not a raw inbox.&lt;/li&gt;
&lt;li&gt;Start at &lt;code&gt;p=none&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Collect at least 1–2 weeks of reports before acting.&lt;/li&gt;
&lt;li&gt;Group failures by source IP; identify every unrecognized sender.&lt;/li&gt;
&lt;li&gt;Fix alignment for legitimate sources before tightening policy.&lt;/li&gt;
&lt;li&gt;Move &lt;code&gt;p=none&lt;/code&gt; → &lt;code&gt;p=quarantine&lt;/code&gt; (with low &lt;code&gt;pct=&lt;/code&gt;) → &lt;code&gt;p=reject&lt;/code&gt;, only as reports confirm it's safe.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Reading DMARC reports correctly is one piece of a larger authentication check — SPF, DKIM, and DMARC all interact, and a mistake in one shows up as noise in the others. The &lt;strong&gt;Cold Email Deliverability Kit&lt;/strong&gt; (&lt;a href="https://remixdenis.gumroad.com/l/kit" rel="noopener noreferrer"&gt;https://remixdenis.gumroad.com/l/kit&lt;/a&gt;) walks through all three in a 20-minute diagnostic pass. For the full policy rollout strategy and alignment troubleshooting, see &lt;strong&gt;Deliverability Diagnostics: What Actually Gets Email to the Inbox&lt;/strong&gt; (&lt;a href="https://remixdenis.gumroad.com/l/mclaie" rel="noopener noreferrer"&gt;https://remixdenis.gumroad.com/l/mclaie&lt;/a&gt;).&lt;/p&gt;

</description>
      <category>dns</category>
      <category>email</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>SPF Too Many DNS Lookups: Fix the 10-Lookup Limit and permerror</title>
      <dc:creator>Denys Button</dc:creator>
      <pubDate>Mon, 28 Sep 2026 10:04:02 +0000</pubDate>
      <link>https://dev.to/denys_button/spf-too-many-dns-lookups-fix-the-10-lookup-limit-and-permerror-2hoj</link>
      <guid>https://dev.to/denys_button/spf-too-many-dns-lookups-fix-the-10-lookup-limit-and-permerror-2hoj</guid>
      <description>&lt;h2&gt;
  
  
  SPF "Too Many DNS Lookups": Diagnosing and Fixing permerror
&lt;/h2&gt;

&lt;p&gt;You added one more &lt;code&gt;include:&lt;/code&gt; to your SPF record — a new ESP, a new outreach tool, a new SaaS vendor that needs to send on your behalf — and now mail that used to pass is failing SPF entirely. This is one of the most common silent failures in email infrastructure, and it doesn't throw an obvious error in most sending dashboards. It just quietly starts failing authentication.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 10-lookup limit, explained
&lt;/h2&gt;

&lt;p&gt;RFC 7208 caps SPF evaluation at 10 DNS lookups per check. Not 10 &lt;code&gt;include:&lt;/code&gt; mechanisms — 10 total lookups, counting every mechanism that requires its own DNS query: &lt;code&gt;include&lt;/code&gt;, &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;mx&lt;/code&gt;, &lt;code&gt;ptr&lt;/code&gt;, &lt;code&gt;exists&lt;/code&gt;, and any redirect. &lt;code&gt;ip4&lt;/code&gt;/&lt;code&gt;ip6&lt;/code&gt; and plain &lt;code&gt;all&lt;/code&gt; don't count, since they don't require a lookup.&lt;/p&gt;

&lt;p&gt;Here's the part that catches people off guard: each &lt;code&gt;include:&lt;/code&gt; can itself contain more &lt;code&gt;include:&lt;/code&gt; statements, each triggering its own lookup. A record with five includes can easily blow past 10 once you follow the chain, because vendors like your ESP or CRM often nest their own third-party includes inside their SPF record.&lt;/p&gt;

&lt;p&gt;When the limit is exceeded, the result isn't "SPF fails" — it's &lt;code&gt;permerror&lt;/code&gt;, a permanent evaluation error. Receiving servers treat &lt;code&gt;permerror&lt;/code&gt; inconsistently, but many treat it as equivalent to a fail, which tanks deliverability across every stream sharing that domain, not just the one from the new vendor you added.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to check your current lookup count
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Pull the raw SPF record:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;dig TXT yourdomain.com +short
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;For every &lt;code&gt;include:&lt;/code&gt; in the record, resolve it and count its own lookups:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;dig TXT _spf.vendor.com +short
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Repeat recursively — an include can point to another include.&lt;/li&gt;
&lt;li&gt;Or skip the manual recursion and run the domain through &lt;strong&gt;MXToolbox's SPF record check&lt;/strong&gt;, which walks the full chain and reports the total lookup count plus a flag if you're at or over the limit.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're at 8–10, you're one vendor addition away from &lt;code&gt;permerror&lt;/code&gt;. Fix it now, not after it breaks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common causes of an oversized SPF record
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Stacking multiple ESPs (e.g., your transactional provider, your marketing platform, and a cold outreach tool) each with their own nested includes&lt;/li&gt;
&lt;li&gt;Legacy vendors left in the record long after you stopped using them&lt;/li&gt;
&lt;li&gt;CRM or helpdesk tools that ask you to add their SPF include for "better deliverability" but rarely get removed when you churn&lt;/li&gt;
&lt;li&gt;Copy-pasted SPF records from old documentation that include unnecessary &lt;code&gt;a&lt;/code&gt; or &lt;code&gt;mx&lt;/code&gt; mechanisms alongside &lt;code&gt;include:&lt;/code&gt; chains&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to fix it: flatten, consolidate, or delegate
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Remove dead vendors first.&lt;/strong&gt; Before doing anything structural, audit every &lt;code&gt;include:&lt;/code&gt; against your actual active sending tools. This alone often solves it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Flatten static includes into IP ranges.&lt;/strong&gt; If a vendor's sending IPs are stable, replace &lt;code&gt;include:vendor.com&lt;/code&gt; with the resolved &lt;code&gt;ip4:&lt;/code&gt; ranges directly in your record. This removes the lookup entirely, but you now own the maintenance burden if the vendor changes IPs — track their changelog or re-flatten periodically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Consolidate under one subdomain per sending stream.&lt;/strong&gt; Some senders split cold outreach, transactional, and marketing mail across subdomains (e.g., &lt;code&gt;mail.yourdomain.com&lt;/code&gt; for outreach), each with a leaner, purpose-specific SPF record instead of one bloated record trying to authorize everything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Use a macro/flattening service if the includes are volatile.&lt;/strong&gt; Tools like dmarcian's SPF Surveyor visualize the full lookup tree and can help you decide what to flatten versus what to leave as a live include for vendors that rotate IPs frequently.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the fixed record should look like
&lt;/h2&gt;

&lt;p&gt;A lean, well-scoped SPF record for a domain sending through one ESP and one cold outreach platform might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;v=spf1 ip4:203.0.113.0/24 include:_spf.esp-example.com -all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note &lt;code&gt;-all&lt;/code&gt; (hard fail) versus &lt;code&gt;~all&lt;/code&gt; (soft fail) — that's a separate decision from lookup count, but worth checking while you're in here. A record with &lt;code&gt;?all&lt;/code&gt; (neutral) provides essentially no protection and is worth tightening once your legitimate senders are fully accounted for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verification checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Run MXToolbox SPF check — confirm lookup count is under 10, ideally under 8 to leave headroom.&lt;/li&gt;
&lt;li&gt;Confirm no &lt;code&gt;permerror&lt;/code&gt; or &lt;code&gt;temperror&lt;/code&gt; in the result.&lt;/li&gt;
&lt;li&gt;Remove any &lt;code&gt;include:&lt;/code&gt; for vendors no longer in active use.&lt;/li&gt;
&lt;li&gt;Flatten stable, high-lookup includes to &lt;code&gt;ip4:&lt;/code&gt;/&lt;code&gt;ip6:&lt;/code&gt; where feasible.&lt;/li&gt;
&lt;li&gt;Re-check after any new vendor is added — this is a recurring maintenance task, not a one-time fix.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Don't stop at SPF
&lt;/h2&gt;

&lt;p&gt;A passing SPF record doesn't guarantee inbox placement on its own — it needs to align with DKIM under DMARC, and it's just one layer of a much larger diagnostic. Vendors change IP ranges without much warning, so this is worth re-checking on a schedule, not just when something breaks.&lt;/p&gt;




&lt;p&gt;For a full DNS-lookup audit workflow alongside DKIM and DMARC checks, the &lt;strong&gt;Cold Email Deliverability Kit&lt;/strong&gt; (&lt;a href="https://remixdenis.gumroad.com/l/kit" rel="noopener noreferrer"&gt;https://remixdenis.gumroad.com/l/kit&lt;/a&gt;) includes the exact diagnostic steps and a bounce-code cheat sheet for when authentication failures start showing up as bounces. The course &lt;strong&gt;Deliverability Diagnostics: What Actually Gets Email to the Inbox&lt;/strong&gt; (&lt;a href="https://remixdenis.gumroad.com/l/mclaie" rel="noopener noreferrer"&gt;https://remixdenis.gumroad.com/l/mclaie&lt;/a&gt;) covers flattening strategy and multi-vendor SPF architecture in more depth.&lt;/p&gt;

</description>
      <category>dns</category>
      <category>email</category>
      <category>devops</category>
      <category>security</category>
    </item>
    <item>
      <title>Why Does My Email Go to Spam? A Diagnostic Order That Actually Works</title>
      <dc:creator>Denys Button</dc:creator>
      <pubDate>Mon, 28 Sep 2026 09:56:16 +0000</pubDate>
      <link>https://dev.to/denys_button/why-does-my-email-go-to-spam-a-diagnostic-order-that-actually-works-2gih</link>
      <guid>https://dev.to/denys_button/why-does-my-email-go-to-spam-a-diagnostic-order-that-actually-works-2gih</guid>
      <description>&lt;p&gt;A step-by-step order for diagnosing why email lands in spam: technical auth first, then reputation and engagement, then copy last. Stop guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does My Email Go to Spam? Diagnose It in the Right Order
&lt;/h2&gt;

&lt;p&gt;Something worked last month. Now half your sends are landing in Promotions, spam, or nowhere at all, and everyone on the team has a theory. Someone wants to rewrite the subject line. Someone wants to swap the send time. Someone's convinced it's the word "free" in paragraph two.&lt;/p&gt;

&lt;p&gt;Most of that is noise. After 16 years working email infrastructure and deliverability across 1,000+ sending domains — including ramping fresh domains to 20,000+ sends/day in 14 days without triggering blocks — the pattern is consistent: people diagnose in the wrong order. They start with copy because copy is the easiest thing to blame and the easiest thing to change. But copy is rarely the actual cause, and "fixing" it without checking the plumbing first just burns another send cycle and another chunk of reputation.&lt;/p&gt;

&lt;p&gt;Here's the order that actually finds the cause, fastest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Technical authentication — check this before anything else
&lt;/h2&gt;

&lt;p&gt;If SPF, DKIM, or DMARC is broken or missing, nothing else you do matters. Mailbox providers use these three records to decide whether your mail is even eligible to be evaluated as legitimate, let alone land in the inbox.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SPF&lt;/strong&gt; — does the sending IP appear in the domain's &lt;code&gt;v=spf1&lt;/code&gt; record? Check for &lt;code&gt;permerror&lt;/code&gt; from exceeding 10 DNS lookups, a common silent failure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DKIM&lt;/strong&gt; — is the message actually being signed, and does the selector's public key in DNS match what's in the &lt;code&gt;d=&lt;/code&gt; and &lt;code&gt;s=&lt;/code&gt; tags of the signature?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DMARC&lt;/strong&gt; — is there a &lt;code&gt;_dmarc&lt;/code&gt; TXT record, and are SPF and/or DKIM aligned with the visible From domain (not just passing in isolation)?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the domain through MXToolbox's SPF/DKIM/DMARC checkers and dig for the raw TXT records yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig TXT yourdomain.com
dig TXT _dmarc.yourdomain.com
dig TXT selector._domainkey.yourdomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If any of these are broken, fix them before touching anything else downstream.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Domain and IP reputation
&lt;/h2&gt;

&lt;p&gt;Authentication passing doesn't mean the sender is trusted — it means the mail is verifiably from you. Reputation is a separate question.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check the sending IP and domain against major blocklists (Spamhaus, Barracuda, SORBI) via MXToolbox's blacklist tool.&lt;/li&gt;
&lt;li&gt;Pull up Google Postmaster Tools for the domain — check IP and domain reputation buckets, spam rate, and delivery errors over the last 30 days.&lt;/li&gt;
&lt;li&gt;New domain or new IP? Reputation isn't built yet. Sudden volume on an unwarmed domain looks identical to a burst of spam from a compromised account, and filters treat it that way.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3: List quality and engagement
&lt;/h2&gt;

&lt;p&gt;Once auth and reputation are clean, look at who you're actually mailing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bounce rate above ~2% on a single send is a signal your list has decayed or was never verified.&lt;/li&gt;
&lt;li&gt;Spam complaint rate above ~0.1% (Gmail's Postmaster threshold) will suppress inbox placement even with perfect SPF/DKIM/DMARC.&lt;/li&gt;
&lt;li&gt;Low open/engagement rates over time train Gmail and Outlook's ML filters to deprioritize you specifically, independent of content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 4: Content — check this last, not first
&lt;/h2&gt;

&lt;p&gt;Only once the first three layers are clean does content start to matter. And even then, it's rarely a single trigger word — it's structural: an unusually high link-to-text ratio, image-only emails with no text, a mismatched display name and From address, or missing a plain-text part. Legitimate mail with a slightly awkward subject line still gets delivered when the domain is trusted and the list is clean.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this order, and not the reverse
&lt;/h2&gt;

&lt;p&gt;Filters layer their decisions the same way this checklist does — auth first, reputation next, behavior third, content last as a tiebreaker. If you start by rewriting subject lines on a domain with a broken DMARC record, you're optimizing a variable that isn't the bottleneck. You'll "fix" something, see no change, and conclude the whole system is a black box. It isn't. It's just being diagnosed backwards.&lt;/p&gt;

&lt;p&gt;One thing this checklist explicitly does not include: tricks to fool spam filters — hidden text, invisible characters, zero-width joiners, cloaked links. Those get flagged the moment a provider updates its model, and the damage to domain reputation outlasts the campaign that triggered it. There's no shortcut around clean infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick self-check
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Do SPF, DKIM, and DMARC all pass and align? (dig + MXToolbox)&lt;/li&gt;
&lt;li&gt;Is the domain/IP on any blocklist? (MXToolbox blacklist check)&lt;/li&gt;
&lt;li&gt;What's the domain's reputation in Google Postmaster Tools?&lt;/li&gt;
&lt;li&gt;What's the bounce rate and complaint rate on recent sends?&lt;/li&gt;
&lt;li&gt;Only after 1–4 are clean: review subject lines, HTML structure, and link ratios.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Running through this manually across SPF, DKIM, DMARC, blocklists, and warm-up takes real time to get right the first time. The &lt;strong&gt;Cold Email Deliverability Kit&lt;/strong&gt; (&lt;a href="https://remixdenis.gumroad.com/l/kit" rel="noopener noreferrer"&gt;https://remixdenis.gumroad.com/l/kit&lt;/a&gt;) is a 20-minute technical diagnostic checklist covering exactly these steps, plus a separate content-audit checklist and a compliant HTML/SMTP boilerplate — no evasion tricks, just the setup that gets mail delivered. If you want the deeper version with real diagnostic walkthroughs, the course &lt;strong&gt;Deliverability Diagnostics: What Actually Gets Email to the Inbox&lt;/strong&gt; (&lt;a href="https://remixdenis.gumroad.com/l/mclaie" rel="noopener noreferrer"&gt;https://remixdenis.gumroad.com/l/mclaie&lt;/a&gt;) goes further.&lt;/p&gt;

</description>
      <category>email</category>
      <category>marketing</category>
      <category>saas</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
