Guida

Come funziona la verifica email, fase per fase

Cosa controlla un verificatore email, fase per fase: sintassi, DNS e MX, sonda SMTP e punteggio, e quale campo dell’API compila ciascuna fase.

Illustrazione di un uomo che presenta una verifica email con una lente d’ingrandimento e una checklist

In breve

La verifica email controlla un indirizzo in quattro fasi senza inviare alcun messaggio: convalida e normalizza la sintassi, cerca i record MX del dominio, chiede via SMTP al server di destinazione se accetterebbe la casella e infine assegna un punteggio alle prove raccolte. In BounceIntel ogni fase compila una parte della risposta, da syntax e mx fino a smtp, is_reachable e score.reason_codes.

Una lista piena di indirizzi morti costa più degli invii che spreca. Ogni hard bounce dice a Gmail, Outlook e Yahoo che non sai a chi stai scrivendo, e loro lo mettono in conto al tuo dominio e al tuo IP di invio. Se succede abbastanza spesso, la campagna successiva finisce nello spam, anche per gli indirizzi buoni.

La verifica email serve a trovare quegli indirizzi prima che lo faccia un provider di posta. Questa guida segue un indirizzo attraverso le quattro fasi eseguite da un verificatore, in ordine, e mostra quale parte di una risposta dell’API di BounceIntel viene compilata da ciascuna fase. Alla fine dovresti riuscire a leggere un risultato da solo, invece di fidarti di un’etichetta di una sola parola.

Cos’è la verifica (e cosa non è)

La verifica email è un test automatico che stabilisce se un indirizzo può ricevere posta in questo momento. Si basa su due fonti: i record DNS pubblici e una breve conversazione con il server di posta che riceverebbe il messaggio. Nessuna email viene inviata. La conversazione si chiude prima che venga trasmesso qualsiasi contenuto, quindi la persona dietro l’indirizzo non vede nulla.

Vale la pena essere altrettanto chiari su ciò che la verifica non può dirti:

  • Se una persona legge la casella. Una casella può esistere ed essere abbandonata. A questa domanda rispondono i dati di engagement, non la verifica.
  • Se l’indirizzo funzionerà ancora il mese prossimo. Le persone cambiano lavoro e le caselle vengono eliminate. Un risultato descrive il momento del controllo, ed è per questo che ogni risultato di BounceIntel contiene score.freshness, da fresh a expired.
  • Se un indirizzo è una spam trap. I domini noti per gestire trappole vengono segnalati, ma una trappola ben fatta è costruita per sembrare un indirizzo reale e funzionante.
  • Se hai il permesso di scrivere a qualcuno. È una questione di consenso, e nessun controllo tecnico può rispondere.

Fase 1: sintassi e normalizzazione

La prima fase non esce mai dal verificatore. Divide l’indirizzo in corrispondenza della @ in una parte locale e un dominio, e controlla che siano entrambi ben formati. Un indirizzo che fallisce qui si ferma qui: nessuna query DNS, nessuna connessione al server di nessuno e un risultato is_reachable: "invalid" con il codice motivo invalid_syntax e un punteggio di 0.

Due dettagli decidono se un indirizzo insolito passa:

  • I domini internazionalizzati come münchen.de vengono convertiti nella loro forma ASCII (xn--mnchen-3ya.de), e tutte le fasi successive usano quella forma.
  • Le parti locali non ASCII come josé@example.com sono considerate non valide. Consegnare loro la posta richiede un’estensione SMTP che la maggior parte dei server di destinazione non offre, quindi in pratica rimbalzano.

La stessa fase prepara due cose utilizzabili subito. syntax.normalized_email restituisce la forma canonica della casella: su Gmail i punti e tutto ciò che segue un + non cambiano la destinazione, quindi [email protected] diventa [email protected] e i duplicati in una lista si individuano facilmente. E quando il dominio dista una o due lettere da un provider noto, syntax.suggestion propone la correzione probabile (gmial.com diventa gmail.com) e viene aggiunto il codice motivo possible_typo.

CampoCosa ti dice
syntax.is_valid_syntaxSe l’indirizzo è ben formato
syntax.username, syntax.domainLe due metà, così come sono state verificate
syntax.normalized_emailLa casella canonica, per eliminare i duplicati
syntax.suggestionUna probabile correzione di un refuso, oppure null

Fase 2: record DNS e MX

Un dominio indica dove deve arrivare la sua posta tramite i record MX. Il verificatore li interroga e la risposta finisce in mx.records (i server di posta del dominio) e mx.accepts_mail. Un dominio senza record MX non ha dove consegnare, e il risultato riporta il codice motivo no_mx. Già questo elimina un numero sorprendente di indirizzi sbagliati: domini aziendali scaduti, refusi che per caso sono registrati e domini inventati digitati nei moduli di iscrizione.

