<?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: Petr Michal</title>
    <description>The latest articles on DEV Community by Petr Michal (@petr_michal_178dc4f87ad91).</description>
    <link>https://dev.to/petr_michal_178dc4f87ad91</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%2F4048945%2Fbe90c809-dd24-48b8-8939-345609d0779f.png</url>
      <title>DEV Community: Petr Michal</title>
      <link>https://dev.to/petr_michal_178dc4f87ad91</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/petr_michal_178dc4f87ad91"/>
    <language>en</language>
    <item>
      <title>The SPF redirect trap: why -all can make redirect= useless</title>
      <dc:creator>Petr Michal</dc:creator>
      <pubDate>Tue, 25 Aug 2026 12:03:53 +0000</pubDate>
      <link>https://dev.to/petr_michal_178dc4f87ad91/the-spf-redirect-trap-why-all-can-make-redirect-useless-3h0f</link>
      <guid>https://dev.to/petr_michal_178dc4f87ad91/the-spf-redirect-trap-why-all-can-make-redirect-useless-3h0f</guid>
      <description>&lt;h1&gt;
  
  
  The SPF &lt;code&gt;redirect&lt;/code&gt; trap: why &lt;code&gt;-all&lt;/code&gt; can make &lt;code&gt;redirect=&lt;/code&gt; useless
&lt;/h1&gt;

&lt;p&gt;SPF records often look simple until you start combining mechanisms and modifiers.&lt;/p&gt;

&lt;p&gt;One particularly easy mistake is to write a record like this:&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 include:_spf.google.com -all redirect=_spf.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first glance, it seems reasonable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;authorize Google,&lt;/li&gt;
&lt;li&gt;reject everything else,&lt;/li&gt;
&lt;li&gt;and use another SPF policy through &lt;code&gt;redirect=&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the &lt;code&gt;redirect=&lt;/code&gt; part will never be used.&lt;/p&gt;

&lt;p&gt;The reason is an important detail of how SPF evaluation works.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;redirect=&lt;/code&gt; is not a fallback after &lt;code&gt;-all&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;An SPF record is evaluated mechanism by mechanism.&lt;/p&gt;

&lt;p&gt;For example:&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:192.0.2.10 include:_spf.google.com -all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The receiver checks the mechanisms until one matches.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;all&lt;/code&gt; mechanism is special because it &lt;strong&gt;always matches&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;effectively says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If nothing before this matched, return SPF Fail.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now consider this record again:&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 include:_spf.google.com -all redirect=_spf.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once SPF reaches &lt;code&gt;-all&lt;/code&gt;, it already has a result.&lt;/p&gt;

&lt;p&gt;There is no reason to evaluate &lt;code&gt;redirect=&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;redirect&lt;/code&gt; modifier is only used when none of the mechanisms in the record produce a match.&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;all&lt;/code&gt; always matches, a record containing &lt;code&gt;all&lt;/code&gt; prevents &lt;code&gt;redirect=&lt;/code&gt; from being used.&lt;/p&gt;

&lt;h2&gt;
  
  
  What &lt;code&gt;redirect=&lt;/code&gt; is actually for
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;redirect&lt;/code&gt; modifier is useful when several domains should share one central SPF policy.&lt;/p&gt;

&lt;p&gt;Imagine these domains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example.com
example.net
example.org
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of maintaining the same SPF configuration independently on every domain, they can redirect to a central policy.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example.com TXT "v=spf1 redirect=_spf.example.com"
example.net TXT "v=spf1 redirect=_spf.example.com"
example.org TXT "v=spf1 redirect=_spf.example.com"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the central record might contain:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now the sending policy can be maintained in one place.&lt;/p&gt;

&lt;p&gt;This is very different from &lt;code&gt;include:&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;redirect=&lt;/code&gt; vs &lt;code&gt;include:&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;These two are easy to confuse.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;include:&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;include:&lt;/code&gt; when you want to authorize senders defined by another SPF record &lt;strong&gt;as part of your own policy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Example:&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 include:_spf.google.com ip4:192.0.2.10 -all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Google is allowed, this IP is allowed, and everything else should fail.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your domain still owns the final policy.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;redirect=&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;redirect=&lt;/code&gt; when another domain should provide the &lt;strong&gt;entire remaining SPF policy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Example:&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 redirect=_spf.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A useful mental shortcut is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;include:  → add another policy
redirect= → use another policy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That distinction matters when debugging SPF records.&lt;/p&gt;

