How to Block Disposable Emails & Fake Signups in Node.js (in under 50ms)
If you've ever built a SaaS, a side project, or a newsletter, you know the pain: bot registrations, disposable emails (10-Minute Mail, GuerrillaMail, Mailinator), and mistyped domains ([email protected]) filling up your dat
If you've ever built a SaaS, a side project, or a newsletter, you know the pain: bot registrations, disposable emails (10-Minute Mail, GuerrillaMail, Mailinator), and mistyped domains ([email protected]) filling up your database and burning your transactional email quotas.
Instead of writing a custom blocklist or maintaining thousands of domains yourself, here is a clean, lightweight way to validate incoming emails directly in your Express auth pipeline.
The Problem with Basic Regex Validation
Most tutorials recommend just validating email syntax with a regex:
// This only checks syntax, not if the inbox or domain is legitimate
const isValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
While this checks RFC formatting, it won't stop someone signing up with [email protected] or an unconfigured domain with no real records.
The Clean Solution: Validating in Express
To solve this for my own projects, I built EmailGuard API, a microservice in Node.js that checks in-memory disposable domain sets (O(1) lookups) and resolves real records with an 800ms strict timeout.
It returns an actionable recommendation field ("allow", "review", or "block"), making integration straightforward:
import express from "express";
const app = express();
app.use(express.json());
app.post("/api/register", async (req, res) => {
const { email, password } = req.body;
try {
const response = await fetch("[https://emailguard-disposable-email-detector-and-hygiene.p.rapidapi.com/v1/verify](https://emailguard-disposable-email-detector-and-hygiene.p.rapidapi.com/v1/verify)", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-RapidAPI-Key": process.env.RAPIDAPI_KEY,
"X-RapidAPI-Host": "emailguard-disposable-email-detector-and-hygiene.p.rapidapi.com"
},
body: JSON.stringify({ email })
});
const result = await response.json();
const data = result.data;
// Direct 1-line check
if (data.recommendation === "block") {
return res.status(400).json({
error: "Disposable or invalid emails are not allowed."
});
}
// Optional: Auto-correct common typos (e.g. gmial.com -> gmail.com)
if (data.checks.typo_guard.has_typo) {
console.log(`Suggested email: ${data.checks.typo_guard.suggested_email}`);
}
// Continue with user creation...
return res.status(201).json({ message: "User registered successfully" });
} catch (error) {
console.error("Verification failed:", error);
return res.status(500).json({ error: "Registration error" });
}
});
What the API Returns
Calling the verification endpoint returns a comprehensive hygiene breakdown:
{
"status": "success",
"data": {
"email": "[email protected]",
"score": 0,
"verdict": "invalid",
"recommendation": "block",
"checks": {
"syntax": { "valid": true, "rfc_compliant": true },
"dns": { "has_mx_records": false },
"disposable": { "is_disposable": true, "provider": "mailinator" },
"account_type": { "is_free_provider": false, "is_role_based": false },
"typo_guard": { "has_typo": false }
},
"meta": {
"execution_time_ms": 1
}
}
}
Try it out for your projects
I published the microservice on RapidAPI with a free tier of 100 requests/month for developers and side projects:
π [EmailGuard API on RapidAPI]
Feedback and edge cases are welcome! If you test it on weird domains, let me know how it handles them.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.