Signup email checker template
- Node.js
- Express
Accept, review or reject an email at signup: catches throwaway inboxes, dead domains, typos and shared inboxes.
A small Node.js and Express app that decides whether to accept an email address at signup. Enter an address and it returns Accept, Review or Reject, with the reason for each: an inbox that is disposable, a domain that can’t receive mail, a likely typo, or a shared address like sales@. Deploy it to try addresses by hand, or call its route from your own signup form.

What it does
- Blocks throwaway inboxes
- Rejects disposable email addresses, the kind people use to grab a free trial and disappear.
- Catches dead domains
- Rejects addresses whose domain has no mail server, so the welcome email would bounce.
- Flags typos
- Sends addresses like [email protected] to review, with the suggested correction on paid plans.
- Spots shared inboxes
- Flags role addresses like info@ and sales@ that reach a team rather than a person.
- Rules you can change
- One small function turns the response into a decision, so you can tune it to your signup flow.
How it works
The signup decision and the route that calls Email Validator.
/**
* Turns the Email Validator response into a signup decision.
* reject: can't receive mail, or a throwaway inbox. review: likely typo or shared inbox.
* Only free-plan fields decide it, so it works on every plan.
*/
function decide(d) {
const typo = d.hasTypo || !!d.suggestedCorrection;
const reasons = [];
if (!d.isRegexValid) reasons.push({ level: 'reject', text: 'Not a valid email format' });
else if (!d.isMxValid) reasons.push({ level: 'reject', text: `${d.domain} can’t receive email` });
if (d.isDisposable) reasons.push({ level: 'reject', text: 'Disposable, throwaway inbox' });
if (typo) reasons.push({ level: 'review', text: d.suggestedCorrection ? `Possible typo. Did they mean ${d.suggestedCorrection}?` : 'The domain looks misspelled' });
if (d.isRoleAccount) reasons.push({ level: 'review', text: 'Shared inbox (info@, sales@), not a person' });
const decision = reasons.some((r) => r.level === 'reject') ? 'reject' : reasons.length ? 'review' : 'accept';
return { decision, reasons };
}
// POST /api/validate { email }
app.post('/api/validate', async (req, res) => {
const email = str(req.body.email, 254);
if (!email) return res.status(400).json({ error: 'Enter an email address.' });
try {
const d = await callApi('emailvalidator', { query: { email } });
res.json({
email: d.email,
...decide(d),
details: {
domain: d.domain,
provider: d.isCompanyEmail ? 'Company domain' : d.isFreeEmail ? 'Free provider' : 'Unknown',
acceptsMail: d.isMxValid,
disposable: d.isDisposable,
sharedInbox: d.isRoleAccount,
suggestion: d.suggestedCorrection || null,
riskLevel: d.riskLevel ?? null
}
});
} catch (err) {
res.status(err.status || 502).json({ error: err.message });
}
});Deploy it
- Get a free API key
The free plan includes 200 credits a month, no card needed. Create your key.
- Deploy it
Click Deploy to Vercel. Vercel copies the repo to your GitHub account and asks for
APIVERVE_API_KEY: paste your key there. - Open your app
Vercel builds it and gives you a live URL, usually in about a minute. Every push to the repo redeploys it.
Try the Email Validator API — the call this template makes
No key required to try it. Get a key to use it in your app.
{
"status": "ok",
"error": null,
"data": {
"email": "[email protected]",
"domain": "myspace.com",
"username": "support",
"isRegexValid": true,
"hasTypo": false,
"isMxValid": true,
"isValid": true,
"isFreeEmail": false,
"isCompanyEmail": true,
"isDisposable": false,
"isRoleAccount": true,
"suggestedCorrection": null,
"riskScore": 10,
"riskLevel": "low"
}
}