&lt;h2&gt;
  
  
  A common broken configuration
&lt;/h2&gt;

&lt;p&gt;Consider this:&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:192.0.2.10 -all redirect=_spf.provider.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Someone may expect the following behavior:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;allow &lt;code&gt;192.0.2.10&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;if it does not match, check &lt;code&gt;_spf.provider.com&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;otherwise fail.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But SPF does not work that way.&lt;/p&gt;

&lt;p&gt;The real evaluation is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;check &lt;code&gt;ip4:192.0.2.10&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;if it does not match, evaluate &lt;code&gt;-all&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;all&lt;/code&gt; matches every sender,&lt;/li&gt;
&lt;li&gt;return SPF Fail,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;redirect=&lt;/code&gt; is never used.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you really want the provider to define the policy, the record should instead 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 redirect=_spf.provider.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want both your own IP address and the provider's authorized senders, &lt;code&gt;include:&lt;/code&gt; is usually the appropriate mechanism:&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:192.0.2.10 include:_spf.provider.com -all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The position of &lt;code&gt;redirect=&lt;/code&gt; can be misleading
&lt;/h2&gt;

&lt;p&gt;Another subtle point is that &lt;code&gt;redirect=&lt;/code&gt; is a &lt;strong&gt;modifier&lt;/strong&gt;, not a mechanism.&lt;/p&gt;

&lt;p&gt;So it should not be read as if SPF simply processes it from left to right like &lt;code&gt;ip4&lt;/code&gt;, &lt;code&gt;include&lt;/code&gt;, &lt;code&gt;mx&lt;/code&gt;, or &lt;code&gt;all&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This record:&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 redirect=_spf.example.com -all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;does not mean:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Try redirect first, then &lt;code&gt;-all&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The presence of the &lt;code&gt;all&lt;/code&gt; mechanism still means SPF can produce a result without using the redirect.&lt;/p&gt;

&lt;p&gt;A good mental model is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Evaluate the SPF mechanisms first.&lt;br&gt;
Only if none of them match can &lt;code&gt;redirect=&lt;/code&gt; provide another SPF record to evaluate.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why this matters in production
&lt;/h2&gt;

&lt;p&gt;A broken SPF redirect can be surprisingly difficult to notice.&lt;/p&gt;

&lt;p&gt;The DNS record is syntactically valid.&lt;/p&gt;

&lt;p&gt;A DNS lookup succeeds.&lt;/p&gt;

&lt;p&gt;The domain has an SPF record.&lt;/p&gt;

&lt;p&gt;Yet mail from an expected sender may still fail SPF because the redirected policy was never evaluated.&lt;/p&gt;

&lt;p&gt;This becomes especially confusing when organizations centralize SPF records across many domains.&lt;/p&gt;

&lt;p&gt;A small mistake in the parent policy can affect multiple domains at once.&lt;/p&gt;

&lt;p&gt;When debugging this kind of issue, check:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;whether the record contains an &lt;code&gt;all&lt;/code&gt; mechanism,&lt;/li&gt;
&lt;li&gt;whether &lt;code&gt;redirect=&lt;/code&gt; is actually reachable,&lt;/li&gt;
&lt;li&gt;whether you really need &lt;code&gt;redirect=&lt;/code&gt; or should use &lt;code&gt;include:&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;the SPF result returned by the redirected domain,&lt;/li&gt;
&lt;li&gt;the total number of DNS-querying SPF terms.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A simple rule to remember
&lt;/h2&gt;

&lt;p&gt;If your SPF record contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and also:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;redirect=...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you should take a closer look.&lt;/p&gt;

&lt;p&gt;In most cases, that combination indicates that the redirect is not doing what the author intended.&lt;/p&gt;

&lt;p&gt;Use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;redirect=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;when another domain should define the SPF policy.&lt;/p&gt;

&lt;p&gt;Use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;include:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;when another SPF policy should be incorporated into your own.&lt;/p&gt;

&lt;p&gt;And use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;when you are ready to explicitly fail senders that did not match any previous mechanism.&lt;/p&gt;




&lt;p&gt;If you are debugging a more complex configuration, I wrote a more detailed guide to the &lt;a href="https://mxfend.com/spf-redirect-modifier/" rel="noopener noreferrer"&gt;SPF redirect modifier&lt;/a&gt;, including &lt;code&gt;redirect=&lt;/code&gt; vs &lt;code&gt;include:&lt;/code&gt;, DNS lookup behavior, common errors, and practical examples.&lt;/p&gt;

