Verify an email address on form submit
The mechanics: where the call lives, what to show for each reason, and how to keep the form from waiting on a slow mail server.
Verification belongs on your server, in the handler that receives the form: the API key must not ship to the browser, and the verdict must be there before you decide what the form does next.
The response has everything the form needs: did_you_mean for the inline correction, suggested_action for the decision, reason for the message, and a timeout you control so the request never outlasts the user's patience.
Wire it in
# Python, in the form handler
r = requests.post("https://api.verimail.io/v3/verify",
headers={"Authorization": f"Bearer {KEY}"},
data={"email": email, "timeout": 2000}, timeout=3)
v = r.json()
MESSAGES = {
"no_mail_server": "That domain can't receive email.",
"mailbox_rejected": "That mailbox doesn't exist.",
"invalid_domain": "That doesn't look like an email address.",
}
if v["did_you_mean"]:
return form_error(f"Did you mean {v['did_you_mean']}?")
if v["suggested_action"] == "reject":
return form_error(MESSAGES.get(v["reason"], "That address can't receive email."))
proceed(email, confirm=v["verdict"] != "deliverable") What to do with each answer here
| deliverable | Proceed. |
| undeliverable | Block, with the reason as a sentence a person understands. Never show the raw reason name. |
| risky | Proceed and confirm by email. Do not tell the user anything; they did nothing wrong. |
| unknown | Proceed and confirm by email. Not billed. Log the evidence if you want to see why later. |
What this does not do
- Set your HTTP client's own timeout a little above the API timeout, so a network stall does not outlast it.
- One verification per submit. Do not verify on every keystroke; it costs a credit and an SMTP dialogue each time.
- A verdict is what the server said now. Re-verify old addresses before a campaign rather than trusting last year's answer.
Reference: the API, handling results, result codes. A free key gives you 100 verifications a month: get one.