How to Validate Email Addresses in Node.js (2026 Guide)

Published: (February 12, 2026 at 12:24 PM EST)
3 min read
Source: Dev.to

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 dns module (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

MethodFormat CheckMX CheckDisposable BlocklistTypos DetectionTypical 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
0 views
Back to Blog

Related posts

Read more »

Infinity - Where Does JavaScript End?

Infinity – Where Does JavaScript End? !Infinity illustrationhttps://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=au...