<?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: Vadim Ivanov</title>
    <description>The latest articles on DEV Community by Vadim Ivanov (@vadimivanov).</description>
    <link>https://dev.to/vadimivanov</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%2F4005114%2Fbd4f0c33-feb3-4ddd-b164-466ac5219a87.jpg</url>
      <title>DEV Community: Vadim Ivanov</title>
      <link>https://dev.to/vadimivanov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vadimivanov"/>
    <language>en</language>
    <item>
      <title>Your email passes SPF and DKIM but still fails DMARC. Here's why</title>
      <dc:creator>Vadim Ivanov</dc:creator>
      <pubDate>Tue, 14 Jul 2026 19:16:58 +0000</pubDate>
      <link>https://dev.to/vadimivanov/your-email-passes-spf-and-dkim-but-still-fails-dmarc-heres-why-58ca</link>
      <guid>https://dev.to/vadimivanov/your-email-passes-spf-and-dkim-but-still-fails-dmarc-heres-why-58ca</guid>
      <description>&lt;h1&gt;
  
  
  Your email passes SPF and DKIM but still fails DMARC. Here's why
&lt;/h1&gt;

&lt;p&gt;You set up SPF. You set up DKIM. You send a test message and both come back pass. Then your DMARC reports show fail, or a receiver quarantines the mail anyway. It reads like a contradiction, and it's the single most common DMARC question I run into.&lt;/p&gt;

&lt;p&gt;The short version: DMARC doesn't care that SPF or DKIM passed. It cares that they passed &lt;em&gt;for your domain&lt;/em&gt;, the one in the From address your recipient actually sees. That extra requirement is called alignment, and it's where almost every "passes auth but fails DMARC" case lives.&lt;/p&gt;

&lt;h2&gt;
  
  
  What DMARC actually checks
&lt;/h2&gt;

&lt;p&gt;SPF and DKIM each authenticate a domain, but not always the domain you'd assume.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SPF authenticates the Return-Path, the envelope sender (RFC5321.MailFrom) where bounces go. It has nothing to do with the visible From address.&lt;/li&gt;
&lt;li&gt;DKIM authenticates whatever domain sits in the signature's &lt;code&gt;d=&lt;/code&gt; tag. That can be your domain, or it can be your email provider's.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DMARC sits on top and adds one rule: at least one of those authenticated domains has to &lt;em&gt;align&lt;/em&gt; with the domain in the visible From header. Per RFC 7489, a message passes DMARC when at least one mechanism produces a pass, and that pass is based on an identifier that is in alignment. One aligned pass is enough. You don't need both.&lt;/p&gt;

&lt;p&gt;So you can have SPF pass for a Return-Path of &lt;code&gt;bounces.sendgrid.net&lt;/code&gt;, and a valid DKIM signature with &lt;code&gt;d=sendgrid.net&lt;/code&gt;, and still fail DMARC, because neither of those is your domain and your From header says &lt;code&gt;you@yourdomain.com&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Relaxed vs strict, and the organizational domain
&lt;/h2&gt;

&lt;p&gt;Alignment has two modes, set by the &lt;code&gt;aspf&lt;/code&gt; and &lt;code&gt;adkim&lt;/code&gt; tags in your DMARC record. Both default to relaxed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Relaxed (the default): the two domains only need to share the same organizational domain, the registrable part. &lt;code&gt;news.yourdomain.com&lt;/code&gt; aligns with &lt;code&gt;yourdomain.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Strict: the fully qualified names must match exactly, so &lt;code&gt;news.yourdomain.com&lt;/code&gt; would not align with &lt;code&gt;yourdomain.com&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That organizational domain is worked out using the Public Suffix List, which is how a checker knows &lt;code&gt;yourdomain.co.uk&lt;/code&gt; is the registrable name rather than &lt;code&gt;co.uk&lt;/code&gt;. This matters more than it sounds: I've seen local DMARC filters reject legitimate subdomain mail purely because they had no Public Suffix List configured and couldn't reduce the two names to the same org domain.&lt;/p&gt;

&lt;p&gt;Unless you deliberately set &lt;code&gt;aspf=s&lt;/code&gt; or &lt;code&gt;adkim=s&lt;/code&gt;, you are in relaxed mode, which is more forgiving than most people expect.&lt;/p&gt;

&lt;h2&gt;
  
  
  The failure patterns that actually bite
