Hai pubblicato v=DMARC1; p=none; rua=mailto:... qualche settimana fa, l’XML ha cominciato ad arrivare, e ora stai guardando il primo riepilogo. Una fetta consistente della tua posta è marcata fail. La domanda che viene spontanea è se qualcuno stia falsificando il tuo dominio.
Quasi certamente no. Quello che hai davanti è la parola fail 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.
Due cose diverse che si chiamano “fail”
Un report DMARC aggregato (il formato è specificato in RFC 9990) non è un elenco di messaggi. È un elenco di gruppi: ogni <record> copre un lotto di messaggi arrivati dallo stesso IP sorgente con lo stesso esito di autenticazione, e <count> dice quanti messaggi rappresenta quel lotto. Qualunque percentuale tu veda, da qualunque parte, è pesata su quel numero.
Dentro ogni record ci sono tre livelli, e rispondono a tre domande diverse.
<record>
<row>
<source_ip>203.0.113.47</source_ip>
<count>128</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>pass</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<dkim>
<domain>example.com</domain>
<selector>s1</selector>
<result>pass</result>
</dkim>
<spf>
<domain>fwd.example.net</domain>
<result>pass</result>
</spf>
</auth_results>
</record>
<auth_results> — i protocolli hanno verificato qualcosa? Sono gli esiti grezzi, non interpretati. Qui SPF ha restituito pass, ma guarda per quale dominio è passato: fwd.example.net, non example.com. DKIM ha verificato una firma che porta d=example.com.
<policy_evaluated>/<spf> e /<dkim> — hanno verificato e combaciano con il dominio del From:? Questa è la vista di DMARC, e ha solo due valori: pass o fail. SPF ha verificato per il dominio di qualcun altro, quindi dal punto di vista di DMARC è fail. DKIM ha verificato per il tuo, quindi è pass.
<policy_evaluated>/<disposition> — cosa ha fatto davvero il destinatario? Tre valori: none (consegnato), quarantine, reject.
Il record qui sopra contiene la parola fail, e non è andato storto assolutamente nulla. DMARC passa quando passa almeno uno 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.
La regola
Eccola per intero, e vale la pena tenerla da qualche parte a portata di copia-incolla.
Un gruppo di messaggi in un report aggregato è un fallimento vero se e solo se:
(A) il destinatario l’ha bloccato —
dispositionèquarantineoreject; oppure(B) è stato consegnato (
dispositionènone), la policy in vigore per quel report erap=none, e entrambi gli esiti grezzi in<auth_results>sono esattamentefail.Tutto il resto appartiene al tuo volume, non ai tuoi fallimenti.
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 disposition è quarantine o reject, della tua posta non è arrivata in una casella, e questo merita attenzione tanto se la causa è un attaccante quanto se è un fornitore configurato male.
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.
Nel caso (B) ci sono due dettagli facili da sbagliare.
La policy che conta è quella di quel report, non quella che hai nel DNS oggi. Ogni report porta con sé la policy che il destinatario ha visto, in <policy_published>/<p>, 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 p va letta dal report che hai in mano.
Conta solo il valore esatto fail. RFC 9990 ammette in <auth_results> diversi altri valori — none, neutral, policy, temperror, permerror, e per SPF anche softfail — e nessuno di questi dimostra alcunché. Un temperror significa che il destinatario non è riuscito a completare il controllo. Un softfail 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.
Perché il caso (B) richiede esattamente p=none
È la parte che si salta, e saltandola il significato della riga si capovolge.
Immagina che il tuo dominio sia già a p=quarantine, e che un report mostri un lotto che ha fallito entrambi i metodi ed è stato comunque consegnato, disposition=none. 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 pct, che RFC 9989 ha rimosso — una decisione di campionamento.
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.
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.
A volte il destinatario ti dice perché
Quando applica un’eccezione, chi riceve può dirlo. <policy_evaluated> può portare uno o più elementi <reason>, e RFC 9990 ne definisce cinque tipi: local_policy, mailing_list, other, policy_test_mode e trusted_forwarder. Alcuni reporter aggiungono anche un <comment> in testo libero.
<policy_evaluated>
<disposition>none</disposition>
<dkim>fail</dkim>
<spf>fail</spf>
<reason>
<type>mailing_list</type>
</reason>
</policy_evaluated>
È 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 forwarded e sampled_out, e continuerai a vederli in circolazione.
Le tre spiegazioni ordinarie
La maggior parte del volume allarmante viene da tre situazioni.
Inoltro automatico. 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: <spf>fail</spf>, <dkim>pass</dkim>, disposition none. Cosa fare: niente. È esattamente il motivo per cui i metodi di autenticazione sono due.
Mailing list. 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 fail, disposition none, a volte con <reason><type>mailing_list</type>. Cosa fare: niente. Il meccanismo pensato per portare l’autenticazione attraverso questo tipo di riscrittura è ARC (RFC 8617), e implementarlo è compito della lista, non tuo.
Un fornitore che firma con il proprio dominio. La piattaforma di fatturazione, il CRM o lo strumento di newsletter spediscono per tuo conto e firmano con d=fornitore.example, non d=example.com. Guarda <auth_results>: il result di DKIM è pass, ma <domain> è quello del fornitore. Successo grezzo, nessun allineamento, quindi <policy_evaluated>/<dkim> è fail. Qui invece serve agire — 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 include: 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.
I record che non sono né l’uno né l’altro
C’è una quarta forma, e non rientra pulitamente in nessuna delle due: SPF fail, e nessun elemento <dkim>, perché il messaggio non era firmato da niente.
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 p=none le spiegazioni possibili sono esattamente due e nel report sono identiche:
- qualcuno sta falsificando il tuo dominio, oppure
- 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.
Il report non può dirti quale delle due. L’IP sorgente di solito sì. Lavora questo elenco prima di alzare la policy, perché sono i messaggi che cominceranno a sparire nel momento esatto in cui lo farai.
Quando è davvero spoofing
I segnali, nell’ordine in cui vale la pena guardarli:
- L’IP sorgente non ha alcun rapporto con te. 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.
- Non passa niente, nemmeno in grezzo. Nessuna firma DKIM allineata, e nessun
passSPF per un dominio che riconosci. - L’infrastruttura di invio non somiglia a un sistema di posta. DNS inverso inutilizzabile, range di hosting invece che range di posta, una sorgente che compare una volta e non torna più.
<header_from>è il tuo dominio mentre tutto il resto appartiene a qualcun altro. È la definizione dell’attacco per cui DMARC è stato costruito.
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.
Cosa farne, di quel numero
Non alzare la policy per far scendere un numero. È il numero sbagliato, e alzare la policy non farà quello che ti aspetti.
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.
E sappi cosa succederà alla tua dashboard quando lo farai. Un lotto di spoofing latente a p=none è il caso (B): consegnato, contato come fallimento. A p=reject 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.
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 analizzatore di intestazioni email: legge le dichiarazioni di chi ha ricevuto, non richiede alcun account e non conserva niente.