&lt;p&gt;You can also inspect an SPF record directly with the &lt;a href="https://mxfend.com/spf-checker/" rel="noopener noreferrer"&gt;MXFend SPF checker&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>email</category>
      <category>dns</category>
      <category>security</category>
      <category>devops</category>
    </item>
    <item>
      <title>How BIMI Inspection Actually Works: DNS Records, Selectors, SVG Logos and DMARC</title>
      <dc:creator>Petr Michal</dc:creator>
      <pubDate>Wed, 19 Aug 2026 20:28:54 +0000</pubDate>
      <link>https://dev.to/petr_michal_178dc4f87ad91/how-bimi-inspection-actually-works-dns-records-selectors-svg-logos-and-dmarc-5e3l</link>
      <guid>https://dev.to/petr_michal_178dc4f87ad91/how-bimi-inspection-actually-works-dns-records-selectors-svg-logos-and-dmarc-5e3l</guid>
      <description>&lt;h1&gt;
  
  
  How BIMI Inspection Actually Works: DNS Records, Selectors, SVG Logos and DMARC
&lt;/h1&gt;

&lt;p&gt;BIMI looks simple at first glance: publish a DNS record, point it at a logo, and wait for mailbox providers to display it.&lt;/p&gt;

&lt;p&gt;In practice, there are several independent pieces that have to line up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the BIMI Assertion Record must exist at the expected DNS name;&lt;/li&gt;
&lt;li&gt;the correct selector has to be queried;&lt;/li&gt;
&lt;li&gt;the logo location has to be reachable;&lt;/li&gt;
&lt;li&gt;the SVG has to meet BIMI-specific constraints;&lt;/li&gt;
&lt;li&gt;the optional evidence document has to be valid for the intended use;&lt;/li&gt;
&lt;li&gt;DMARC must meet BIMI's enforcement prerequisite;&lt;/li&gt;
&lt;li&gt;and even then, mailbox providers can still apply their own eligibility, reputation, and policy checks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article walks through the inspection process from the DNS query outward.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Start with the BIMI DNS name
&lt;/h2&gt;

&lt;p&gt;The conventional BIMI selector is &lt;code&gt;default&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For a domain such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the first DNS name to inspect is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;default._bimi.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A BIMI implementation can use a non-default selector, but it should not blindly guess or enumerate selectors. A specific selector is normally relevant when the message or sender configuration actually requests one.&lt;/p&gt;

&lt;p&gt;That distinction matters because "no record at &lt;code&gt;default&lt;/code&gt;" and "BIMI is not configured anywhere for this domain" are not necessarily the same statement.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Inspect the published BIMI Assertion Record
&lt;/h2&gt;

&lt;p&gt;A BIMI record is published as DNS TXT.&lt;/p&gt;

&lt;p&gt;A simplified record may 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=BIMI1; l=https://example.com/logo.svg; a=https://example.com/evidence.pem;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important parts are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;v=&lt;/code&gt; — BIMI version;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;l=&lt;/code&gt; — logo location;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;a=&lt;/code&gt; — evidence document location, when present.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An inspector should not stop at "a TXT record exists." It should also check whether the record is structurally usable and whether there are ambiguous or conflicting records.&lt;/p&gt;

&lt;p&gt;Multiple BIMI records for the same selector are especially important to surface rather than silently merging or choosing one.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The selector is part of the inspection
&lt;/h2&gt;

&lt;p&gt;The selector is not just a UI detail.&lt;/p&gt;

&lt;p&gt;It changes the DNS name being queried:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;selector&amp;gt;._bimi.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;default._bimi.example.com
marketing._bimi.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those are two different DNS records.&lt;/p&gt;

&lt;p&gt;A useful BIMI inspector should therefore show the selector it actually queried and the resulting DNS name, so the operator can verify that the inspection matches the sender's intended configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Follow the logo location
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;l=&lt;/code&gt; value points to the logo asset.&lt;/p&gt;

&lt;p&gt;An inspector can check things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;whether the URL is present;&lt;/li&gt;
&lt;li&gt;whether it is reachable;&lt;/li&gt;
&lt;li&gt;whether the response is actually an SVG;&lt;/li&gt;
&lt;li&gt;whether the SVG is structurally compatible with BIMI expectations;&lt;/li&gt;
&lt;li&gt;whether obvious asset problems make the BIMI setup unusable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where many apparently "valid" DNS configurations fail in practice.&lt;/p&gt;