&lt;/h2&gt;

&lt;p&gt;Nearly every real "passes auth, fails DMARC" case is one of these four.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Your provider sends with its own Return-Path and doesn't sign as you.&lt;/strong&gt; This is the big one. Marketing and transactional platforms send from their own bounce domain, so SPF authenticates &lt;em&gt;their&lt;/em&gt; domain. If they also sign with &lt;code&gt;d=&lt;/code&gt; set to their domain instead of yours, nothing aligns with your From, and DMARC fails even though SPF and DKIM both technically passed. The fix lives in the platform: either a custom Return-Path under your own domain so SPF aligns, or an aligned DKIM signature with &lt;code&gt;d=yourdomain.com&lt;/code&gt;. Most serious platforms support at least one. Turn it on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Forwarding.&lt;/strong&gt; A forwarder relays your message from its own servers, so SPF now checks the forwarder's IP against your SPF record and fails. SPF alignment is gone. If your only DKIM signature also got mangled in transit (a footer appended, headers rewritten), DKIM breaks too, and a message you genuinely sent fails DMARC. This is exactly why a DKIM signature that survives forwarding is worth more to DMARC than SPF is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. A broken DKIM signature leaves only SPF, and SPF doesn't align.&lt;/strong&gt; If your aligned DKIM signature fails to verify, maybe a rotated key, a DNS TXT record split badly, or an intermittent DNS lookup failure, DMARC falls back to SPF. If SPF passes only for a non-aligned Return-Path, you fail. The pass you saw in a quick test was the wrong mechanism carrying you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Strict mode you didn't mean to set.&lt;/strong&gt; If &lt;code&gt;aspf=s&lt;/code&gt; or &lt;code&gt;adkim=s&lt;/code&gt; is in your record and you send from a subdomain, or your provider signs with the org domain while you send from a subdomain, exact-match rejects an alignment that relaxed mode would have accepted.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to diagnose it in about two minutes
&lt;/h2&gt;

&lt;p&gt;Open the raw headers of a message that failed and read the Authentication-Results line. Don't stop at &lt;code&gt;spf=pass&lt;/code&gt; and &lt;code&gt;dkim=pass&lt;/code&gt;. Look at the domains next to them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For SPF, compare &lt;code&gt;smtp.mailfrom&lt;/code&gt; (the Return-Path) with your From domain.&lt;/li&gt;
&lt;li&gt;For DKIM, compare &lt;code&gt;header.d&lt;/code&gt; (the &lt;code&gt;d=&lt;/code&gt; tag) with your From domain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If neither matches your From domain, even under the relaxed org-domain rule, that's your answer: authenticated, but not aligned. If picking through raw headers by hand isn't appealing, an &lt;a href="https://relaymetry.com/tools/email-header-analyzer" rel="noopener noreferrer"&gt;email header analyzer&lt;/a&gt; will pull those domains out and show you whether SPF and DKIM line up with your From. Your DMARC aggregate reports (the &lt;code&gt;rua&lt;/code&gt; address) show the same thing at scale. They break every sending source down by whether SPF and DKIM aligned, which is the fastest way to find the one stream that's failing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix, in one line
&lt;/h2&gt;

&lt;p&gt;Get one identifier to align with your From domain, and prefer DKIM. An aligned DKIM signature with &lt;code&gt;d=&lt;/code&gt; set to your domain survives forwarding and doesn't depend on the Return-Path, so it is the sturdier of the two. Align SPF as well if your platform makes it easy with a custom Return-Path under your domain, but if you only fix one thing, make it DKIM.&lt;/p&gt;

&lt;p&gt;Alignment isn't DMARC being pedantic. It is the whole point of the standard. SPF and DKIM prove that &lt;em&gt;some&lt;/em&gt; domain authorized the mail; alignment is what ties that proof to the name your recipient actually reads in the From line. Without it, a spammer could pass their own SPF and DKIM all day long and still drop your brand into the From field.&lt;/p&gt;

