Migrer depuis Emailable
Ce guide montre comment remplacer les appels de vérification d'Emailable par
Mailbeam. La plupart des migrations prennent 30 à 60 minutes : le travail consiste
à remplacer une requête et à faire correspondre la chaîne state d'Emailable au
booléen et au score de Mailbeam.
Pourquoi les développeurs changent
- Résidence des données dans l'UE : Emailable traite sur une infrastructure américaine, ce qui oblige une entreprise européenne à passer par des clauses contractuelles types ; Mailbeam traite à Francfort, avec un DPA sur chaque forfait
- Conçu pour les formulaires : la latence d'Emailable sur une adresse unique tourne autour de 250 ms, ce qui est lent pour valider en ligne pendant que quelqu'un tape encore
- Catch-all gradué : Emailable renvoie les domaines accept-all en
riskyouunknown, sans rien sur quoi poser un seuil ; Mailbeam ajoute un score de 0 à 100 et unreason - Un prix qu'on peut isoler : entre les paquets de crédits et les options de délivrabilité facturées à part, le coût de la vérification elle-même est difficile à lire
- Mode bac à sable : un mode test déterministe pour l'intégration continue, plutôt que d'appeler la production
Un point joue réellement en faveur d'Emailable : il propose des tests de placement en boîte de réception par adresses témoins et une surveillance continue de la délivrabilité, que Mailbeam ne fait délibérément pas. Les équipes qui en ont besoin gardent souvent Emailable pour la délivrabilité et ne déplacent que la vérification.
Correspondance des endpoints
| Emailable | Mailbeam | Remarques |
|---|---|---|
GET /v1/verify?email=&api_key= | POST /v1/verify | Vérification d'une adresse |
POST /v1/batch | POST /v1/verify/batch | Jusqu'à 500 000 adresses par tâche |
GET /v1/batch?id= | GET /v1/jobs/{id} | État du lot |
Authentification
Emailable passe la clé d'API en paramètre d'URL, si bien qu'elle finit dans les journaux d'accès, l'historique du navigateur et les traces de proxy. Mailbeam prend un jeton Bearer dans l'en-tête : l'identifiant reste hors de l'URL.
Emailable (avant) :
curl "https://api.emailable.com/v1/verify?email=user@example.com&api_key=YOUR_KEY"Mailbeam (après) :
curl -X POST https://api.mailbeam.dev/v1/verify \
-H "Authorization: Bearer $MAILBEAM_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com"}'Correspondance des réponses
Emailable rapporte une seule chaîne state. Mailbeam répartit la même information
entre un booléen sur lequel brancher et un score sur lequel poser un seuil.
| Champ Emailable | Équivalent Mailbeam |
|---|---|
state: "deliverable" | valid: true, score >= 70 |
state: "undeliverable" | valid: false |
state: "risky" | valid: true, score entre 30 et 69 |
state: "unknown" | status: "unknown" |
reason | reason (code lisible par la machine) |
disposable | disposable |
role | role |
accept_all | catchAll, avec un score gradué |
Migrer l'appel
Emailable (avant) :
const res = await fetch(
`https://api.emailable.com/v1/verify?email=${email}&api_key=${apiKey}`
);
const { state } = await res.json();
if (state !== "deliverable") return 422;Mailbeam (après) :
// Pas de SDK à installer — voyez /docs/quickstart pour ce wrapper de 12 lignes.
import { verifyEmail } from "./lib/mailbeam.js";
const { valid, score, reason } = await verifyEmail(email);
if (!valid || score < 60) return 422;Regardez bien ce que faisait l'ancienne branche : state !== "deliverable"
rejette risky et unknown en même temps que les vrais échecs. Si votre tunnel
d'inscription écartait discrètement des adresses d'entreprise en accept-all,
c'est là que cela se jouait.
À regarder en premier : risky et unknown
Emailable ramène deux situations différentes à des chaînes que vous devez
interpréter. Un domaine accept-all et un serveur qui a refusé de répondre
arrivent tous deux sous autre chose que deliverable, et la plupart des
intégrations rejettent les deux. Mailbeam les sépare, ce qui vous permet de
décider une fois pour chaque cas :
const { valid, status, catchAll, score, reason } = await verifyEmail(email);
if (status === "unknown") {
// Le serveur n'a pas voulu répondre — greylisting, expiration, refus temporaire.
// Ce n'est pas une preuve que la boîte est mauvaise. Acceptez et revérifiez plus tard.
return acceptPendingReverification();
}
if (catchAll) {
return score >= 70 ? accept() : challenge({ reason });
}
return valid ? accept() : reject({ reason });