<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Blog Sentinely</title>
    <link>https://sentinely.eu/it/blog/</link>
    <description>Approfondimenti su DMARC, autenticazione email, deliverability e protezione dei domini dallo spoofing.</description>
    <language>it</language>
    <lastBuildDate>Tue, 25 Aug 2026 21:47:20 GMT</lastBuildDate>
    <atom:link href="https://sentinely.eu/it/blog/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Quanti indirizzi IP autorizza davvero il tuo record SPF?</title>
      <link>https://sentinely.eu/it/blog/quanti-ip-autorizza-il-tuo-spf/</link>
      <guid isPermaLink="true">https://sentinely.eu/it/blog/quanti-ip-autorizza-il-tuo-spf/</guid>
      <pubDate>Tue, 25 Aug 2026 21:47:20 GMT</pubDate>
      <description>Counting the addresses an SPF record authorizes is harder than summing its ip4 ranges. The four ways the naive count lies, worked on real ESP records.</description>
      <dc:creator>Valerio Bonaldi</dc:creator>
      <category>Autenticazione email</category>
      <category>Record DNS</category>
      <category>ESP e fornitori</category>
      <category>SPF</category>
      <content:encoded><![CDATA[<p>Chiedi che cosa autorizza il tuo record SPF e ti daranno un aggettivo. Largo. Permissivo. <em>Una superficie d’attacco più ampia.</em> Chiedi un numero e di solito la conversazione si ferma lì.</p>
<p>Il numero si può ottenere. È solo più difficile da ottenere <em>giusto</em> di quanto sembri, e quasi tutti i modi di sbagliarlo lo fanno crescere — cioè vanno nella direzione che vende allarme.</p>
<p>Partiamo dall’include più diffuso che esista:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="plaintext"><code><span class="line"><span>google.com        v=spf1 include:_spf.google.com ~all</span></span>
<span class="line"><span></span></span>
<span class="line"><span>_spf.google.com   v=spf1 ip4:74.125.0.0/16 ip4:209.85.128.0/17</span></span>
<span class="line"><span>                  ip6:2001:4860:4864::/56 ip6:2404:6800:4864::/56</span></span>
<span class="line"><span>                  ip6:2607:f8b0:4864::/56 ip6:2800:3f0:4864::/56</span></span>
<span class="line"><span>                  ip6:2a00:1450:4864::/56 ip6:2c0f:fb50:4864::/56 ~all</span></span></code></pre>
<p><em>Risolti ad agosto 2026. I fornitori cambiano i propri range senza preavviso: risolvi i tuoi, invece di fidarti di un numero stampato in un articolo — compreso questo.</em></p>
<p>La metà IPv4 è aritmetica da scuola media. Un <code>/16</code> sono 2¹⁶ = 65.536 indirizzi, un <code>/17</code> sono 32.768. In tutto: <strong>98.304 indirizzi</strong> abilitati a spedire posta a nome di quel dominio.</p>
<p>Poi c’è la metà IPv6, ed è lì che un conteggio che sembrava facile comincia a mentire. Sei blocchi. Ci torniamo.</p>
<p>E quello era un record <em>semplice</em>: un include, due letterali IPv4, nessun meccanismo dinamico. Ecco i quattro modi in cui il conto sbaglia su tutti gli altri.</p>
<h2 id="regola-1-ip4-e-ip6-non-sono-tutto-il-record">Regola 1: <code>ip4:</code> e <code>ip6:</code> non sono tutto il record</h2>
<p>Alcuni meccanismi non contengono indirizzi. Contengono <em>istruzioni per trovare degli indirizzi</em>, eseguite nell’istante in cui un messaggio arriva.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="plaintext"><code><span class="line"><span>_spf.salesforce.com   v=spf1 exists:%{i}._spf.mta.salesforce.com -all</span></span></code></pre>
<p>Conta i meccanismi <code>ip4:</code> in quel record: zero. Uno strumento che conta i letterali dirà che quel fornitore non autorizza niente — un numero che non è impreciso, è rovesciato.</p>
<p>Quello che il record dice davvero è questo. <code>exists:</code> costruisce un nome di dominio a partire dall’indirizzo IP che si sta connettendo (<code>%{i}</code> è la macro che lo rappresenta), cerca un record A a quel nome, e autorizza il mittente se ne trova uno (RFC 7208 §5.7). L’autorizzazione è una domanda che si pone un indirizzo alla volta, e la risposta sta in una zona DNS che non hai modo di elencare. Ho provato con un indirizzo di documentazione — <code>192.0.2.1._spf.mta.salesforce.com</code> risponde NXDOMAIN, quindi quello non è autorizzato — ma per ricostruire l’insieme completo bisognerebbe fare la stessa domanda 4,3 miliardi di volte.</p>
<p><code>a</code>, <code>mx</code> e <code>ptr</code> hanno la stessa forma: si risolvono al momento della valutazione, contro record che possono cambiare da un messaggio all’altro. (<code>ptr</code> è un caso a parte: la §5.5 di RFC 7208 si intitola letteralmente <em>“ptr” (do not use)</em> e dice che il meccanismo non andrebbe pubblicato. Se ne trovi uno nel tuo record, quello è già un risultato.)</p>
<p>Un conteggio onesto fa quindi due cose insieme: somma i letterali e <strong>dichiara</strong> i meccanismi che non ha potuto enumerare. Quello che ne esce è un minimo, mai un totale. Un numero che tace sul terzo tipo non è una misura.</p>
<h2 id="regola-2-ipv4-e-ipv6-non-si-sommano">Regola 2: IPv4 e IPv6 non si sommano</h2>
<p>Torniamo a quei sei blocchi IPv6. Prendiamo un esempio più grosso — l’infrastruttura di invio di Microsoft 365, che pubblica entrambe le famiglie:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="plaintext"><code><span class="line"><span>spf.protection.outlook.com</span></span>
<span class="line"><span>  v=spf1 ip4:40.92.0.0/15 ip4:40.107.0.0/16 ip4:52.100.0.0/15</span></span>
<span class="line"><span>         ip4:52.102.0.0/16 ip4:52.103.0.0/17 ip4:104.47.0.0/17</span></span>
<span class="line"><span>         ip6:2a01:111:f400::/48 ip6:2a01:111:f403::/49</span></span>
<span class="line"><span>         ip6:2a01:111:f403:8000::/51 ip6:2a01:111:f403:c000::/51</span></span>
<span class="line"><span>         ip6:2a01:111:f403:f000::/52 -all</span></span></code></pre>
<p>Il lato IPv4 fa <strong>458.752</strong> indirizzi. Adesso il lato IPv6: un singolo <code>/48</code> contiene 2⁸⁰ indirizzi, e i cinque blocchi insieme fanno circa 2,19 × 10²⁴.</p>
<p>Somma le due metà e ottieni 2,19 × 10²⁴, cioè la stessa cifra di prima. I 458.752 indirizzi IPv4 non sopravvivono all’arrotondamento: sono diciotto ordini di grandezza troppo piccoli per comparire. Un totale unico non è un numero grande, è il numero dell’IPv6 travestito — e per produrlo si è cancellata l’unica parte su cui un sistemista può davvero ragionare.</p>
<p>Quindi: gli IPv4 si contano a <strong>indirizzi</strong>, gli IPv6 a <strong>blocchi</strong>, e non si pubblica mai una cifra sola per entrambi. Chi ti dice che il tuo SPF autorizza settantanove miliardi di miliardi di indirizzi ha sommato le due famiglie e ti sta citando la dimensione di IPv6.</p>
<h2 id="regola-3-i-range-sovrapposti-vanno-fusi-prima">Regola 3: i range sovrapposti vanno fusi prima</h2>
<p>Qui i trabocchetti sono tre, e tutti e tre gonfiano.</p>
<p><strong>Range scritti separati che sono un range solo.</strong> Riguarda il record Microsoft qui sopra. Pubblica sei letterali IPv4, ma <code>52.100.0.0/15</code>, <code>52.102.0.0/16</code> e <code>52.103.0.0/17</code> stanno attaccati uno all’altro: insieme sono un’unica corsa ininterrotta da <code>52.100.0.0</code> a <code>52.103.127.255</code>, 229.376 indirizzi. I letterali sono sei, i blocchi contigui sono <strong>quattro</strong>. Chi dice «sei range» ha contato la punteggiatura, non la superficie.</p>
<p><strong>Lo stesso fornitore contato due volte.</strong> Il record di <code>sendgrid.net</code> finisce già con <code>include:ab.sendgrid.net</code>. Un dominio che pubblica entrambi gli include — cosa in cui è facile ritrovarsi seguendo due guide di configurazione a un anno di distanza — eredita quel secondo record lungo tutte e due le strade. Sommando i letterali alla cieca vengono 238.592 indirizzi. Fondendo prima gli intervalli il numero vero è <strong>237.056</strong>: la differenza, 1.536, è esattamente il sotto-record contato una seconda volta.</p>
<p><strong>Host-bit che non stanno dove pensi.</strong> La §5.6 di RFC 7208 dice che si confrontano solo i bit alti del prefisso, quindi i bit sotto la lunghezza del prefisso, nel letterale pubblicato, sono semplicemente irrilevanti. Il record di <code>_spf-b.microsoft.com</code> contiene <code>ip4:207.46.22.98/29</code>. Non autorizza otto indirizzi a partire da <code>.98</code>: autorizza da <code>207.46.22.96</code> a <code>207.46.22.103</code>, quindi anche <code>.96</code> e <code>.97</code>, e non <code>.104</code>. Prendi il letterale alla lettera e ogni intervallo ti si sfasa da entrambi i lati — il che manda in pezzi, silenziosamente, la fusione del paragrafo precedente.</p>
<p>Qui in ballo ci sono due cifre diverse, e conviene tenerle separate. I range che stanno soltanto uno accanto all’altro gonfiano il conteggio dei <strong>blocchi</strong> lasciando corretto il totale degli indirizzi — è il caso Microsoft. Un fornitore ereditato due volte gonfia gli <strong>indirizzi</strong> stessi — è il caso SendGrid. Gli host-bit letti male rovinano entrambi.</p>
<p>Quello che i tre errori hanno in comune è la direzione. Tutti e tre fanno la cifra <strong>più grande</strong>: un conteggio che salta la fusione non è approssimativo in modo neutro, è sistematicamente sbilanciato verso l’allarme.</p>
<h2 id="regola-4-zero-e-non-lo-so-sono-numeri-diversi">Regola 4: zero e «non lo so» sono numeri diversi</h2>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="plaintext"><code><span class="line"><span>example.com   v=spf1 -all</span></span></code></pre>
<p>Quel record autorizza esattamente zero indirizzi, ed è un fatto vero, utile e difendibile: è quello che dovrebbe pubblicare un dominio che non spedisce posta.</p>
<p>Adesso considera un <code>include:</code> che non si è risolto, o un ramo abbandonato perché il record aveva già esaurito i dieci lookup consentiti (RFC 7208 §4.6.4). Gli indirizzi che ci stanno dietro non sono zero. Sono <em>ignoti</em>, e la risposta onesta è una casella vuota, non una cifra.</p>
<p>La distinzione sembra pedanteria finché non guardi da che parte cade l’errore. Scritto <code>0</code>, un dato ignoto si legge come una <strong>buona notizia</strong>: il record più permissivo del tuo parco, mostrato come il più stretto. E uno strumento che non sa dirti quando non è riuscito a guardare ha zeri che non valgono niente nemmeno altrove.</p>
<h2 id="la-domanda-migliore-quanti-di-quegli-indirizzi-hanno-mai-spedito">La domanda migliore: quanti di quegli indirizzi hanno mai spedito?</h2>
<p>La superficie autorizzata è un elenco di permessi, e da sola non dice nulla su che cosa sia effettivamente in uso. La cifra interessante è la sovrapposizione con la realtà, e i report aggregati DMARC forniscono l’altra metà: ogni report elenca le sorgenti che hanno spedito posta a nome del tuo dominio (RFC 9990 §3.1).</p>
<p>Incrocia i due insiemi e ottieni due numeri utili:</p>
<ul>
<li><strong>autorizzati ∩ osservati</strong> — gli indirizzi che spediscono davvero la tua posta;</li>
<li><strong>autorizzati − osservati</strong> — il peso morto: indirizzi per cui garantisci e che non spediscono un messaggio da mesi.</li>
</ul>
<p>Il peso morto è quasi sempre archeologia. L’ESP da cui sei migrato e che nessuno ha tolto. Un server di posta dismesso due traslochi fa. Un apparato di monitoraggio che ha smesso di mandare email quando qualcuno ne ha spento gli avvisi. Nessuno di questi si annuncia: l’<code>include:</code> continua a risolversi, il record continua a essere valido, e gli indirizzi continuano a essere autorizzati.</p>
<p>Due discipline rendono onesto quel numero, e contano più dell’aritmetica:</p>
<p><strong>«Nessun report» non è «zero mittenti».</strong> Se nella finestra di osservazione non è arrivato niente, non hai imparato nulla sull’uso. Dire a chi ha configurato il reporting la settimana scorsa che nessuno dei suoi 98.304 indirizzi autorizzati spedisce posta sarebbe assurdo, e uno strumento che lo fa sta sottraendo da dati che non ha. L’esito corretto è tacere sull’uso, non esibire un numero grande e preoccupante.</p>
<p><strong>Si contano le sorgenti distinte, non i messaggi.</strong> La domanda è quanti indirizzi autorizzati siano vivi, quindi un server che ha spedito un milione di messaggi vale uno. Pesare per volume produce una cifra grossa e senza alcun rapporto con la superficie che dovrebbe descrivere.</p>
<h2 id="un-spf-largo-non-è-di-per-sé-un-errore">Un SPF largo non è, di per sé, un errore</h2>
<p>Va detto chiaramente, perché il genere a cui questo articolo appartiene di solito chiude lasciando intendere il contrario.</p>
<p>I 98.304 indirizzi di Google non sono sciatteria. Sono la dimensione di una piattaforma di posta che recapita per moltissime organizzazioni, e qualunque fornitore che operi a quella scala autorizzerà un intervallo paragonabile. Non è successo niente di male.</p>
<p>E quella cifra non è nemmeno un voto. Non esiste una soglia oltre la quale un record diventa cattivo, non c’è un valore di riferimento sotto cui stare, e il numero non va messo dietro un semaforo rosso. È una misura — la stessa categoria del numero di host sulla tua rete: utile da sapere, priva di senso come pagella.</p>
<p>Vale anche la pena essere precisi su che cosa quella superficie esponga. Un indirizzo autorizzato non è una porta aperta: è una macchina per la cui posta il tuo dominio si fa garante. Il rischio che rappresenta è condizionato — conta se una di quelle macchine viene compromessa, o se un range torna al fornitore cloud e viene riaffittato a qualcun altro. È una preoccupazione reale, ed è esattamente il motivo per cui la <strong>provenienza</strong> conta più della <strong>dimensione</strong>. Un record che autorizza 98.304 indirizzi di un solo fornitore che usi attivamente sta meglio di uno che ne autorizza 3.000 distribuiti su sei fornitori, quattro dei quali hai smesso di pagare due anni fa.</p>
<h2 id="che-cosa-farsene-di-quel-numero">Che cosa farsene, di quel numero</h2>
<p><strong>Togli i fornitori che non usi più.</strong> È l’unico intervento sempre giusto, non costa niente e riduce insieme la superficie e il conteggio dei lookup. Non richiede alcuna valutazione: serve solo l’elenco, e qualcuno disposto a dire quali voci sono ancora vere. Comincia dal peso morto.</p>
<p><strong>Dai un sottodominio ai mittenti pesanti.</strong> La posta di marketing e quella transazionale spedite da <code>mail.example.com</code>, con un proprio record SPF, tengono piccolo e verificabile a parte il record del dominio aziendale. I range del tuo ESP finiscono così dietro a un nome il cui unico mestiere è la posta massiva, e la compromissione di quella superficie non si porta dietro il peso del tuo dominio principale.</p>
<p><strong>Non ricorrere al flattening.</strong> Sostituire <code>include:_spf.google.com</code> con i range letterali in cui si risolve oggi riduce davvero il conteggio dei lookup, ed è il consiglio standard per i record che hanno sbattuto contro il tetto dei dieci. Ma trasforma un riferimento vivo in un’istantanea, e il fornitore continua a cambiare i range alle tue spalle. Quando ne aggiunge uno, la posta che parte da lì comincia a fallire. Quando ne <strong>rilascia</strong> uno — restituito al pool del cloud, riassegnato a un altro cliente — il tuo record continua ad autorizzare indirizzi che ormai appartengono a un estraneo. È precisamente il rischio che l’espressione «superficie d’attacco» era stata coniata per descrivere, e il flattening lo fabbrica. Merita un articolo a sé, ma la versione breve è che baratta un limite misurabile con un’esposizione che non si vede.</p>
<hr>
<p>Contare la superficie richiede un pomeriggio e un resolver. Sapere quanta ne sia ancora viva richiede i report DMARC su una finestra abbastanza lunga da intercettare anche i mittenti trimestrali, ed è la metà che nessuna ispezione del record può darti. <a href="https://sentinely.eu/it/pricing">Sentinely</a> fa entrambe le cose: misura la superficie autorizzata, dichiara le parti che non ha potuto enumerare invece di arrotondarle a zero, e incrocia il risultato con le sorgenti che i tuoi report mostrano davvero — che è dove il peso morto diventa visibile. Se sei arrivato qui per il taglio sicurezza, <a href="https://sentinely.eu/it/solutions/it-security/">quel lato sta qui</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Il record DMARC è corretto e non arriva nessun report. Sei cause, in ordine.</title>
      <link>https://sentinely.eu/it/blog/report-dmarc-non-arrivano/</link>
      <guid isPermaLink="true">https://sentinely.eu/it/blog/report-dmarc-non-arrivano/</guid>
      <pubDate>Mon, 24 Aug 2026 22:13:55 GMT</pubDate>
      <description>Il record DMARC è valido e i report non arrivano. Le sei cause nell&apos;&apos;ordine in cui vanno verificate, compresa quella di cui non parla nessuno.</description>
      <dc:creator>Valerio Bonaldi</dc:creator>
      <category>Diagnostica email</category>
      <category>Report aggregati</category>
      <category>DMARC</category>
      <category>Record DNS</category>
      <content:encoded><![CDATA[<p>Il record è giusto. L’hai controllato tre volte, un validatore online ti dà ragione, e la casella su cui hai puntato il tag <code>rua=</code> è vuota da una settimana.</p>
<p>Quasi tutti gli elenchi di cause che si trovano in giro sono disordinati, ed è l’unica cosa che un elenco del genere non può permettersi. Le verifiche hanno una sequenza naturale — ognuna dà senso alla successiva — e farle alla rinfusa significa dimostrare due volte la stessa cosa mentre la causa vera aspetta più in basso. Qui sotto c’è la sequenza. Prima ci sono due domande, perché per una buona parte di chi legge la risposta è che non si è rotto niente.</p>
<h2 id="due-domande-che-possono-chiudere-la-faccenda-subito">Due domande che possono chiudere la faccenda subito</h2>
<h3 id="sono-passate-48-ore">Sono passate 48 ore?</h3>
<p>I report aggregati non vengono emessi man mano che la posta viaggia. Ogni report copre un <em>periodo di rilevazione</em>, e RFC 9990 (§3.1.1.4) dice che quel periodo di norma coincide con una giornata UTC che comincia alle 00:00. La generazione e l’invio avvengono dopo che il periodo si è chiuso.</p>
<p>Quindi: se hai pubblicato martedì alle 16:00, il primo periodo che contiene il tuo record si chiude alle 00:00 UTC di mercoledì, e il report viene costruito e spedito qualche tempo dopo. Ventiquattro-quarantotto ore sono l’attesa normale, e i grandi riceventi si distribuiscono dentro quella finestra.</p>
<p>Due cose la allungano:</p>
<ul>
<li><strong>La cache del DNS.</strong> Se il nome <code>_dmarc.example.com</code> prima non esisteva, i resolver hanno messo in cache la sua <em>assenza</em>, non solo il suo contenuto. La cache negativa (RFC 2308) dura un tempo che deriva dal record SOA della zona, e un ricevente che ha guardato un’ora prima della tua pubblicazione non tornerà a guardare finché non scade. Controlla il minimum del tuo SOA prima di dare per scontato che qualcosa non funzioni.</li>
<li><strong>Non puoi chiedere di andare più in fretta.</strong> Il tag <code>ri=</code> serviva a chiedere un intervallo di rilevazione più corto. RFC 9989 lo ha rimosso (Appendice C.5.2) e il registro IANA oggi lo classifica come <em>historic</em>. Pubblicare <code>ri=3600</code> non ottiene niente: è un tag sconosciuto, e i tag sconosciuti vengono ignorati.</li>
</ul>
<h3 id="il-dominio-spedisce-davvero-posta">Il dominio spedisce davvero posta?</h3>
<p>Un ricevente scopre che vuoi i report solo quando interroga la tua policy, e interroga la tua policy solo quando gli è arrivato un messaggio con il tuo dominio nel campo <code>From:</code> (RFC 9990 §3.4).</p>
<p>Niente posta, nessuna interrogazione, nessun report. Se il dominio è parcheggiato, o serve solo un sito web, o l’hai registrato il mese scorso e non ha ancora spedito nulla, il silenzio è l’esito corretto e nessun lavoro sul DNS lo cambierà. Un dominio che manda una manciata di messaggi al giorno è la versione attenuata dello stesso caso: riceverai report solo dai riceventi che hanno visto la tua posta <em>e</em> che gestiscono un programma di reporting, quindi una settimana magra non dimostra che il record sia sbagliato.</p>
<p>Se hai superato entrambe le domande, si scende lungo l’elenco.</p>
<h2 id="le-sei-cause-nellordine-in-cui-vanno-verificate">Le sei cause, nell’ordine in cui vanno verificate</h2>
<ol>
<li><strong>Non c’è nessun record DMARC</strong> dove i riceventi lo cercano.</li>
<li><strong>Il record c’è, ma i riceventi lo scartano</strong> — quasi sempre un punto e virgola mancante.</li>
<li><strong>Il record è valido e non ha il tag <code>rua=</code></strong>, oppure ne ha uno inutilizzabile.</li>
<li><strong>Il <code>rua=</code> è valido e non è il tuo</strong> — i report esistono, e vanno altrove.</li>
<li><strong>È troppo presto</strong> — se ne è parlato sopra.</li>
<li><strong>Stanno arrivando</strong> — e il problema è a valle.</li>
</ol>
<p>Un comando solo risolve le prime quattro:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="text"><code><span class="line"><span>dig +short TXT _dmarc.example.com</span></span></code></pre>
<h3 id="1-nessun-record-dove-i-riceventi-lo-cercano">1. Nessun record dove i riceventi lo cercano</h3>
<p>La ricerca della policy parte dal nome che si ottiene anteponendo <code>_dmarc</code> al dominio scritto nel campo <code>From:</code> (RFC 9989 §4.10.1). Non l’apice, non <code>www</code>, non un CNAME verso la pagina commerciale del fornitore.</p>
<p>L’errore che genera più confusione lo produce il pannello DNS che aggiunge la zona per conto tuo. Hai scritto <code>_dmarc.example.com</code> nel campo <em>nome</em>, il pannello ha appeso <code>.example.com</code>, e il record adesso vive su <code>_dmarc.example.com.example.com</code>, dove nessuno guarderà mai. Il <code>dig</code> qui sopra non restituisce niente e il pannello continua a mostrarti un record che sembra perfetto. Credi al <code>dig</code>, non al pannello.</p>
<p>Ce n’è una versione più insidiosa. Se la posta parte da un sottodominio — <code>From: noreply@mail.example.com</code> — la ricerca guarda prima <code>_dmarc.mail.example.com</code>, e solo se lì non trova un record valido risale verso il dominio organizzativo (RFC 9989 §4.10). Entrambi gli esiti sono normali. Quello che conta per la tua dashboard vuota è che nel secondo caso il record che si applica è quello del dominio padre, e i report di quella posta vanno al <code>rua</code> <strong>del padre</strong>. Tienilo da parte se stai monitorando un sottodominio.</p>
<h3 id="2-il-record-cè-e-i-riceventi-lo-scartano">2. Il record c’è e i riceventi lo scartano</h3>
<p>Tre modi in cui un record pubblicato viene buttato via prima che qualcuno arrivi a leggere il tuo <code>rua</code>:</p>
<p><strong>Più di un record.</strong> Se un’interrogazione restituisce più record DMARC per lo stesso nome, vengono scartati tutti (RFC 9989 §4.10). È il classico strascico di un cambio di fornitore: il record vecchio non è mai stato cancellato e quello nuovo gli è stato messo accanto. <code>dig +short</code> li mostra entrambi. Due record corretti sono peggio di uno.</p>
<p><strong><code>v=</code> non è il primo, o non è esattamente <code>DMARC1</code>.</strong> Il tag di versione deve venire per primo, e il suo valore distingue maiuscole e minuscole. Se manca, se non è in testa o se è scritto diversamente, l’intero record va ignorato (RFC 9989 §4.7). <code>v=dmarc1</code> non è un record DMARC.</p>
<p><strong>Un punto e virgola mancante.</strong> Questo merita una sezione a sé, perché è invisibile e per <em>come</em> fallisce.</p>
<h2 id="un-carattere-il-punto-e-virgola-mancante">Un carattere: il punto e virgola mancante</h2>
<p>Questi due record differiscono per un solo <code>;</code>:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="plaintext"><code><span class="line"><span>v=DMARC1; p=none rua=mailto:dmarc@example.com</span></span></code></pre>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="plaintext"><code><span class="line"><span>v=DMARC1; p=none; rua=mailto:dmarc@example.com</span></span></code></pre>
<p>Aperti nel pannello del DNS sono indistinguibili. Il primo non ti porta nessun report, ed ecco il meccanismo, perché non è quello che quasi tutti immaginano.</p>
<p>La grammatica di RFC 9989 §4.8 definisce il valore di un tag come qualunque carattere stampabile <em>tranne</em> il punto e virgola. Lo spazio rientra. Anche <code>=</code> rientra. Un ricevente che analizza il primo record non si ferma allo spazio: legge il valore di <code>p</code> come <code>none rua=mailto:dmarc@example.com</code>.</p>
<p>Adesso sono vere due cose insieme, ed è la seconda quella che fa male:</p>
<ul>
<li><code>p</code> ha un valore che non è <code>none</code>, <code>quarantine</code> né <code>reject</code>, quindi non è valido;</li>
<li><strong>nel record non c’è più nessun tag <code>rua</code></strong> — è stato inghiottito dentro il valore di <code>p</code>.</li>
</ul>
<p>RFC 9989 §4.10.1 tratta con indulgenza un <code>p</code> non valido, ma l’indulgenza ha una condizione. Se nel record c’è un tag <code>rua</code> con almeno un URI sintatticamente valido, il ricevente si comporta come se il record dicesse <code>p=none</code> e tira dritto — e il reporting sopravvive. Altrimenti «non applica alcuna elaborazione DMARC al messaggio».</p>
<p>Il punto e virgola mancante cancella esattamente il tag che avrebbe salvato la situazione. È per questo che questo refuso è silenzioso invece che rumoroso: non indebolisce la policy, ti toglie i report.</p>
<p>Lo stesso errore in altra forma, meno frequente, è un record con i tag in ordine sbagliato — <code>p=none; v=DMARC1; rua=…</code> — che cade sulla regola della versione vista sopra.</p>
<p>E il rovescio rassicurante, così non ci passi un pomeriggio: un frammento estraneo che non sia una coppia <code>tag=valore</code> <strong>non</strong> è fatale. RFC 9989 §4.8 dice che gli errori di sintassi nel resto del record vengono scartati in favore dei valori di default, oppure ignorati. Sciatto, da ripulire, ma non è il motivo per cui la tua dashboard è vuota.</p>
<h2 id="3-nessun-rua-utilizzabile">3. Nessun <code>rua=</code> utilizzabile</h2>
<p>Il tag è facoltativo per lo standard, e la sua assenza non lascia margini: senza <code>rua</code> i riceventi non devono generare report aggregati per quel dominio (RFC 9989 §4.7). Un record può essere impeccabile, imporre <code>p=reject</code>, e non dirti niente.</p>
<p>Tre modi in cui il tag c’è ma non serve a nulla:</p>
<ul>
<li><strong>Un indirizzo al posto di un URI.</strong> <code>rua=dmarc@example.com</code> non è un URI di reporting DMARC: un URI richiede uno schema. Va scritto <code>rua=mailto:dmarc@example.com</code>. È una dimenticanza facile da fare e difficile da vedere, perché a un lettore umano un indirizzo senza schema sembra del tutto ragionevole.</li>
<li><strong>Solo <code>https:</code>.</strong> I riceventi sono obbligati a supportare <code>mailto:</code>; il supporto a qualunque altro schema è facoltativo, e gli URI con schemi non supportati devono essere ignorati (RFC 9989 §4.7). Un <code>rua</code> solo HTTPS è una scommessa, ricevente per ricevente.</li>
<li><strong>Il vecchio limite di dimensione.</strong> Il suffisso <code>!10m</code> oggi è sintassi obsoleta, e chi genera i report è invitato a ignorarlo (RFC 9989 §4.8). Innocuo se c’è già, inutile da aggiungere.</li>
</ul>
<h2 id="4-il-rua-è-valido-e-non-è-il-tuo">4. Il <code>rua=</code> è valido, e non è il tuo</h2>
<p>È la causa che sopravvive a tutte le verifiche precedenti, ed è quella che quasi nessuno va a cercare.</p>
<p>Un validatore di sintassi ti confermerà che <code>rua=mailto:dmarc@reports.fornitore.example</code> è un URI di reporting ben formato, perché lo è. Quello che nessun validatore può sapere è se quell’indirizzo sia <strong>tuo</strong>. Lo sai solo tu. Così il record supera ogni controllo, lo strumento che stai pagando resta vuoto, e da nessuna parte compare un errore — perché dal punto di vista del protocollo non c’è niente che non va. I report vengono generati, puntuali, tutti i giorni. Vanno da un’altra parte.</p>
<p>Da dove arriva, di solito, quell’altro indirizzo:</p>
<ul>
<li>un fornitore DMARC precedente, dopo la scadenza dell’abbonamento — disdire un contratto non modifica il tuo DNS;</li>
<li>l’agenzia o l’MSP che ha configurato il dominio anni fa, che puntava al proprio account di aggregazione;</li>
<li>una casella interna su un sistema di posta che nel frattempo è stato dismesso.</li>
</ul>
<p>La verifica consiste nel leggere l’elenco con i propri occhi, invece di fidarsi di una spunta verde. Lancia il <code>dig</code> di prima e leggi il valore di <code>rua=</code> per quello che è: una lista di destinazioni separate da virgola. Su ogni voce fatti una domanda sola: <em>chi riceve posta a quell’indirizzo, oggi?</em> Se per una non sai rispondere, l’hai trovata.</p>
<p>Due cose da sapere prima di mettere mano al record:</p>
<p><strong>Essere uno fra tanti è del tutto normale, quindi la correzione di solito è aggiungere, non sostituire.</strong> Ogni destinazione valida dell’elenco riceve la propria copia; non esiste un destinatario principale. Se stai passando da uno strumento a un altro, tienili accesi entrambi per una settimana e confronta, poi togli il vecchio.</p>
<p><strong>Se stai monitorando un sottodominio, controlla anche il padre.</strong> Per la risalita descritta nella causa 1, la posta che parte da un sottodominio privo di un proprio record <code>_dmarc</code> ricade sotto il record del dominio organizzativo — quindi i suoi report arrivano al <code>rua</code> del padre mentre la dashboard del sottodominio resta vuota. Non c’è niente di sbagliato nella configurazione: stai guardando lo scaffale sbagliato.</p>
<h2 id="due-cause-che-non-stanno-nel-record">Due cause che non stanno nel record</h2>
<h3 id="la-destinazione-è-su-un-altro-dominio-e-non-ha-acconsentito">La destinazione è su un altro dominio e non ha acconsentito</h3>
<p>Se l’indirizzo <code>rua</code> sta sotto un dominio organizzativo diverso da quello che pubblica la policy, i riceventi devono prima accertarsi che la destinazione sia d’accordo (RFC 9990 §4). Il motivo è evidente appena lo si dice: senza quel controllo chiunque potrebbe pubblicare un record che dirotta una valanga di report su una vittima.</p>
<p>La verifica è un’interrogazione DNS che fa il ricevente. Prende l’host dal tuo URI <code>rua</code>, gli antepone <code>_report._dmarc</code>, e antepone ancora il dominio da cui è arrivata la policy. Quindi una policy su <code>example.com</code> che chiede <code>rua=mailto:dmarc@reports.example.net</code> produce una richiesta TXT per</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="text"><code><span class="line"><span>example.com._report._dmarc.reports.example.net</span></span></code></pre>
<p>e la risposta deve leggersi come un record DMARC con <code>v=DMARC1</code> in testa. Se quel record non c’è, l’URI <strong>deve essere ignorato</strong> dal ricevente che sta generando il report (RFC 9990 §4). Di nuovo silenzio, senza che si sia rotto niente in nessuno dei posti in cui ti verrebbe da guardare.</p>
<p>Tre conseguenze pratiche:</p>
<ul>
<li><strong>Il record va nella zona della destinazione, non nella tua.</strong> Se i report vanno a un servizio di terze parti, tocca a loro pubblicarlo, e la maggior parte usa una wildcard — <code>*._report._dmarc.&lt;loro dominio&gt;</code> — che copre tutti i clienti in un colpo solo. Se invece i report vanno a una casella su un secondo dominio <strong>tuo</strong>, nessuno lo pubblicherà al posto tuo.</li>
<li><strong>Stesso dominio organizzativo, nessuna verifica.</strong> Una policy su <code>_dmarc.mail.example.com</code> che spedisce a <code>dmarc@example.com</code> non attiva affatto questo controllo.</li>
<li><strong>L’ultima parola ce l’ha la destinazione.</strong> Il record di consenso può a sua volta contenere un <code>rua</code>, che sovrascrive quello della tua policy, vincolato allo stesso host (RFC 9990 §4). È raro, ma è un altro modo legittimo in cui i report finiscono dove non hai deciso tu.</li>
</ul>
<h3 id="è-la-casella-che-se-li-mangia">È la casella che se li mangia</h3>
<p>Un report è una normalissima email con un allegato: un file XML che dovrebbe essere compresso con gzip, trasportato come <code>application/gzip</code> oppure <code>text/xml</code>, con un nome costruito nella forma <code>ricevente!dominio-policy!timestamp-inizio!timestamp-fine.xml.gz</code> (RFC 9990 §3.5.2).</p>
<p>L’oggetto è fissato dallo standard, e questo ti dà una cosa da cercare:</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="text"><code><span class="line"><span>Subject: Report Domain: example.com</span></span>
<span class="line"><span>    Submitter: mx.example.net</span></span>
<span class="line"><span>    Report-ID: 1755820800-example.com@example.net</span></span></code></pre>
<p>Cerca <code>Report Domain:</code> in tutta la casella — spam, quarantena e archivio compresi. Se saltano fuori dei messaggi, tutto quello che c’è scritto sopra è a posto e il problema è a valle. Se non salta fuori niente da nessuna parte, le cause precedenti sono ancora in gioco.</p>
<p>Che cosa se li mangia, grosso modo in ordine di frequenza: le policy sugli allegati che bloccano o rimuovono i file compressi; una regola che li archivia in una cartella che nessuno apre; una casella condivisa la cui quarantena non guarda nessuno; e un indirizzo <code>rua</code> che in realtà non accetta posta, il che produce bounce che tu non vedi mai, perché tornano al ricevente e non a te.</p>
<p>Un dettaglio che ti risparmia una discussione con chi gestisce la posta: il traffico dei report è a sua volta autenticato con DMARC — RFC 9990 §3.5.2 richiede che questi flussi producano un <code>pass</code> allineato. Quando i report finiscono in quarantena si tratta di una scelta del filtro locale, non di un problema di autenticazione.</p>
<h2 id="arrivano-e-la-dashboard-è-comunque-vuota">Arrivano, e la dashboard è comunque vuota</h2>
<p>Se i messaggi li hai trovati, quello che resta sta tutto a valle della consegna.</p>
<p><strong>Stai guardando il dominio sbagliato.</strong> Viene generato un report distinto per ogni dominio della policy incontrato nel periodo (RFC 9990 §3.1). Apri uno degli XML e leggi <code>policy_published/domain</code>: è lo scaffale su cui quei dati sono stati archiviati. Se dice <code>example.com</code> e tu stai guardando <code>mail.example.com</code>, torna alla causa 4.</p>
<p><strong>I duplicati sono stati tolti, ed è giusto così.</strong> Quando chi genera un report lo rispedisce deve riutilizzare il nome di file originale, e il <code>Report-ID</code> esiste proprio perché chi lo riceve possa riconoscere e ignorare i duplicati (RFC 9990 §3.5.2). Un report arrivato due volte che compare una volta sola è il sistema che funziona.</p>
<p><strong>L’importazione ha una sua cadenza.</strong> I report vengono raccolti e analizzati a lotti, non nell’istante in cui atterrano. Se il primo è arrivato venti minuti fa, dagli un’ora prima di aprire una segnalazione.</p>
<hr>
<p>Mentre aspetti il primo report non sei costretto ad aspettare per sapere qualcosa. Un report riassume una giornata di posta; le intestazioni di un singolo messaggio ti dicono che cosa ha concluso un ricevente su quel messaggio, adesso. Se puoi mandarti un messaggio di prova, incolla le sue intestazioni nel nostro <a href="https://sentinely.eu/it/tools/email-header-analyzer/">analizzatore di intestazioni email</a>: legge le dichiarazioni di chi ha ricevuto, non richiede alcun account e non conserva niente.</p>
<p>E quando i report cominceranno ad arrivare, la cosa da tenere d’occhio non è solo che il record continui a essere leggibile, ma che il suo <code>rua</code> continui a nominare te. È il controllo che <a href="https://sentinely.eu/it/pricing">Sentinely</a> fa in continuo, ed è la differenza fra accorgersene oggi e accorgersene al prossimo audit.</p>
<hr>
]]></content:encoded>
    </item>
    <item>
      <title>Il tuo report DMARC dice &quot;fail&quot;. Spesso non è successo niente.</title>
      <link>https://sentinely.eu/it/blog/report-dmarc-fail-ma-email-consegnata/</link>
      <guid isPermaLink="true">https://sentinely.eu/it/blog/report-dmarc-fail-ma-email-consegnata/</guid>
      <pubDate>Mon, 24 Aug 2026 21:38:48 GMT</pubDate>
      <description>Nei report DMARC &quot;fail&quot; significa due cose diverse: allineamento fallito o messaggio bloccato. La regola per distinguerle, su righe di report vere.</description>
      <dc:creator>Valerio Bonaldi</dc:creator>
      <category>Report DMARC</category>
      <category>Report aggregati</category>
      <category>Allineamento</category>
      <category>DMARC</category>
      <content:encoded><![CDATA[<p>Hai pubblicato <code>v=DMARC1; p=none; rua=mailto:...</code> qualche settimana fa, l’XML ha cominciato ad arrivare, e ora stai guardando il primo riepilogo. Una fetta consistente della tua posta è marcata <code>fail</code>. La domanda che viene spontanea è se qualcuno stia falsificando il tuo dominio.</p>
<p>Quasi certamente no. Quello che hai davanti è la parola <code>fail</code> usata per due cose diverse, e gli strumenti che ti mostrano un unico “tasso di fallimento” di solito le fondono. Una delle due significa che un messaggio è stato bloccato. L’altra significa che un messaggio è stato consegnato regolarmente, da un destinatario che ne era perfettamente soddisfatto. Distinguerle richiede circa un minuto per riga, e il resto di questo articolo è quel minuto.</p>
<h2 id="due-cose-diverse-che-si-chiamano-fail">Due cose diverse che si chiamano “fail”</h2>
<p>Un report DMARC aggregato (il formato è specificato in RFC 9990) non è un elenco di messaggi. È un elenco di <em>gruppi</em>: ogni <code>&lt;record&gt;</code> copre un lotto di messaggi arrivati dallo stesso IP sorgente con lo stesso esito di autenticazione, e <code>&lt;count&gt;</code> dice quanti messaggi rappresenta quel lotto. Qualunque percentuale tu veda, da qualunque parte, è pesata su quel numero.</p>
<p>Dentro ogni record ci sono tre livelli, e rispondono a tre domande diverse.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="xml"><code><span class="line"><span style="color:#E1E4E8">&#x3C;</span><span style="color:#85E89D">record</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">  &#x3C;</span><span style="color:#85E89D">row</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">    &#x3C;</span><span style="color:#85E89D">source_ip</span><span style="color:#E1E4E8">>203.0.113.47&#x3C;/</span><span style="color:#85E89D">source_ip</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">    &#x3C;</span><span style="color:#85E89D">count</span><span style="color:#E1E4E8">>128&#x3C;/</span><span style="color:#85E89D">count</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">    &#x3C;</span><span style="color:#85E89D">policy_evaluated</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">      &#x3C;</span><span style="color:#85E89D">disposition</span><span style="color:#E1E4E8">>none&#x3C;/</span><span style="color:#85E89D">disposition</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">      &#x3C;</span><span style="color:#85E89D">dkim</span><span style="color:#E1E4E8">>pass&#x3C;/</span><span style="color:#85E89D">dkim</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">      &#x3C;</span><span style="color:#85E89D">spf</span><span style="color:#E1E4E8">>fail&#x3C;/</span><span style="color:#85E89D">spf</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">    &#x3C;/</span><span style="color:#85E89D">policy_evaluated</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">  &#x3C;/</span><span style="color:#85E89D">row</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">  &#x3C;</span><span style="color:#85E89D">identifiers</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">    &#x3C;</span><span style="color:#85E89D">header_from</span><span style="color:#E1E4E8">>example.com&#x3C;/</span><span style="color:#85E89D">header_from</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">  &#x3C;/</span><span style="color:#85E89D">identifiers</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">  &#x3C;</span><span style="color:#85E89D">auth_results</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">    &#x3C;</span><span style="color:#85E89D">dkim</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">      &#x3C;</span><span style="color:#85E89D">domain</span><span style="color:#E1E4E8">>example.com&#x3C;/</span><span style="color:#85E89D">domain</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">      &#x3C;</span><span style="color:#85E89D">selector</span><span style="color:#E1E4E8">>s1&#x3C;/</span><span style="color:#85E89D">selector</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">      &#x3C;</span><span style="color:#85E89D">result</span><span style="color:#E1E4E8">>pass&#x3C;/</span><span style="color:#85E89D">result</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">    &#x3C;/</span><span style="color:#85E89D">dkim</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">    &#x3C;</span><span style="color:#85E89D">spf</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">      &#x3C;</span><span style="color:#85E89D">domain</span><span style="color:#E1E4E8">>fwd.example.net&#x3C;/</span><span style="color:#85E89D">domain</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">      &#x3C;</span><span style="color:#85E89D">result</span><span style="color:#E1E4E8">>pass&#x3C;/</span><span style="color:#85E89D">result</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">    &#x3C;/</span><span style="color:#85E89D">spf</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">  &#x3C;/</span><span style="color:#85E89D">auth_results</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">&#x3C;/</span><span style="color:#85E89D">record</span><span style="color:#E1E4E8">></span></span></code></pre>
<p><strong><code>&lt;auth_results&gt;</code> — i protocolli hanno verificato qualcosa?</strong> Sono gli esiti grezzi, non interpretati. Qui SPF ha restituito <code>pass</code>, ma guarda per <em>quale</em> dominio è passato: <code>fwd.example.net</code>, non <code>example.com</code>. DKIM ha verificato una firma che porta <code>d=example.com</code>.</p>
<p><strong><code>&lt;policy_evaluated&gt;/&lt;spf&gt;</code> e <code>/&lt;dkim&gt;</code> — hanno verificato <em>e</em> combaciano con il dominio del <code>From:</code>?</strong> Questa è la vista di DMARC, e ha solo due valori: <code>pass</code> o <code>fail</code>. SPF ha verificato per il dominio di qualcun altro, quindi dal punto di vista di DMARC è <code>fail</code>. DKIM ha verificato per il tuo, quindi è <code>pass</code>.</p>
<p><strong><code>&lt;policy_evaluated&gt;/&lt;disposition&gt;</code> — cosa ha fatto davvero il destinatario?</strong> Tre valori: <code>none</code> (consegnato), <code>quarantine</code>, <code>reject</code>.</p>
<p>Il record qui sopra contiene la parola <code>fail</code>, e non è andato storto assolutamente nulla. DMARC passa quando passa <em>almeno uno</em> dei due metodi allineati — la firma DKIM allineata è bastata — quindi il messaggio è stato autenticato, consegnato e corretto. Se la tua dashboard traccia un “tasso di pass SPF” e tu guardi quel numero, questo record ti preoccuperà ogni singolo giorno senza motivo.</p>
<h2 id="la-regola">La regola</h2>
<p>Eccola per intero, e vale la pena tenerla da qualche parte a portata di copia-incolla.</p>
<blockquote>
<p>Un gruppo di messaggi in un report aggregato è un fallimento <strong>vero</strong> se e solo se:</p>
<p><strong>(A)</strong> il destinatario l’ha bloccato — <code>disposition</code> è <code>quarantine</code> o <code>reject</code>; <strong>oppure</strong></p>
<p><strong>(B)</strong> è stato consegnato (<code>disposition</code> è <code>none</code>), la policy in vigore per quel report era <code>p=none</code>, <strong>e</strong> entrambi gli esiti grezzi in <code>&lt;auth_results&gt;</code> sono esattamente <code>fail</code>.</p>
<p>Tutto il resto appartiene al tuo volume, non ai tuoi fallimenti.</p>
</blockquote>
<p>Il caso (A) non richiede interpretazione. Il destinatario ha preso una decisione e te l’ha comunicata. Non importa quali fossero gli esiti grezzi e non importa cosa dica la tua policy: se <code>disposition</code> è <code>quarantine</code> o <code>reject</code>, della tua posta non è arrivata in una casella, e questo merita attenzione tanto se la causa è un attaccante quanto se è un fornitore configurato male.</p>
<p>Il caso (B) è quello che nessuno mette per iscritto. Il messaggio è stato consegnato, entrambi i protocolli hanno fallito del tutto, e l’unico motivo per cui è finito in una casella è che non hai ancora chiesto a nessuno di fermarlo. Quello è spoofing latente: sembra innocuo oggi e diventa un messaggio bloccato il giorno in cui passi all’enforcement.</p>
<p>Nel caso (B) ci sono due dettagli facili da sbagliare.</p>
<p><strong>La policy che conta è quella di quel report, non quella che hai nel DNS oggi.</strong> Ogni report porta con sé la policy che il destinatario ha visto, in <code>&lt;policy_published&gt;/&lt;p&gt;</code>, e descrive una finestra che si è già chiusa — di solito il giorno prima. Se hai cambiato il record martedì, i report di lunedì descrivono ancora la policy di lunedì. La <code>p</code> va letta dal report che hai in mano.</p>
<p><strong>Conta solo il valore esatto <code>fail</code>.</strong> RFC 9990 ammette in <code>&lt;auth_results&gt;</code> diversi altri valori — <code>none</code>, <code>neutral</code>, <code>policy</code>, <code>temperror</code>, <code>permerror</code>, e per SPF anche <code>softfail</code> — e nessuno di questi dimostra alcunché. Un <code>temperror</code> significa che il destinatario non è riuscito a completare il controllo. Un <code>softfail</code> significa che è stato il tuo stesso record a chiedere indecisione. Trattarli come fallimenti è il modo in cui uno strumento di monitoraggio si inventa problemi che non esistono.</p>
<h2 id="perché-il-caso-b-richiede-esattamente-pnone">Perché il caso (B) richiede esattamente <code>p=none</code></h2>
<p>È la parte che si salta, e saltandola il significato della riga si capovolge.</p>
<p>Immagina che il tuo dominio sia già a <code>p=quarantine</code>, e che un report mostri un lotto che ha fallito entrambi i metodi ed è stato comunque consegnato, <code>disposition=none</code>. A una lettura ingenua è peggio: lo spoofing è passato lo stesso. È l’opposto. Tu avevi chiesto al destinatario di mettere in quarantena quella posta, e il destinatario ha scelto di non farlo. RFC 9989 è esplicito nel dire che la gestione finale resta sempre una decisione locale di chi riceve: il protocollo esprime una preferenza, non un comando. Un messaggio consegnato su un dominio in enforcement significa quindi che è stata applicata un’eccezione: una allowlist locale, una regola su un inoltratore fidato, oppure — sui record che portano ancora il tag legacy <code>pct</code>, che RFC 9989 ha rimosso — una decisione di campionamento.</p>
<p>Su quel dominio l’enforcement esiste. Il destinatario ha guardato la tua policy e ha fatto un’eccezione. È una situazione diversa da “l’enforcement non c’è ancora”, e non è spoofing latente.</p>
<p>Lo stesso ragionamento copre il terzo caso: se non sai quale policy fosse pubblicata, il caso (B) non si applica affatto. Non puoi concludere “consegnato solo perché mancava l’enforcement” senza sapere se l’enforcement ci fosse.</p>
<h2 id="a-volte-il-destinatario-ti-dice-perché">A volte il destinatario ti dice perché</h2>
<p>Quando applica un’eccezione, chi riceve può dirlo. <code>&lt;policy_evaluated&gt;</code> può portare uno o più elementi <code>&lt;reason&gt;</code>, e RFC 9990 ne definisce cinque tipi: <code>local_policy</code>, <code>mailing_list</code>, <code>other</code>, <code>policy_test_mode</code> e <code>trusted_forwarder</code>. Alcuni reporter aggiungono anche un <code>&lt;comment&gt;</code> in testo libero.</p>
<pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="xml"><code><span class="line"><span style="color:#E1E4E8">&#x3C;</span><span style="color:#85E89D">policy_evaluated</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">  &#x3C;</span><span style="color:#85E89D">disposition</span><span style="color:#E1E4E8">>none&#x3C;/</span><span style="color:#85E89D">disposition</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">  &#x3C;</span><span style="color:#85E89D">dkim</span><span style="color:#E1E4E8">>fail&#x3C;/</span><span style="color:#85E89D">dkim</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">  &#x3C;</span><span style="color:#85E89D">spf</span><span style="color:#E1E4E8">>fail&#x3C;/</span><span style="color:#85E89D">spf</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">  &#x3C;</span><span style="color:#85E89D">reason</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">    &#x3C;</span><span style="color:#85E89D">type</span><span style="color:#E1E4E8">>mailing_list&#x3C;/</span><span style="color:#85E89D">type</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">  &#x3C;/</span><span style="color:#85E89D">reason</span><span style="color:#E1E4E8">></span></span>
<span class="line"><span style="color:#E1E4E8">&#x3C;/</span><span style="color:#85E89D">policy_evaluated</span><span style="color:#E1E4E8">></span></span></code></pre>
<p>È un destinatario che ti dice, dentro il report, di aver riconosciuto una mailing list e di aver deciso di non farti pagare la tua stessa policy. È il campo più utile del formato, ed è opzionale: la maggior parte dei record non lo avrà, ma quando c’è ti risparmia l’indagine. I reporter, inoltre, si muovono più lentamente della specifica: fino al 2026 il riferimento era RFC 7489, il cui elenco di motivi comprendeva anche <code>forwarded</code> e <code>sampled_out</code>, e continuerai a vederli in circolazione.</p>
<h2 id="le-tre-spiegazioni-ordinarie">Le tre spiegazioni ordinarie</h2>
<p>La maggior parte del volume allarmante viene da tre situazioni.</p>
<p><strong>Inoltro automatico.</strong> Un utente si fa inoltrare la posta altrove, oppure un vecchio alias punta ancora fuori. Il server che inoltra spedisce dal proprio IP, che non è nel tuo record SPF, quindi SPF non è più allineato con il tuo dominio. Se l’inoltratore lascia il messaggio intatto, la firma DKIM sopravvive, DMARC passa su DKIM e il messaggio viene consegnato. Nel report: <code>&lt;spf&gt;fail&lt;/spf&gt;</code>, <code>&lt;dkim&gt;pass&lt;/dkim&gt;</code>, disposition <code>none</code>. <strong>Cosa fare: niente.</strong> È esattamente il motivo per cui i metodi di autenticazione sono due.</p>
<p><strong>Mailing list.</strong> Una lista aggiunge un prefisso all’oggetto o un piè di pagina, e questo invalida la firma DKIM sul corpo modificato; poi riscrive il mittente di busta con il proprio dominio, e questo sposta SPF lontano dal tuo. Entrambi i metodi falliscono l’allineamento, e il messaggio viene consegnato lo stesso perché chi riceve riconosce lo schema. Nel report: entrambi <code>fail</code>, disposition <code>none</code>, a volte con <code>&lt;reason&gt;&lt;type&gt;mailing_list&lt;/type&gt;</code>. <strong>Cosa fare: niente.</strong> Il meccanismo pensato per portare l’autenticazione attraverso questo tipo di riscrittura è ARC (RFC 8617), e implementarlo è compito della lista, non tuo.</p>
<p><strong>Un fornitore che firma con il proprio dominio.</strong> La piattaforma di fatturazione, il CRM o lo strumento di newsletter spediscono per tuo conto e firmano con <code>d=fornitore.example</code>, non <code>d=example.com</code>. Guarda <code>&lt;auth_results&gt;</code>: il <code>result</code> di DKIM è <code>pass</code>, ma <code>&lt;domain&gt;</code> è quello del fornitore. Successo grezzo, nessun allineamento, quindi <code>&lt;policy_evaluated&gt;/&lt;dkim&gt;</code> è <code>fail</code>. <strong>Qui invece serve agire</strong> — non con urgenza, ma sul serio. Chiedi al fornitore la firma DKIM sotto il tuo dominio (quasi sempre un CNAME che punta a un selettore che ti fornisce lui) e, se spedisce con un mittente di busta nel tuo dominio, assicurati che il suo <code>include:</code> sia nel tuo record SPF. Fino ad allora quel traffico non ha alcun identificatore allineato, ed è esattamente il traffico che si romperà il giorno in cui passerai all’enforcement.</p>
<h2 id="i-record-che-non-sono-né-luno-né-laltro">I record che non sono né l’uno né l’altro</h2>
<p>C’è una quarta forma, e non rientra pulitamente in nessuna delle due: SPF <code>fail</code>, e nessun elemento <code>&lt;dkim&gt;</code>, perché il messaggio non era firmato da niente.</p>
<p>La regola qui sopra non li conta come fallimenti, ed è una scelta deliberata. Un elemento DKIM mancante non è un fallimento di DKIM: è l’assenza di prove su quel lato, e l’assenza di prove non è una prova. Ma questi record non sono nemmeno “a posto”, e meritano una coda tutta loro, perché su un dominio a <code>p=none</code> le spiegazioni possibili sono esattamente due e nel report sono identiche:</p>
<ol>
<li>qualcuno sta falsificando il tuo dominio, oppure</li>
<li>un tuo mittente legittimo non ha alcuna autenticazione — il plugin di un modulo di contatto su un piccolo VPS, uno script di monitoraggio, un’applicazione di reparto che nessuno ricorda di aver installato.</li>
</ol>
<p>Il report non può dirti quale delle due. L’IP sorgente di solito sì. Lavora questo elenco <em>prima</em> di alzare la policy, perché sono i messaggi che cominceranno a sparire nel momento esatto in cui lo farai.</p>
<h2 id="quando-è-davvero-spoofing">Quando è davvero spoofing</h2>
<p>I segnali, nell’ordine in cui vale la pena guardarli:</p>
<ul>
<li><strong>L’IP sorgente non ha alcun rapporto con te.</strong> Non è il tuo provider, non è il tuo ufficio, non è un fornitore che sai nominare. È il segnale più forte che esista, e l’unico che si regga da solo.</li>
<li><strong>Non passa niente, nemmeno in grezzo.</strong> Nessuna firma DKIM allineata, e nessun <code>pass</code> SPF per un dominio che riconosci.</li>
<li><strong>L’infrastruttura di invio non somiglia a un sistema di posta.</strong> DNS inverso inutilizzabile, range di hosting invece che range di posta, una sorgente che compare una volta e non torna più.</li>
<li><strong><code>&lt;header_from&gt;</code> è il tuo dominio mentre tutto il resto appartiene a qualcun altro.</strong> È la definizione dell’attacco per cui DMARC è stato costruito.</li>
</ul>
<p>Qui non ci sono soglie, deliberatamente. “Più del X% da un singolo IP” è il tipo di numero che si copia da un articolo all’altro e non dice niente sul tuo dominio: un fornitore di invio legittimo concentra volumi enormi su pochissimi indirizzi. Si giudicano le sorgenti, non le percentuali.</p>
<h2 id="cosa-farne-di-quel-numero">Cosa farne, di quel numero</h2>
<p>Non alzare la policy per far scendere un numero. È il numero sbagliato, e alzare la policy non farà quello che ti aspetti.</p>
<p>Procedi invece in quest’ordine. Identifica ogni sorgente nei tuoi report finché non ne resta nessuna inspiegata: quello è il lavoro vero, e su un dominio di una certa età richiede settimane, non un pomeriggio. Sistema l’allineamento di quelle legittime, cominciando dai fornitori che firmano sotto il proprio dominio. Poi sposta la policy, e non prima.</p>
<p>E sappi cosa succederà alla tua dashboard quando lo farai. Un lotto di spoofing latente a <code>p=none</code> è il caso (B): consegnato, contato come fallimento. A <code>p=reject</code> quello stesso lotto diventa il caso (A): rifiutato, e contato ancora come fallimento. Il conteggio dei fallimenti non deve per forza scendere perché l’enforcement stia funzionando — quella posta ha smesso di arrivare nelle caselle, che era tutto il punto. Quello che deve scendere è il volume che non sai spiegare.</p>
<p>I report aggregati riassumono; non contengono mai il messaggio. Quando è un messaggio specifico a darti fastidio e vuoi sapere cosa ne ha concluso davvero il server che l’ha ricevuto, incolla le sue intestazioni nel nostro <a href="https://sentinely.eu/tools/email-header-analyzer/">analizzatore di intestazioni email</a>: legge le dichiarazioni di chi ha ricevuto, non richiede alcun account e non conserva niente.</p>
<hr>
]]></content:encoded>
    </item>
  </channel>
</rss>
