Back to blog
EmailDNSDeveloper GuideValidation

How to Check if an Email Domain Is Valid

Check if an email domain can receive mail. Verify MX records, SPF, DKIM, and DMARC with command-line tools, code examples, and free online checkers.

SendPigeon TeamMarch 11, 20265 min read

An email domain is valid if it can receive mail. The minimum requirement: at least one MX record in DNS pointing to a mail server. No MX record, no email delivery.

But "valid" has layers. A domain might accept email but land everything in spam because it's missing authentication records. Here's how to check all of it.

TL;DR

Quick check: Run dig MX domain.com +short in your terminal. If it returns mail server records, the domain is valid for receiving email.

Full check: Use our free deliverability checker to verify MX, SPF, DKIM, and DMARC in one step.


Check MX records (can the domain receive email?)

MX records tell sending servers where to deliver email for a domain. If a domain has MX records, it can receive email.

Command line

# macOS / Linux
dig MX gmail.com +short

# Output:
# 5 gmail-smtp-in.l.google.com.
# 10 alt1.gmail-smtp-in.l.google.com.
# 20 alt2.gmail-smtp-in.l.google.com.
# Windows
nslookup -type=MX gmail.com

If you get results, the domain is valid. If dig returns nothing, the domain either doesn't exist or can't receive email.

In Node.js

import dns from "node:dns/promises";

async function hasValidMx(domain: string): Promise<boolean> {
  try {
    const records = await dns.resolveMx(domain);
    return records.length > 0;
  } catch {
    return false;
  }
}

await hasValidMx("gmail.com");     // true
await hasValidMx("notadomain.xyz"); // false

In Python

import dns.resolver

def has_valid_mx(domain: str) -> bool:
    try:
        records = dns.resolver.resolve(domain, "MX")
        return len(records) > 0
    except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN, dns.resolver.NoNameservers):
        return False

has_valid_mx("gmail.com")      # True
has_valid_mx("notadomain.xyz") # False
pip install dnspython

Edge case: no MX but has A record

Per RFC 5321, if a domain has no MX records, sending servers fall back to the domain's A record. So a domain without MX records might still receive email — but this is unusual and unreliable.


Check SPF, DKIM, and DMARC (can the domain send legitimate email?)

MX records tell you about receiving. For sending, check authentication records.

SPF

SPF lists which servers are allowed to send email for a domain:

dig TXT domain.com +short | grep "v=spf1"

# Example output:
# "v=spf1 include:_spf.google.com ~all"

If there's no SPF record, anyone can spoof emails from that domain.

DKIM

DKIM records are at a specific selector subdomain. You need to know the selector (it varies by provider):

# Google Workspace
dig TXT google._domainkey.domain.com +short

# SendPigeon
dig CNAME sp._domainkey.domain.com +short

DMARC

DMARC tells receiving servers what to do when SPF or DKIM fails:

dig TXT _dmarc.domain.com +short

# Example output:
# "v=DMARC1; p=reject; rua=mailto:dmarc@domain.com"

Check everything at once

Running four dig commands is tedious. Use our deliverability checker to verify MX, SPF, DKIM, and DMARC in one step — just enter the domain.


Validate email domains in your application

If you're building a signup form or email input, validating the domain catches typos and fake addresses before they become bounces.

Basic validation (Node.js)

import dns from "node:dns/promises";

async function validateEmailDomain(email: string): Promise<{
  valid: boolean;
  reason?: string;
}> {
  const domain = email.split("@")[1];

  if (!domain) {
    return { valid: false, reason: "No domain in email address" };
  }

  try {
    const mx = await dns.resolveMx(domain);
    return { valid: mx.length > 0 };
  } catch (err) {
    const code = (err as NodeJS.ErrnoException).code;

    if (code === "ENOTFOUND") {
      return { valid: false, reason: "Domain does not exist" };
    }
    if (code === "ENODATA") {
      return { valid: false, reason: "Domain has no MX records" };
    }
    return { valid: false, reason: "DNS lookup failed" };
  }
}

await validateEmailDomain("user@gmail.com");        // { valid: true }
await validateEmailDomain("user@gmial.com");        // { valid: false, reason: "Domain does not exist" }
await validateEmailDomain("user@notreal.example");  // { valid: false, reason: "Domain does not exist" }

When to validate

  • Signup forms — Catch typos like gmial.com before the user submits
  • Bulk imports — Filter invalid domains before sending to avoid bounces
  • Webhook processing — Validate email addresses from external sources

MX validation catches invalid domains but not invalid mailboxes. user@gmail.com passes MX validation even if that specific user doesn't exist. For mailbox-level verification, you'd need an email verification service.


Common invalid domain patterns

PatternExampleWhy it fails
Typosgmial.com, outlok.comDomain doesn't exist or has no MX
Disposable domainstempmail.com, guerrillamail.comValid but temporary — email will bounce later
Internal domainscompany.local, mail.internalNot publicly resolvable
Missing TLDuser@companyNot a valid domain

Domain validation vs email verification

Domain validationEmail verification
ChecksDNS records existSpecific mailbox exists
SpeedMilliseconds (DNS lookup)Seconds (SMTP handshake)
AccuracyCatches invalid domainsCatches invalid addresses
False positivesValid domain, invalid mailboxRare
Use caseSignup forms, basic filteringList cleaning, pre-send validation

For most applications, domain validation is enough for the signup flow. Run full email verification as a batch process on your existing list.


Next Steps