</description>
      <category>email</category>
      <category>security</category>
      <category>dns</category>
      <category>webdev</category>
    </item>
    <item>
      <title>97.8% of the top 10,000 domains have no MTA-STS. Here's how to be in the other 2%</title>
      <dc:creator>Vadim Ivanov</dc:creator>
      <pubDate>Sat, 04 Jul 2026 19:17:19 +0000</pubDate>
      <link>https://dev.to/vadimivanov/978-of-the-top-10000-domains-have-no-mta-sts-heres-how-to-be-in-the-other-2-1bfn</link>
      <guid>https://dev.to/vadimivanov/978-of-the-top-10000-domains-have-no-mta-sts-heres-how-to-be-in-the-other-2-1bfn</guid>
      <description>&lt;p&gt;Of the 10,000 most-visited domains on the web, 97.8% have no MTA-STS policy at all. Not misconfigured. Not weak. Just absent. I scanned the Tranco top 10,000 in June and MTA-STS is the single most-ignored email-security control I measured, by a wide margin.&lt;/p&gt;

&lt;p&gt;For comparison, in the same scan a third of those domains had no DMARC, which people already treat as a problem worth writing about. Missing MTA-STS is nearly three times as common as that, and almost nobody mentions it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What MTA-STS actually protects
&lt;/h2&gt;

&lt;p&gt;SMTP encryption is opportunistic. When one mail server hands a message to another, it tries STARTTLS to upgrade the connection to TLS, but if the upgrade fails it usually just delivers in plaintext instead of refusing. That fallback is the hole. An attacker positioned between the two servers can strip the STARTTLS offer, or present a bad certificate, and the sending server shrugs and delivers over an unencrypted connection anyway. The mail goes through, and nobody sees a downgrade happen.&lt;/p&gt;

&lt;p&gt;MTA-STS (RFC 8461) closes that hole. You publish a policy that says, in effect, "mail for my domain must be delivered over TLS, to a server whose certificate actually validates and matches one of my listed MX hosts." A sending server that supports MTA-STS reads that policy and, in enforce mode, refuses to deliver if the connection can't be secured. Downgrade stripped? Certificate wrong? The message is held, not leaked.&lt;/p&gt;

&lt;p&gt;TLS-RPT (RFC 8460) is the companion. It's a DNS record that asks other providers to send you a daily report of how TLS negotiation went for mail to your domain, including failures. It's how you find out something is wrong before it becomes a habit. In the scan, 97.1% of domains had no TLS-RPT record either, so almost everyone who skips the policy also skips the reporting that would tell them they need one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why adoption is this low
&lt;/h2&gt;

&lt;p&gt;Two reasons, and neither is that MTA-STS is hard to understand.&lt;/p&gt;

&lt;p&gt;The first is moving parts. DMARC is one DNS record. MTA-STS is a DNS record plus a policy file served over HTTPS at a fixed well-known URL on a dedicated subdomain, plus your MX hosts presenting valid certificates that match the policy. That's a web endpoint, a DNS entry, and mail-server TLS all having to agree. None of it is difficult, but it's more surface than pasting one TXT record, and more surface is where adoption goes to die.&lt;/p&gt;

&lt;p&gt;The second is that nothing forced it. DMARC adoption jumped when Google and Yahoo made authentication a requirement for bulk senders, a hard deadline with deliverability consequences. MTA-STS has no equivalent forcing function. No inbox provider bounces your mail for lacking it, so it sits permanently at the bottom of the list, behind every task that has a deadline attached.&lt;/p&gt;

&lt;p&gt;Here's the part that surprised me: it isn't a small-domain problem. Among the top 1,000 domains, 96.9% still have no MTA-STS, barely better than the long tail. And the few that do adopt it tend to mean it. Of the roughly 220 domains publishing a policy, 59% run it in enforce mode and most of the rest in testing. So this isn't a case of people turning it on and leaving it half-configured. It's a case of almost nobody turning it on at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to be in the other 2%
&lt;/h2&gt;