&lt;p&gt;The DNS record may parse correctly while the referenced logo is unavailable or unsuitable.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. SVG Tiny PS is not the same as "any SVG"
&lt;/h2&gt;

&lt;p&gt;A normal SVG that renders perfectly in a browser is not automatically suitable for BIMI.&lt;/p&gt;

&lt;p&gt;BIMI expects a restricted SVG profile. That means an inspection step should treat "valid XML/SVG" and "BIMI-compatible SVG" as separate questions.&lt;/p&gt;

&lt;p&gt;This distinction is useful when troubleshooting a setup that looks correct from DNS alone but still does not satisfy BIMI requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Inspect the evidence document separately
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;a=&lt;/code&gt; location is conceptually separate from the logo.&lt;/p&gt;

&lt;p&gt;Depending on the BIMI setup, it may point to an evidence document such as a certificate-related artifact.&lt;/p&gt;

&lt;p&gt;A robust inspector should report the evidence location independently rather than treating the logo and evidence document as one combined resource.&lt;/p&gt;

&lt;p&gt;This also makes troubleshooting easier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DNS record: OK
Logo: OK
Evidence location: problem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is much more actionable than a generic "BIMI failed."&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Check the DMARC prerequisite
&lt;/h2&gt;

&lt;p&gt;BIMI does not operate in isolation from email authentication.&lt;/p&gt;

&lt;p&gt;A domain may have a syntactically correct BIMI record and a valid logo, but still not meet BIMI's DMARC enforcement prerequisite.&lt;/p&gt;

&lt;p&gt;That is why BIMI inspection should include DMARC state rather than only checking &lt;code&gt;_bimi&lt;/code&gt; DNS.&lt;/p&gt;

&lt;p&gt;The useful question is not merely:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does this domain have DMARC?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;but rather:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does the DMARC configuration meet the enforcement prerequisite expected for BIMI?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is an important difference for domains that are still in monitoring-only mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. A technically correct setup still does not guarantee logo display
&lt;/h2&gt;

&lt;p&gt;This is probably the most important operational point.&lt;/p&gt;

&lt;p&gt;Passing all structural checks does &lt;strong&gt;not&lt;/strong&gt; mean Gmail, Yahoo, Apple Mail, or another provider must display the logo.&lt;/p&gt;

&lt;p&gt;Mailbox providers can apply additional requirements and their own reputation, eligibility, certificate, or policy rules.&lt;/p&gt;

&lt;p&gt;So the result of an inspector should be interpreted as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The published BIMI configuration is structurally ready
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your logo is guaranteed to appear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That distinction avoids false confidence and makes the tool more useful for debugging.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. A practical inspection flow
&lt;/h2&gt;

&lt;p&gt;When troubleshooting BIMI, I prefer this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Determine the selector.&lt;/li&gt;
&lt;li&gt;Query &lt;code&gt;&amp;lt;selector&amp;gt;._bimi.&amp;lt;domain&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Confirm exactly one usable BIMI Assertion Record.&lt;/li&gt;
&lt;li&gt;Parse the logo and evidence locations.&lt;/li&gt;
&lt;li&gt;Check the logo resource and BIMI SVG compatibility.&lt;/li&gt;
&lt;li&gt;Check the evidence document location when present.&lt;/li&gt;
&lt;li&gt;Verify the DMARC enforcement prerequisite.&lt;/li&gt;
&lt;li&gt;Only then investigate provider-specific eligibility or reputation issues.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This order separates DNS/configuration failures from provider-side display decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Inspect a real domain
&lt;/h2&gt;

&lt;p&gt;I built a free BIMI Inspector in MXFend that follows this workflow and shows the queried selector, BIMI record, logo/evidence locations, SVG compatibility, and DMARC prerequisite in one place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MXFend BIMI Inspector:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://mxfend.com/bimi-inspector/" rel="noopener noreferrer"&gt;https://mxfend.com/bimi-inspector/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is also a simpler BIMI Checker for a faster basic check:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mxfend.com/bimi-checker/" rel="noopener noreferrer"&gt;https://mxfend.com/bimi-checker/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The distinction is intentional:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BIMI Checker&lt;/strong&gt; — quick configuration check;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BIMI Inspector&lt;/strong&gt; — deeper record, selector, logo/evidence, and DMARC inspection.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Closing thought
&lt;/h2&gt;