In questa fase l’indirizzo viene anche confrontato con ciò che si sa del suo dominio e della sua parte locale:

  • misc.is_disposable segnala i servizi di caselle usa e getta (codice motivo disposable).
  • misc.is_role_account segnala indirizzi condivisi come info@ o support@ (role_account).
  • misc.is_spam_trap_domain segnala i domini noti per gestire spam trap (spam_trap).
  • I provider consumer gratuiti come Gmail vengono annotati con free_provider.

L’host MX identifica anche il provider di posta dietro il dominio, per esempio Google Workspace o Microsoft 365. Conta per la fase successiva, perché ogni grande provider risponde alla verifica a modo suo.

File di rack di server in un data center luminoso

Fase 3: la sonda SMTP

È la fase che distingue una verifica vera da un semplice controllo di formato. Il verificatore si collega a uno degli host MX del dominio sulla porta 25 e avvia la stessa conversazione di qualsiasi server di invio:

  1. Si presenta con EHLO.
  2. Indica un mittente con MAIL FROM.
  3. Indica l’indirizzo da controllare con RCPT TO.
  4. Legge la risposta del server per quel destinatario e chiude la connessione.

Il messaggio vero e proprio, il passaggio DATA, non avviene mai. Ciò che conta è come ha risposto il server al passaggio 3:

  • Accettato (risposta 250): smtp.is_deliverable è true.
  • Rifiutato come utente sconosciuto: smtp.is_deliverable è false, con il codice motivo smtp_undeliverable.
  • Rifiutato perché l’account è disattivato: smtp.is_disabled è true (disabled_mailbox).
  • Rifiutato perché la casella è piena: smtp.has_full_inbox è true (full_inbox).

Sulla stessa connessione, BounceIntel chiede poi di un secondo destinatario: un indirizzo casuale di 15 caratteri sullo stesso dominio che non può esistere. Se il server accetta anche quello, smtp.is_catch_all è true. Più avanti vediamo perché è importante.

"smtp": {
  "can_connect_smtp": true,
  "is_deliverable": true,
  "is_disabled": false,
  "has_full_inbox": false,
  "is_catch_all": false
}

Non tutti i server danno una risposta chiara. Alcuni rallentano di proposito i mittenti sconosciuti con un rifiuto temporaneo (greylisting), altri limitano la frequenza, altri rifiutano le connessioni da reti che non riconoscono e altri semplicemente non rispondono in tempo. Niente di tutto questo è un verdetto sull’indirizzo, e BounceIntel non finge che lo sia. Il risultato diventa unknown e un codice motivo indica cosa è successo: transient_smtp, smtp_policy_block, smtp_timeout, smtp_network, smtp_ambiguous o smtp_unreachable.

Fase 4: punteggio e codici motivo

L’ultima fase trasforma tutti i segnali delle prime tre in qualcosa su cui agire. score.score va da 0 a 100 e corrisponde a una categoria: 80–100 è valid, 50–79 è risky, 1–49 è unknown e 0 è invalid. score.confidence e score.confidence_level (high, medium, low o very_low) dicono quante prove sostengono quel numero, e score.safe_to_send dà la risposta sì o no.

La parte su cui costruire è score.reason_codes. Elenca ogni segnale che ha influito sul risultato come stringhe stabili su cui il tuo codice può decidere, e score.sub_reason indica quello decisivo. Accanto, bounce_risk.action consiglia cosa fare (send, send_with_caution, verify_manually o do_not_send) e bounce_risk.risk_factors spiega quel consiglio, ogni fattore con il suo peso.

Ecco un risultato reale per un indirizzo di supporto condiviso su un dominio che accetta tutta la posta, ridotto ai campi del punteggio:

{
  "input": "[email protected]",
  "is_reachable": "risky",
  "score": {
    "score": 55,
    "category": "risky",
    "confidence_level": "low",
    "reason_codes": ["catch_all", "role_account", "catch_all_high_risk"],
    "sub_reason": "catch_all",
    "safe_to_send": false
  },
  "bounce_risk": {
    "action": "verify_manually",
    "risk_factors": [
      { "signal": "smtp_is_catch_all", "contribution": 20, "description": "Corporate catch-all mailbox" },
      { "signal": "is_role_account", "contribution": 10, "description": "Role-based mailbox" }
    ]
  }
}

Nel codice, decidi in base al consiglio e conserva i codici motivo per chi esaminerà l’indirizzo in seguito:

const { bounce_risk, score } = await res.json();