&lt;p&gt;The rollout mirrors DMARC's, and you should treat it the same way: report first, enforce later.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stand up the policy file. Serve &lt;code&gt;https://mta-sts.yourdomain.com/.well-known/mta-sts.txt&lt;/code&gt; with your MX hosts listed, &lt;code&gt;max_age&lt;/code&gt; set, and start at &lt;code&gt;mode: testing&lt;/code&gt;. Testing mode changes nothing about delivery yet; it just makes your policy visible.&lt;/li&gt;
&lt;li&gt;Publish the DNS record. Add the &lt;code&gt;_mta-sts&lt;/code&gt; TXT record with a version and an &lt;code&gt;id&lt;/code&gt;. You bump the &lt;code&gt;id&lt;/code&gt; whenever the policy changes so senders know to refetch.&lt;/li&gt;
&lt;li&gt;Turn on TLS-RPT. Add the &lt;code&gt;_smtp._tls&lt;/code&gt; TXT record pointing at a mailbox. Now you get reports about TLS successes and failures to your domain.&lt;/li&gt;
&lt;li&gt;Read the reports, then enforce. Watch a couple of weeks of TLS-RPT data. If your MX hosts are negotiating TLS cleanly, flip the policy from &lt;code&gt;testing&lt;/code&gt; to &lt;code&gt;enforce&lt;/code&gt;. If something's failing, you'll see it in the reports before it can hurt you, which is the whole point of starting in testing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The certificate on your MX hosts has to be valid and has to match a name in your policy, so the most common snag is a mail server with a self-signed or mismatched cert that was fine under opportunistic TLS and isn't fine under a policy that checks. Testing mode surfaces exactly that, which is why you don't skip it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;MTA-STS is the rare control where the hard part is genuinely just doing it. The spec is stable, the failure mode it prevents is real, and adoption is at 2% not because it's controversial but because nothing makes anyone finish it. If you already run DMARC, you've done the harder conceptual work; MTA-STS is mostly plumbing on top. The 2% who bothered aren't smarter, they just got to it.&lt;/p&gt;

&lt;p&gt;I published the full aggregate from this scan as an open dataset (SPF, DKIM, DMARC, MTA-STS, TLS-RPT, BIMI across the Tranco top 10,000, aggregate only) here: &lt;a href="https://github.com/relaymetry/state-of-email-authentication" rel="noopener noreferrer"&gt;https://github.com/relaymetry/state-of-email-authentication&lt;/a&gt; — it's CC BY 4.0, so use the numbers however you like.&lt;/p&gt;

&lt;p&gt;Disclosure: I'm the founder of Relaymetry, a free SPF/DKIM/DMARC/MTA-STS checker. If you want to check your own domain's MTA-STS policy and TLS-RPT record, &lt;a href="https://relaymetry.com/mta-sts-explained" rel="noopener noreferrer"&gt;Relaymetry walks through it here&lt;/a&gt;, no signup required.&lt;/p&gt;

</description>
      <category>security</category>
      <category>email</category>
      <category>dns</category>
      <category>devops</category>
    </item>
    <item>
      <title>SPF's 10-lookup limit: why your SPF silently fails, and how to fix it</title>
      <dc:creator>Vadim Ivanov</dc:creator>
      <pubDate>Fri, 03 Jul 2026 13:53:40 +0000</pubDate>
      <link>https://dev.to/vadimivanov/spfs-10-lookup-limit-why-your-spf-silently-fails-and-how-to-fix-it-3hg</link>
      <guid>https://dev.to/vadimivanov/spfs-10-lookup-limit-why-your-spf-silently-fails-and-how-to-fix-it-3hg</guid>
      <description>&lt;p&gt;Your SPF record can be perfectly valid, publish without a single error, and still fail every time it is checked. The reason is a rule most people never learn until it bites them: SPF is allowed at most ten DNS lookups per evaluation, and going over does not degrade gracefully. It fails outright.&lt;/p&gt;

&lt;p&gt;In a scan I ran across the top 10,000 domains earlier this year, 1.7% were already over the limit. That sounds small until you realize these are among the most-managed domains on the web, and the number only goes up as a domain adds senders. It is the kind of problem you grow into without noticing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the limit actually is
&lt;/h2&gt;

&lt;p&gt;RFC 7208, the SPF spec, caps the number of mechanisms that require a DNS lookup at ten per evaluation (section 4.6.4). The mechanisms that count are &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;, and &lt;code&gt;exists&lt;/code&gt;, plus the &lt;code&gt;redirect&lt;/code&gt; modifier. The ones that do not count are &lt;code&gt;ip4&lt;/code&gt;, &lt;code&gt;ip6&lt;/code&gt;, and &lt;code&gt;all&lt;/code&gt;, because they are answered from the record itself without another query.&lt;/p&gt;

&lt;p&gt;Cross ten lookups and the evaluation returns &lt;code&gt;permerror&lt;/code&gt;. That is not a soft "neutral" result you can ignore. A permerror means SPF produced no usable answer, so it cannot give you a pass. For DMARC that counts the same as a fail, and many receivers treat a standalone SPF permerror as a failure on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it is silent
&lt;/h2&gt;