&lt;p&gt;BIMI troubleshooting becomes much easier once you stop treating it as one binary DNS check.&lt;/p&gt;

&lt;p&gt;It is really a chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;selector
  -&amp;gt; BIMI DNS record
  -&amp;gt; logo
  -&amp;gt; SVG compatibility
  -&amp;gt; evidence document
  -&amp;gt; DMARC prerequisite
  -&amp;gt; mailbox-provider policy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inspecting each layer separately gives you a much clearer answer to the only question that matters during debugging:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which exact layer is preventing this BIMI configuration from being ready?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://mxfend.com/knowledge/email-authentication/how-bimi-inspection-works/" rel="noopener noreferrer"&gt;MXFend&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>email</category>
      <category>dns</category>
      <category>security</category>
      <category>devops</category>
    </item>
    <item>
      <title>HELO vs EHLO: Why Your SMTP Greeting Can Hurt Email Delivery</title>
      <dc:creator>Petr Michal</dc:creator>
      <pubDate>Fri, 07 Aug 2026 07:44:23 +0000</pubDate>
      <link>https://dev.to/petr_michal_178dc4f87ad91/helo-vs-ehlo-why-your-smtp-greeting-can-hurt-email-delivery-3226</link>
      <guid>https://dev.to/petr_michal_178dc4f87ad91/helo-vs-ehlo-why-your-smtp-greeting-can-hurt-email-delivery-3226</guid>
      <description>&lt;h1&gt;
  
  
  HELO vs EHLO: Why Your SMTP Greeting Can Hurt Email Delivery
&lt;/h1&gt;

&lt;p&gt;Your SPF, DKIM, and DMARC records may all look correct while your mail server still introduces itself as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EHLO localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EHLO server1.internal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That greeting happens before the message body is transmitted and can become one of the first identity signals a receiving server evaluates.&lt;/p&gt;

&lt;h2&gt;
  
  
  What HELO and EHLO actually do
&lt;/h2&gt;

&lt;p&gt;When one mail server connects to another, the receiving server first sends an SMTP banner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;220 mx.receiver.example ESMTP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The sending server then identifies itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EHLO mail.sender.example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;HELO&lt;/code&gt; is the older SMTP greeting.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;EHLO&lt;/code&gt; is the modern Extended SMTP greeting. It also allows the receiving server to advertise capabilities such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;STARTTLS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SIZE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;8BITMIME&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PIPELINING&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DSN&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Modern mail servers normally try &lt;code&gt;EHLO&lt;/code&gt; first and fall back to &lt;code&gt;HELO&lt;/code&gt; only when necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a valid EHLO hostname should look like
&lt;/h2&gt;

&lt;p&gt;A good EHLO identity is normally a publicly resolvable fully qualified domain name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mail.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should not be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;localhost
server1
mail.local
127.0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A strong configuration creates a consistent identity chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sending IP
    ↓ PTR
mail.example.com
    ↓ A or AAAA
Same sending IP
    ↓ EHLO
mail.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is commonly described as forward-confirmed reverse DNS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why PTR and EHLO should agree
&lt;/h2&gt;

&lt;p&gt;Suppose the sending connection comes from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;203.0.113.20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Its PTR record returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mail.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the SMTP session announces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EHLO host123.provider.example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server may still deliver mail, but the identity is inconsistent.&lt;/p&gt;

&lt;p&gt;Receiving systems can combine that inconsistency with other signals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IP reputation&lt;/li&gt;
&lt;li&gt;blocklist status&lt;/li&gt;
&lt;li&gt;SPF, DKIM, and DMARC results&lt;/li&gt;
&lt;li&gt;TLS configuration&lt;/li&gt;
&lt;li&gt;complaint history&lt;/li&gt;
&lt;li&gt;sending patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A HELO mismatch is rarely the only reason a message lands in spam, but it can make an already marginal sender look less trustworthy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common HELO and EHLO mistakes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Using &lt;code&gt;localhost&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This often happens after installing Postfix, Exim, or another MTA without setting the public hostname.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using an internal hostname
&lt;/h3&gt;

&lt;p&gt;Names such as &lt;code&gt;mail.internal&lt;/code&gt; or &lt;code&gt;server1.lan&lt;/code&gt; cannot be verified through public DNS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Missing forward DNS
&lt;/h3&gt;

