How to Validate Email Addresses in Node.js (2026 Guide)
Source: Dev.to
Basic Regex Validation
A simple regular expression can catch obvious formatting errors, but it won’t verify that the domain actually receives mail or that the address isn’t disposable.
function isValidEmail(email) {
const regex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
return regex.test(email) && email.length 0;
} catch {
return false;
}
}
async function validateEmail(email) {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!regex.test(email)) return { valid: false, reason: "Invalid format" };
const domain = email.split("@")[1];
const hasMx = await hasMxRecords(domain);
if (!hasMx) return { valid: false, reason: "Domain has no mail server" };
return { valid: true };
}
// Example
(async () => {
const result = await validateEmail("user@fakdomain123.com");
console.log(result); // { valid: false, reason: "Domain has no mail server" }
})();
Pros
- Detects domains without mail servers.
- Uses the built‑in Node.js
dnsmodule (no extra dependencies).
Cons
- Doesn’t detect disposable addresses, role accounts, or common typos.
- Adds ~10–50 ms latency for the DNS lookup.
Disposable Email Blocklist
Many sign‑ups use temporary services (Mailinator, Guerrilla Mail, etc.). Maintaining a blocklist can filter most of these.
const disposableDomains = new Set([
"mailinator.com",
"guerrillamail.com",
"tempmail.com",
"throwaway.email",
"yopmail.com",
// …add more as needed
]);
function isDisposable(email) {
const domain = email.split("@")[1].toLowerCase();
return disposableDomains.has(domain);
}
console.log(isDisposable("user@mailinator.com")); // true
console.log(isDisposable("user@gmail.com")); // false
Pros
- Blocks the majority of throwaway sign‑ups.
Cons
- The list must be kept up‑to‑date; new services appear constantly.
Full API Validation (mxcheck)
The mxcheck service performs all checks in a single request: syntax, MX records, disposable detection, role accounts, typo suggestions, and more.
import mxcheck from "mxcheck";
const result = await mxcheck("admin@mailinator.com");
console.log(result);
// {
// email: "admin@mailinator.com",
// valid: true,
// score: 0.6,
// checks: {
// syntax: { valid: true },
// mx: { valid: true, records: ["mail.mailinator.com"] },
// disposable: true,
// role_account: true,
// free_provider: false
// },
// suggestion: null
// }
Typos detection
const result = await mxcheck("user@gmial.com");
console.log(result.suggestion); // "user@gmail.com"
Pros
- One call handles syntax, MX, disposable, role accounts, free‑provider flags, and typo suggestions.
- Low latency (~5 ms).
Cons
- External dependency; you need an API key for higher limits.
Comparison of Methods
| Method | Format Check | MX Check | Disposable Blocklist | Typos Detection | Typical Latency |
|---|---|---|---|---|---|
| Regex | ✅ | ❌ | ❌ | ❌ | { |
| const { email } = req.body; | |||||
| const result = await mxcheck(email); |
if (!result.valid) { return res.status(400).json({ error: “Invalid email address”, reason: result.reason, suggestion: result.suggestion }); }
if (result.checks.disposable) { return res.status(400).json({ error: “Disposable email addresses are not allowed” }); }
// Email passed all checks – proceed with signup logic res.json({ success: true }); });
app.listen(3000, () => console.log(“Server running on port 3000”));
One API call can block fake emails, catch common typos, and flag disposable addresses, simplifying your validation pipeline.
---
**mxcheck** – free tier: 3,000 requests/month. Install with:
```bash
npm install mxcheck