&lt;p&gt;Nothing warns you. The record is syntactically fine, so it publishes cleanly and looks correct in your DNS panel. The count is only evaluated at the receiver, at send time, by expanding every &lt;code&gt;include&lt;/code&gt; down its full chain. You do not see the failure; your recipients' mail servers do, and the only symptom is mail that quietly stops authenticating.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it creeps up on you
&lt;/h2&gt;

&lt;p&gt;The culprit is almost always &lt;code&gt;include:&lt;/code&gt; chains. An include does not cost one lookup, it costs however many the included record costs, recursively. &lt;code&gt;include:_spf.google.com&lt;/code&gt; is around four lookups on its own, because it chains to several sub-records. Add Microsoft 365, a marketing platform, a helpdesk, an invoicing tool, and each one brings its own chain. Nobody adds "six lookups" on purpose; you add &lt;code&gt;include:sendgrid.net&lt;/code&gt;, it looks like one line, and you are quietly over.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to check
&lt;/h2&gt;

&lt;p&gt;Count resolved lookups, not lines. Reading the record by eye undercounts badly because the expensive part is hidden inside the includes. Use a checker that expands every include and reports the real total against the limit of ten. That one number tells you whether you have a problem and how much headroom is left.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to fix it
&lt;/h2&gt;

&lt;p&gt;In rough order of how much they buy you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove what you no longer use. The fastest win is usually deleting includes for senders you stopped using a year ago. Audit the list against who actually sends your mail.&lt;/li&gt;
&lt;li&gt;Drop redundant mechanisms. &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;mx&lt;/code&gt; each cost a lookup. If your MX hosts do not send outbound mail, you do not need &lt;code&gt;mx&lt;/code&gt; in SPF at all.&lt;/li&gt;
&lt;li&gt;Use the provider's consolidated include. Some providers replaced a sprawl of sub-records with one: Microsoft 365 is the classic example, where a single &lt;code&gt;include:spf.protection.outlook.com&lt;/code&gt; replaces the old pile of entries.&lt;/li&gt;
&lt;li&gt;Flatten stable senders. Replace an &lt;code&gt;include:&lt;/code&gt; with the actual &lt;code&gt;ip4:&lt;/code&gt;/&lt;code&gt;ip6:&lt;/code&gt; ranges it resolves to. Those do not count toward the limit, so every include you flatten frees its lookups. The catch is maintenance: if that provider changes its IPs, your record is silently wrong until you update it, so only flatten senders whose ranges are stable. Your own infrastructure is a safe candidate; a big cloud provider's is not, keep those as includes.&lt;/li&gt;
&lt;li&gt;Split senders onto subdomains. The limit is per record. If a source only ever sends as &lt;code&gt;mktg.example.com&lt;/code&gt;, give that subdomain its own SPF record and move its includes there, freeing lookups on your main domain.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The part people miss
&lt;/h2&gt;

&lt;p&gt;SPF is not your only authentication leg, and it is the one with this limit. Aligned DKIM has no lookup cap and survives forwarding, where SPF breaks anyway. If you are fighting to squeeze a sender under the SPF limit, the better move is often to make sure that sender signs with aligned DKIM instead, and stop relying on SPF for it. DMARC only needs one of the two to pass and align, so a sender you cannot fit into SPF can still authenticate cleanly on DKIM.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;The ten-lookup limit is a slow-motion failure: nothing breaks the day you cross it, and by the time you notice, some of your mail has been quietly failing for a while. Check your real resolved-lookup count now, trim what you do not need, flatten the stable senders, and lean on aligned DKIM for the rest. That cleanup is worth the hour: it is the difference between SPF that passes and SPF that silently does not.&lt;/p&gt;

&lt;p&gt;Disclosure: I'm the founder of Relaymetry, a free SPF/DKIM/DMARC/MTA-STS checker that expands your includes and shows the real lookup count. I wrote up the fixes in more detail &lt;a href="https://relaymetry.com/spf-too-many-dns-lookups" rel="noopener noreferrer"&gt;here&lt;/a&gt; if you want to work through your own record.&lt;/p&gt;

