Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use a three-state result—invalid, domain_mail_route_found, or unknown—to keep syntax checks and DNS evidence separate without claiming that an individual mailbox exists. Node.js can query a domain’s MX records with dns/promises.resolveMx(); a successful lookup is evidence of domain-level mail routing, not proof that an address will accept a message.

What the three states mean

A syntax parser and a DNS lookup answer different questions. Parsing checks whether the submitted address fits your application’s documented syntax policy. MX lookup checks whether DNS returns mail-exchanger records for the parsed domain. Neither check confirms that the local-part—the text before @—names a real mailbox.

State Meaning What it does not mean
invalid The input fails your documented policy or parser. It does not mean that an address rejected only because of a narrow policy is invalid under every possible email syntax.
domain_mail_route_found Syntax passed and the application found usable MX evidence for the domain. It does not prove the mailbox exists, accepts mail, or will receive a message.
unknown The available checks cannot justify either of the other outcomes. It is not a synonym for invalid.

The explicit unknown state matters because SMTP does not guarantee that a recipient can be checked in real time. RFC 5321 notes that “There may be circumstances where an address appears to be valid but cannot reasonably be verified in real time,” including when a server relays mail for another server or domain. A remote server may also defer or refuse mail according to policies that local syntax and DNS checks cannot see. RFC 5321

Choose a syntax policy before checking DNS

Decide which address forms your product accepts, and document that choice. A parser can enforce that policy; it cannot establish delivery. Avoid treating one hand-written regular expression as a complete standards parser, especially if the product must handle unusual or legacy forms.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Narrow application policy

For a product that intentionally accepts a limited set of ordinary internet addresses, a narrow policy can be simpler to explain and maintain. Its trade-off is false rejection: a form your policy excludes may still be valid under email standards. Tell users what formats are accepted and avoid presenting the result as a universal judgment about the address.

Broader compatibility

RFC 3696 discusses quoted local-parts. It calls them uncommon but says they “must be supported by applications that are processing email addresses.” The RFC states historical length limits of 64 octets for the local-part and 255 octets for the domain part; those are octet figures, not JavaScript character-count rules that can be applied blindly to internationalized input. RFC 3696

One library option is Haraka’s @haraka/email-address, whose documentation describes envelope and header parsing, quoted local-parts, address literals, internationalized addresses, and ESM/CommonJS entry points. Review its supported input flavor, current maintenance, and version against your application’s policy before adopting it; its documented capabilities are not a substitute for that review.

Implement the gate with Node.js DNS

Node.js documents resolveMx(domain) in its DNS promises API. A successful call returns an array of records containing priority and exchange. The example below assumes a parser that returns { ok: true, domain } or { ok: false }; replace that interface with your chosen parser and policy. Node.js DNS API

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import { resolveMx } from 'node:dns/promises';

async function assessEmail(input) {
  const parsed = parseUnderYourDocumentedPolicy(input);
  if (!parsed.ok) {
    return { status: 'invalid', reason: 'syntax' };
  }

  try {
    const records = await resolveMx(parsed.domain);

    if (records.length === 0) {
      return { status: 'unknown', reason: 'no-mx-result' };
    }

    return {
      status: 'domain_mail_route_found',
      signal: 'mx-records-found',
      mx: records.map(({ priority, exchange }) => ({ priority, exchange }))
    };
  } catch {
    return { status: 'unknown', reason: 'dns-query-inconclusive' };
  }
}

This is an illustrative pattern, not tested code. In particular, the parser is intentionally left as an application choice. Use a domain-normalization and parsing strategy appropriate to your accepted address forms, and do not silently turn DNS exceptions into a syntax verdict.

Define DNS outcomes rather than treating every lookup alike

resolveMx() asks specifically for MX records. SMTP’s routing rules also account for resolvable fully qualified names through address records, so “no MX records returned” is not automatically equivalent to “this domain cannot receive mail.” Your application should decide explicitly how to handle this case rather than assuming an empty MX array proves invalidity. RFC 5321

  • MX records returned: record the MX evidence and return domain_mail_route_found if that is sufficient under your policy. Do not label the mailbox verified.
  • No MX records returned: treat the result as inconclusive unless your application separately checks and interprets address-record fallback. The example returns unknown.
  • Explicit non-mail configuration: apply a documented policy for this DNS condition. Do not convert it into a general syntax failure; it is domain-routing evidence, not a parser result.
  • Resolver error, timeout, or transient failure: return unknown and preserve a reason useful for logs or retry decisions. A failed query does not establish that the user’s address is invalid.

The Node.js API documents the MX query and its result shape, but the application still needs an operational policy for latency, timeouts, retry behavior, and DNS outcomes. Keep those decisions separate from syntax classification so that a temporary infrastructure failure does not reject a user’s input as malformed.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Use the result safely in signup and contact flows

Choose a product action for each state based on the consequence of accepting an address. A signup form may permit an unknown result and require confirmation before enabling the account; a high-risk workflow may defer a decision or ask the user to retry. A contact form may accept the submission while making no promise that delivery succeeded.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Show a clear correction prompt for invalid only when the input fails the published syntax policy.
  • Describe domain_mail_route_found internally or in product copy as a routing signal, not mailbox verification.
  • For unknown, choose an explicit retry, defer, or confirmation path rather than silently rejecting the address.
  • Keep confirmation by sending a message distinct from this local gate: only interaction with the recipient mailbox can provide stronger evidence that the user can receive that message.

Do not expose raw DNS error text as if it were a user mistake. Log structured reasons such as dns-query-inconclusive for diagnostics, while presenting an actionable message appropriate to the form.

Choose between a narrow parser and a broader parser

Approach Best fit Trade-offs to review
Narrow application-level syntax policy plus Node.js MX lookup A simple flow that accepts ordinary internet addresses under a defined product policy. Accepted forms, false-rejection risk, DNS latency, failure handling, and how unknown results affect the user flow.
Maintained standards-oriented parser plus Node.js MX lookup A product that needs quoted or legacy local-parts, address literals, internationalized cases, or multiple syntax contexts. Supported grammar, envelope versus header mode, package maintenance, performance needs, and the product’s own acceptance policy.

The parser project’s repository makes its own performance characterization; that is not an independent benchmark. Select it for grammar and maintenance fit rather than assuming a performance result applies to your workload. For bulk screening or signals beyond this local gate, an external email-verification service may be an option, but it is not required to implement the tri-state pattern.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.