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, dafreshaexpired. - 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.devengono 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.comsono 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.
| Campo | Cosa ti dice |
|---|---|
syntax.is_valid_syntax | Se l’indirizzo è ben formato |
syntax.username, syntax.domain | Le due metà, così come sono state verificate |
syntax.normalized_email | La casella canonica, per eliminare i duplicati |
syntax.suggestion | Una 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_disposablesegnala i servizi di caselle usa e getta (codice motivodisposable).misc.is_role_accountsegnala indirizzi condivisi comeinfo@osupport@(role_account).misc.is_spam_trap_domainsegnala 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.

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:
- Si presenta con
EHLO. - Indica un mittente con
MAIL FROM. - Indica l’indirizzo da controllare con
RCPT TO. - 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 motivosmtp_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_reachable | Cosa è successo | Cosa fare |
|---|---|---|
safe | Il server ha accettato la casella e non è emerso alcun segnale di rischio | Inviare |
risky | La casella sembra esistere, ma il dominio è catch-all, l’indirizzo è usa e getta o generico, la casella è piena o il dominio gestisce spam trap | Leggere i codici motivo, poi decidere |
invalid | Sintassi errata, oppure il server ha rifiutato o disattivato la casella | Rimuoverlo |
unknown | Il server non ha dato una risposta utilizzabile: timeout, greylisting o blocco | Tenerlo 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 reale | In blocco | |
|---|---|---|
| Endpoint | POST /v1/check_email | POST /v1/bulk, poi controllo del job |
| Momento migliore | Quando l’indirizzo viene raccolto | Prima di una campagna o dopo un’importazione |
| Vantaggio principale | Refusi corretti mentre la persona è ancora lì | Indirizzi morti rimossi prima che rimbalzino |
Gestione di unknown | Accettarlo e ricontrollare | Escluderlo 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.