</description>
      <category>email</category>
      <category>dns</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to safely move your DMARC policy from p=none to p=reject</title>
      <dc:creator>Vadim Ivanov</dc:creator>
      <pubDate>Thu, 02 Jul 2026 00:27:26 +0000</pubDate>
      <link>https://dev.to/vadimivanov/how-to-safely-move-your-dmarc-policy-from-pnone-to-preject-1mfc</link>
      <guid>https://dev.to/vadimivanov/how-to-safely-move-your-dmarc-policy-from-pnone-to-preject-1mfc</guid>
      <description>&lt;p&gt;Publishing a DMARC record is the easy part. Most domains do it: in a scan I ran across the top 10,000 domains earlier this year, two thirds had a DMARC record, and only about half of those actually enforce it. The hard part, the part most never finish, is moving off &lt;code&gt;p=none&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;p=none&lt;/code&gt; monitors and enforces nothing. It asks receivers to report what they see and take no action on failures, which is exactly the right first step and exactly where most deployments quietly stall. A record stuck at &lt;code&gt;p=none&lt;/code&gt; looks like protection and provides none: anyone can still spoof your domain and receivers will deliver it. The whole point of DMARC, stopping unauthenticated mail that uses your From address, only kicks in at &lt;code&gt;p=quarantine&lt;/code&gt; or &lt;code&gt;p=reject&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is how to get there without blocking your own legitimate mail on the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the three policies actually do
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;p=none&lt;/code&gt;: report only, no enforcement.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;p=quarantine&lt;/code&gt;: mail that fails DMARC is treated as suspicious, usually sent to spam.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;p=reject&lt;/code&gt;: mail that fails DMARC is rejected outright at the SMTP layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DMARC fails for a message when neither SPF nor DKIM produces a result that both passes and aligns with the domain in the visible From header. So the safe path is really one task: make sure every legitimate source of your mail produces an aligned pass before you turn on enforcement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why you can't just flip to p=reject
&lt;/h2&gt;

&lt;p&gt;If you jump straight from &lt;code&gt;p=none&lt;/code&gt; to &lt;code&gt;p=reject&lt;/code&gt;, every legitimate sender that is not yet aligned starts getting rejected. That is almost never zero senders. Your marketing platform, your helpdesk, your invoicing system, that one server someone set up in 2019, mail forwarded by employees to personal accounts: all of these can be sending as your domain without aligned authentication. &lt;code&gt;p=reject&lt;/code&gt; on day one turns those into hard bounces, and the first you hear of it is a customer who never got their receipt.&lt;/p&gt;

&lt;p&gt;The reports are what let you find those senders before they become a problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: publish p=none and collect reports
&lt;/h2&gt;

&lt;p&gt;Start with:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;rua&lt;/code&gt; is the aggregate-report address. Receivers send a daily XML summary of every source sending as your domain and whether it passed SPF, DKIM, and alignment. Leave it running at least a couple of weeks so you capture the monthly senders (billing, newsletters) as well as the daily ones. You can add &lt;code&gt;ruf&lt;/code&gt; for per-message failure reports, but most receivers do not send them and they can contain message content, so aggregate &lt;code&gt;rua&lt;/code&gt; is what you will actually work from.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: read the reports and inventory your senders
&lt;/h2&gt;

&lt;p&gt;Aggregate reports are XML and painful by eye past a handful. Feed them to a DMARC report viewer and you get a clean list: for each source, how many messages, and whether SPF and DKIM passed and aligned. Sort every source into two buckets: legitimate senders you recognize (your servers, your ESPs, your SaaS tools), and everything else. For each legitimate one, ask: does it produce an aligned pass on SPF or DKIM? You only need one of the two to align, not both.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: fix each legitimate source until it aligns
&lt;/h2&gt;

&lt;p&gt;This is the real work. For each legitimate source that is not yet aligned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ESPs and SaaS senders (Mailchimp, SendGrid, your helpdesk): almost all support aligned DKIM by publishing a CNAME under your domain pointing at their signing key. Turn it on. Aligned DKIM is the better fix because it survives forwarding, where SPF breaks.&lt;/li&gt;
&lt;li&gt;Your own servers: put their IPs in SPF and, ideally, DKIM-sign with a key published under your domain.&lt;/li&gt;
&lt;li&gt;Anything that cannot align (a legacy system, a notifier with no DKIM support): move it behind a relay that can sign, give it its own subdomain so it does not affect your main domain's policy, or retire it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep watching the reports. As you fix sources, their aligned-pass rate climbs. When every source you recognize is passing and aligned, you are ready to enforce.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: ramp to quarantine, then reject
&lt;/h2&gt;