&lt;p&gt;The PTR points to &lt;code&gt;mail.example.com&lt;/code&gt;, but that hostname does not resolve back to the sending IP.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using the wrong identity on a multi-IP server
&lt;/h3&gt;

&lt;p&gt;A server sends from several IP addresses but announces the same hostname for all of them, even though each IP has a different PTR record.&lt;/p&gt;

&lt;h3&gt;
  
  
  Assuming the From domain must match
&lt;/h3&gt;

&lt;p&gt;The EHLO hostname does not necessarily need to equal the visible From domain.&lt;/p&gt;

&lt;p&gt;For example, this can be valid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EHLO mail.example.net
From: billing@example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What matters most at this layer is that the server identity is valid, resolvable, and consistent with the sending infrastructure.&lt;/p&gt;

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

&lt;p&gt;Start with the actual outbound IP address, not only the domain used in the From header.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find the IP used for outbound SMTP.&lt;/li&gt;
&lt;li&gt;Resolve its PTR record.&lt;/li&gt;
&lt;li&gt;Resolve the returned hostname back to an IP.&lt;/li&gt;
&lt;li&gt;Inspect the EHLO value used by the sending server.&lt;/li&gt;
&lt;li&gt;Verify that the complete identity chain is consistent.&lt;/li&gt;
&lt;li&gt;Check STARTTLS and the server certificate.&lt;/li&gt;
&lt;li&gt;Then verify SPF, DKIM, and DMARC separately.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Example commands
&lt;/h2&gt;

&lt;p&gt;Check reverse DNS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig &lt;span class="nt"&gt;-x&lt;/span&gt; 203.0.113.20 +short
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check forward DNS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig mail.example.com A +short
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inspect an SMTP greeting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl s_client &lt;span class="nt"&gt;-starttls&lt;/span&gt; smtp &lt;span class="nt"&gt;-connect&lt;/span&gt; mail.example.com:25
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact tests available depend on whether the remote server accepts connections from your network and whether port 25 is blocked.&lt;/p&gt;

&lt;h2&gt;
  
  
  HELO is not a replacement for email authentication
&lt;/h2&gt;

&lt;p&gt;A correct EHLO identity does not replace:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SPF&lt;/li&gt;
&lt;li&gt;DKIM&lt;/li&gt;
&lt;li&gt;DMARC&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These mechanisms work at different layers.&lt;/p&gt;

&lt;p&gt;HELO/EHLO and PTR describe the connecting server.&lt;/p&gt;

&lt;p&gt;SPF, DKIM, and DMARC authenticate domains and messages.&lt;/p&gt;

&lt;p&gt;For reliable delivery, both layers should be configured correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the complete guide
&lt;/h2&gt;

&lt;p&gt;The original guide includes more context about HELO, EHLO, DNS identity, and common configuration mistakes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mxfend.com/helo-ehlo-email/" rel="noopener noreferrer"&gt;Read the complete HELO and EHLO guide on MXFend&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also use the &lt;a href="https://mxfend.com/smtp-tls-checker/" rel="noopener noreferrer"&gt;MXFend SMTP TLS Checker&lt;/a&gt; to inspect STARTTLS and related mail-server configuration.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclosure: I built MXFend. The diagnostic tools are free to use and do not require an account.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>email</category>
      <category>dns</category>
      <category>devops</category>
      <category>security</category>
    </item>
    <item>
      <title>Why SPF Breaks After Adding One More Email Provider</title>
      <dc:creator>Petr Michal</dc:creator>
      <pubDate>Mon, 27 Jul 2026 07:43:47 +0000</pubDate>
      <link>https://dev.to/petr_michal_178dc4f87ad91/why-spf-breaks-after-adding-one-more-email-provider-1jle</link>
      <guid>https://dev.to/petr_michal_178dc4f87ad91/why-spf-breaks-after-adding-one-more-email-provider-1jle</guid>
      <description>&lt;h1&gt;
  
  
  Why SPF Breaks After Adding One More Email Provider
&lt;/h1&gt;

