How to Validate Email Addresses in Node.js (2026 Guide)
Email validation is one of those problems that looks simple but isn't. A basic regex catches obvious typos, but it won't tell you if the domain has a mail server, if the address is a disposable throwaway, or if the mailbox actually exists.
This guide covers 4 approaches to email validation in Node.js, from basic regex to full API-based verification, with working code for each.
1. Regex Validation (Basic)
The simplest approach. Catches formatting errors but nothing else.
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 <= 254;
}
console.log(isValidEmail("user@gmail.com")); // true
console.log(isValidEmail("not-an-email")); // false
console.log(isValidEmail("user@.com")); // false
Pros: Fast, no dependencies, no network calls.
Cons: user@fakdomain123.com passes validation. So does user@mailinator.com. You're only checking format, not deliverability.
2. MX Record Lookup (Medium)
Check if the domain actually has mail servers configured. This catches fake domains that pass regex.
const dns = require('dns').promises;
async function hasMxRecords(domain) {
try {
const records = await dns.resolveMx(domain);
return records && records.length > 0;
} catch (err) {
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 };
}
// Usage
const result = await validateEmail("user@fakdomain123.com");
// { valid: false, reason: "Domain has no mail server" }
Pros: Catches fake domains. Uses built-in Node.js dns module (no dependencies).
Cons: Doesn't catch disposable emails, role accounts, or typos. DNS lookups add ~10-50ms latency.
3. Disposable Email Detection (Better)
About 60% of fake signups use disposable email services like Mailinator, Guerrilla Mail, or 10MinuteMail. You need a blocklist.
// Maintain a Set of known disposable domains
const disposableDomains = new Set([
"mailinator.com",
"guerrillamail.com",
"tempmail.com",
"throwaway.email",
"yopmail.com",
// ... 500+ more domains
]);
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 signups.
Cons: You need to maintain the list yourself. New disposable services appear constantly. Combining this with regex + MX checks requires writing orchestration code.
4. API-Based Validation (Best)
An API handles all checks in one call: syntax, MX records, disposable detection, typo suggestions, role account detection, and more.
// Using MXCheck API via fetch (no dependencies)
async function validateEmail(email) {
const res = await fetch(
`https://mxcheck.dev/api/validate?email=${encodeURIComponent(email)}`
);
return await res.json();
}
const result = await validateEmail("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
// }
The API also catches typos:
const result = await validateEmail("user@gmial.com");
console.log(result.suggestion); // "user@gmail.com"
Try MXCheck Free
3,000 free requests per month. Syntax, MX, disposable, typo detection in one call.
Get Free API KeyComparison
| Method | Catches fake format | Catches fake domains | Catches disposable | Catches typos | Latency |
|---|---|---|---|---|---|
| Regex | Yes | No | No | No | <1ms |
| MX Lookup | Yes | Yes | No | No | 10-50ms |
| Blocklist | Yes | No | Yes | No | <1ms |
| API (MXCheck) | Yes | Yes | Yes | Yes | ~5ms |
Which approach should you use?
- Contact form with low stakes: Regex is fine.
- User registration: MX lookup + disposable detection at minimum.
- Lead generation or paid signups: API-based validation. Bad emails cost you money in bounced campaigns and wasted outreach.
- Enterprise or compliance: API-based, plus consider SMTP verification for mailbox-level confirmation.
Quick start: Add email validation to Express.js
const express = require("express");
const app = express();
app.use(express.json());
app.post("/signup", async (req, res) => {
const { email, password } = req.body;
// Validate email before creating account
const check = await fetch(
`https://mxcheck.dev/api/validate?email=${encodeURIComponent(email)}`
);
const result = await check.json();
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 is valid, proceed with signup
// ... create user account
res.json({ success: true });
});
app.listen(3000);
That's it. One API call in your signup flow blocks fake emails, catches typos before they become bounces, and flags disposable addresses before they waste your resources.