&lt;p&gt;Do not go straight to reject even now. Move to quarantine first:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Watch the reports for a week or two. Quarantine is forgiving: a sender you missed lands in spam rather than vanishing, so you get a warning instead of a catastrophe. Fix what shows up, then move to reject:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;v=DMARC1; p=reject; rua=mailto:dmarc@yourdomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Some guides suggest the &lt;code&gt;pct&lt;/code&gt; tag to enforce on a fraction of mail first (&lt;code&gt;pct=25&lt;/code&gt;, then &lt;code&gt;50&lt;/code&gt;, then &lt;code&gt;100&lt;/code&gt;). It can help, but receiver support for it is uneven, so treat the quarantine-then-reject progression itself as the reliable ramp and &lt;code&gt;pct&lt;/code&gt; as a nice-to-have, not the plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few things that bite people
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Subdomains: a subdomain with no DMARC record of its own falls back to your organizational domain's policy, so &lt;code&gt;p=reject&lt;/code&gt; does cover them by default. Use the &lt;code&gt;sp=&lt;/code&gt; tag if you want subdomains to have a different policy, and don't assume without checking.&lt;/li&gt;
&lt;li&gt;Forwarding and mailing lists: these break SPF always and DKIM when they modify the message, so some forwarded copies of your mail will fail DMARC no matter what you do. That is expected. Aligned DKIM survives clean forwarders, and ARC-aware receivers honor a trusted forwarder's chain. Don't weaken your policy over forwarded failures; they are noise, not your problem.&lt;/li&gt;
&lt;li&gt;Keep reading the reports after you reach reject. New senders appear (a new tool, a new campaign), and you want to catch them before someone complains.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;None of this is hard, it is just patient. The domains stuck at &lt;code&gt;p=none&lt;/code&gt; are not stuck because the last step is difficult; they are stuck because nobody went back to read the reports and finish. Block out the couple of weeks, work the sources one at a time, and you get real protection instead of a record that only looks like it.&lt;/p&gt;

&lt;p&gt;Disclosure: I'm the founder of Relaymetry, a free SPF/DKIM/DMARC/MTA-STS checker. I wrote a step-by-step version with the exact record changes &lt;a href="https://relaymetry.com/dmarc-p-none-to-reject" rel="noopener noreferrer"&gt;here&lt;/a&gt; if you want a checklist to work from.&lt;/p&gt;

</description>
      <category>email</category>
      <category>dns</category>
      <category>dmarc</category>
      <category>security</category>
    </item>
    <item>
      <title>What 10,000 domains actually publish for email authentication in 2026</title>
      <dc:creator>Vadim Ivanov</dc:creator>
      <pubDate>Sat, 27 Jun 2026 09:51:27 +0000</pubDate>
      <link>https://dev.to/vadimivanov/what-10000-domains-actually-publish-for-email-authentication-in-2026-2c12</link>
      <guid>https://dev.to/vadimivanov/what-10000-domains-actually-publish-for-email-authentication-in-2026-2c12</guid>
      <description>&lt;p&gt;Email authentication has been "solved" on paper for years. SPF, DKIM, and DMARC are old standards, every deliverability guide repeats them, and Google and Yahoo made DMARC effectively mandatory for bulk senders in 2024. So I expected the top of the web to be in good shape.&lt;/p&gt;

&lt;p&gt;In June 2026 I ran SPF, DKIM, DMARC, and MTA-STS checks across the Tranco top 10,000 domains, using public resolvers (1.1.1.1 and 8.8.8.8) and the same checks my own tool runs. The records are public DNS, so anyone can reproduce this. The picture is worse than the "solved problem" framing suggests, and the interesting part is not adoption, it is where people stop.&lt;/p&gt;

&lt;h2&gt;
  
  
  A third of the top 10k still have no DMARC
&lt;/h2&gt;

&lt;p&gt;3,318 of the 9,937 domains that resolved (33.4%) publish no DMARC record at all. These are not obscure sites, they are the most-visited domains on the web. Without DMARC a receiver has no published instruction for what to do when SPF and DKIM fail, and you get none of the aggregate reporting that tells you who is sending as you.&lt;/p&gt;

&lt;p&gt;It does get better at the very top. Among the top 1,000 domains, 28.4% have no DMARC, versus 34% across the rest of the 10k. Better, not good.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real problem is p=none, not missing records
&lt;/h2&gt;