&lt;p&gt;Your SPF record may look valid and still produce a &lt;code&gt;PermError&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This often happens after connecting one more service:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google Workspace&lt;/li&gt;
&lt;li&gt;Microsoft 365&lt;/li&gt;
&lt;li&gt;Mailchimp&lt;/li&gt;
&lt;li&gt;Zendesk&lt;/li&gt;
&lt;li&gt;a CRM&lt;/li&gt;
&lt;li&gt;a support platform&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each &lt;code&gt;include:&lt;/code&gt; can trigger additional DNS lookups. SPF allows no more than &lt;strong&gt;10 DNS-triggering mechanisms&lt;/strong&gt; during one evaluation.&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple-looking record
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;v=spf1 include:_spf.google.com include:servers.mcsv.net include:mail.zendesk.com -all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The record contains only three &lt;code&gt;include:&lt;/code&gt; mechanisms, but each included record may contain more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;include&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;redirect&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;a&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;exists&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The limit applies to the &lt;strong&gt;complete evaluation tree&lt;/strong&gt;, not only to the mechanisms visible in the root record.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens after the limit is exceeded
&lt;/h2&gt;

&lt;p&gt;The receiving mail server may return an SPF &lt;code&gt;PermError&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That does not necessarily mean every message will be rejected. The final outcome depends on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the receiving provider,&lt;/li&gt;
&lt;li&gt;whether DKIM passes,&lt;/li&gt;
&lt;li&gt;whether SPF or DKIM aligns with DMARC,&lt;/li&gt;
&lt;li&gt;the receiver's local spam-filtering rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why the problem can appear inconsistent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one provider accepts the message,&lt;/li&gt;
&lt;li&gt;another sends it to spam,&lt;/li&gt;
&lt;li&gt;another reports an authentication failure.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ol&gt;
&lt;li&gt;Expand every &lt;code&gt;include:&lt;/code&gt; recursively.&lt;/li&gt;
&lt;li&gt;Count all DNS-triggering mechanisms in the full tree.&lt;/li&gt;
&lt;li&gt;Identify senders and providers that are no longer used.&lt;/li&gt;
&lt;li&gt;Check whether multiple services authorize the same infrastructure.&lt;/li&gt;
&lt;li&gt;Look for nested includes that consume more lookups than expected.&lt;/li&gt;
&lt;li&gt;Avoid blindly flattening records without understanding how the provider updates its IP ranges.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Common mistakes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Counting only visible includes
&lt;/h3&gt;

&lt;p&gt;Three visible &lt;code&gt;include:&lt;/code&gt; mechanisms do not necessarily mean three DNS lookups.&lt;/p&gt;

&lt;p&gt;An included record may trigger several additional lookups of its own.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding a second SPF record
&lt;/h3&gt;

&lt;p&gt;A domain should publish a single SPF policy.&lt;/p&gt;

&lt;p&gt;Adding another TXT record beginning with &lt;code&gt;v=spf1&lt;/code&gt; does not extend the existing policy. Multiple SPF records can instead cause a &lt;code&gt;PermError&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flattening and forgetting
&lt;/h3&gt;

&lt;p&gt;Flattening can reduce DNS lookups by replacing includes with IP addresses, but it also creates a maintenance obligation.&lt;/p&gt;

&lt;p&gt;If the provider changes its sending infrastructure and the flattened record is not updated, legitimate mail may stop passing SPF.&lt;/p&gt;

&lt;h2&gt;
  
  
  A safer way to fix it
&lt;/h2&gt;

&lt;p&gt;Start by mapping the complete lookup tree.&lt;/p&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;remove obsolete providers,&lt;/li&gt;
&lt;li&gt;remove duplicate authorization paths,&lt;/li&gt;
&lt;li&gt;simplify unnecessary mechanisms,&lt;/li&gt;
&lt;li&gt;confirm which systems still send mail for the domain,&lt;/li&gt;
&lt;li&gt;flatten only where you understand the update and monitoring strategy.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal is not only to get below 10 lookups today. The SPF policy should remain correct when providers change their infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the full lookup tree
&lt;/h2&gt;

&lt;p&gt;I built a free SPF lookup visualizer for this type of diagnosis:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mxfend.com/spf-lookup-visualizer/" rel="noopener noreferrer"&gt;Open the MXFend SPF Lookup Visualizer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It expands the recursive lookup tree and helps show where the SPF lookup budget is being consumed.&lt;/p&gt;

&lt;p&gt;You can also browse more SPF guides in the&lt;br&gt;
&lt;a href="https://mxfend.com/knowledge/spf/" rel="noopener noreferrer"&gt;MXFend SPF knowledge base&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclosure: I built MXFend. The visualizer is free to use and does not require an account.&lt;/p&gt;
&lt;/blockquote&gt;

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