if (bounce_risk.action === "do_not_send") {
  suppress(email, score.reason_codes);
} else if (bounce_risk.action === "verify_manually") {
  queueForReview(email, score.reason_codes);
} else {
  accept(email);
}

Il punteggio considera anche lo storico del tuo account con quell’indirizzo negli ultimi 180 giorni, ed è per questo che un nuovo controllo può tornare con più confidenza del primo.

Il punto cieco del catch-all

La fase 3 ha un limite che nessun verificatore può aggirare. Alcuni domini sono configurati per accettare posta per qualsiasi indirizzo, reale o no. Chiedi al loro server di jane.doe@ e risponde sì; chiedi di una stringa di caratteri casuali e risponde di nuovo sì. La conversazione SMTP dimostra che il dominio riceve posta. Non può dimostrare che la casella che ti interessa esista.

A questo serve la sonda con l’indirizzo casuale. Quando viene accettata, BounceIntel classifica il risultato come risky invece di safe, aggiunge il codice motivo catch_all e gradua il rischio con un codice di gravità (catch_all_low_confidence, catch_all_medium_confidence o catch_all_high_risk) basato su prove come la configurazione del dominio e gli schemi di nome già verificati in quell’azienda. Un verificatore che definisce «validi» questi indirizzi sta descrivendo la cortesia del server, non la casella.

Cosa significano «safe / risky / invalid / unknown»

is_reachable è il riassunto in una parola di tutto quanto sopra. Il verificatore gratuito di questo sito mostra gli stessi quattro valori, con etichette tradotte.

is_reachableCosa è successoCosa fare
safeIl server ha accettato la casella e non è emerso alcun segnale di rischioInviare
riskyLa casella sembra esistere, ma il dominio è catch-all, l’indirizzo è usa e getta o generico, la casella è piena o il dominio gestisce spam trapLeggere i codici motivo, poi decidere
invalidSintassi errata, oppure il server ha rifiutato o disattivato la casellaRimuoverlo
unknownIl server non ha dato una risposta utilizzabile: timeout, greylisting o bloccoTenerlo e ricontrollarlo più tardi

Qui è facile sbagliare su due punti. unknown descrive un server in un certo momento, non l’indirizzo, quindi eliminare quegli indirizzi significa buttare contatti buoni. E risky copre situazioni molto diverse: una casella piena di solito è temporanea, mentre un indirizzo usa e getta non apparterrà mai a un cliente. L’etichetta è un riassunto. La decisione spetta a bounce_risk.action e score.reason_codes.

Quando usare la verifica in tempo reale e quando in blocco

Le quattro fasi sono le stesse in entrambi i casi. Cambia il momento in cui le esegui.

La verifica in tempo reale, un indirizzo alla volta con POST /v1/check_email, va messa dove un indirizzo entra nei tuoi sistemi: moduli di iscrizione, checkout, moduli di contatto commerciale, un commerciale che digita nel CRM. La persona è ancora lì, quindi un refuso rilevato da syntax.suggestion si può correggere subito invece di diventare un rimbalzo la settimana dopo. Chiama l’API dal tuo server, mai da codice nel browser che contiene la tua chiave, e tratta unknown come «accetta e ricontrolla più tardi», così un server lento non blocca mai un’iscrizione vera.

La verifica in blocco, con POST /v1/bulk o caricando un CSV nella dashboard, va fatta prima di un invio: una newsletter verso una lista rimasta ferma, un’importazione da una fiera o da un nuovo CRM, o un passaggio periodico su un vecchio database. Ogni riga torna con gli stessi campi. Le liste si degradano man mano che le persone cambiano lavoro, quindi verifica tutto ciò che non è stato controllato da qualche mese prima di usarlo.

Tempo realeIn blocco
EndpointPOST /v1/check_emailPOST /v1/bulk, poi controllo del job
Momento miglioreQuando l’indirizzo viene raccoltoPrima di una campagna o dopo un’importazione
Vantaggio principaleRefusi corretti mentre la persona è ancora lìIndirizzi morti rimossi prima che rimbalzino
Gestione di unknownAccettarlo e ricontrollareEscluderlo da questo invio e ricontrollare

Controlla un indirizzo e leggi il risultato

Tutto ciò che il verificatore mostra arriva dalla stessa API che chiamerebbe il tuo codice. La documentazione dell’API descrive ogni campo della risposta, la verifica in blocco copre liste intere e i prezzi mostrano quanto costa un piano con accesso all’API.

Proteggi la tua reputazione di mittente prima del prossimo invio.

Verifica una lista, collega l’API al modulo di iscrizione e tieni gli indirizzi sbagliati lontani dalle tue campagne.