&lt;p&gt;This is the number that actually matters. Of the 6,619 domains that do publish DMARC, only 46.5% are at &lt;code&gt;p=reject&lt;/code&gt;. About a quarter (26%) are still sitting at &lt;code&gt;p=none&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;p=none&lt;/code&gt; is monitor-only. It asks receivers to report what they see and to enforce nothing. It is the correct first step: publish &lt;code&gt;p=none&lt;/code&gt;, collect aggregate reports, fix the sources that should be passing, then tighten the policy. The trouble is that &lt;code&gt;p=none&lt;/code&gt; is also where most deployments quietly stop. The reports start arriving, nobody reads them, and the domain sits unprotected behind a policy that does nothing while looking like progress.&lt;/p&gt;

&lt;p&gt;Moving from &lt;code&gt;p=none&lt;/code&gt; to &lt;code&gt;p=reject&lt;/code&gt; is the step that turns DMARC from a dashboard into a defense, and it is the step most people never finish. I wrote up &lt;a href="https://relaymetry.com/dmarc-p-none-to-reject" rel="noopener noreferrer"&gt;the safe way to make that move&lt;/a&gt;, since it is the question I get most often: read your aggregate reports until every legitimate source aligns, go to &lt;code&gt;p=quarantine&lt;/code&gt;, then &lt;code&gt;p=reject&lt;/code&gt;, raising &lt;code&gt;pct&lt;/code&gt; if you want to ease in.&lt;/p&gt;

&lt;h2&gt;
  
  
  SPF is widespread but quietly broken on some domains
&lt;/h2&gt;

&lt;p&gt;25% of the domains have no SPF record, higher than I expected for the top of the web. A smaller but more interesting group, 1.7%, publish an SPF record that exceeds the 10 DNS-lookup limit from RFC 7208. Once you cross that limit the record returns a permerror, so SPF effectively fails even though a record exists and looks fine to the eye. This usually creeps in through &lt;code&gt;include:&lt;/code&gt; chains: you add a few SaaS senders, each brings its own includes, and one day you are over ten lookups without having changed anything visible. It is the kind of failure you only catch if you count.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transport security is basically unused
&lt;/h2&gt;

&lt;p&gt;This is the most lopsided result in the scan. 97.8% of the domains have no MTA-STS policy (RFC 8461), and 97.1% publish no TLS-RPT. MTA-STS is what lets a sending server insist on TLS and a valid certificate when delivering to you, closing the downgrade gap that plain STARTTLS leaves open. Nearly the entire top 10k has skipped it. Some of that is fair, MTA-STS needs a policy file served over HTTPS on an &lt;code&gt;mta-sts.&lt;/code&gt; subdomain plus a DNS record, so it is more work than a single TXT entry. But "more work" does not explain a 2% adoption rate at the top of the web.&lt;/p&gt;

&lt;h2&gt;
  
  
  BIMI is still early
&lt;/h2&gt;

&lt;p&gt;8.9% of domains publish a BIMI record, climbing to 15.7% in the top 1,000. That fits: BIMI rewards brands that already enforce DMARC and have budget for a verified mark. It is the one area where low adoption is genuinely fine, BIMI is optional and brand-driven, not a security baseline.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I take from this
&lt;/h2&gt;

&lt;p&gt;The headline is not "people don't adopt email auth." Most of the top 10k publish SPF and DMARC. The gap is follow-through: a DMARC record stuck at &lt;code&gt;p=none&lt;/code&gt;, an SPF record one include over the limit, a transport-security feature nobody enabled. Each of these looks like a configured domain and behaves like an unconfigured one.&lt;/p&gt;

&lt;p&gt;If you own a sending domain, the highest-value 20 minutes you can spend is checking which of these you are actually in: is your DMARC enforcing or just watching, is your SPF under the lookup limit, and have you ever published an MTA-STS policy. The records are public, so the answer is one DNS lookup away.&lt;/p&gt;

&lt;p&gt;Disclosure: I'm the founder of Relaymetry, a free SPF/DKIM/DMARC/MTA-STS checker, which is the tool I used to run this scan. The numbers are from a June 2026 crawl of the Tranco top 10,000; happy to share more on the methodology if anyone wants it.&lt;/p&gt;

</description>
      <category>security</category>
      <category>dns</category>
      <category>email</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
