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 (user@gmial.com) 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 throwaway@mailinator.com 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": "spam@mailinator.com",
"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.
Top comments (0)