Suped

How can I bulk check and clean MX records for a list of domains?

Matthew Whittaker profile picture
Matthew Whittaker
Co-founder & CTO, Suped
Published 10 Jul 2025
Updated 22 May 2026
8 min read
Summarize with
A clean editorial thumbnail about bulk checking MX records.
Yes. For a list of 500 or more domains, the fastest first pass is a bulk DNS MX lookup, then a cleanup step that classifies each domain into keep, suppress, or review. I usually start with dig because it can read a file of domains directly and return the raw MX answers without sending any mail.
The important caveat is that no MX record is not always the same as no mail route. SMTP delivery falls back to the domain's A or AAAA record when there is no MX. For list cleaning, I treat that as a review category, not an automatic delete. A null MX record, NXDOMAIN, and obvious parked-domain MX patterns are much stronger suppression signals.
  1. Fast pass: Run a bulk MX lookup against a normalized domain file and keep the queried domain beside every answer.
  2. Clean pass: Separate valid MX, null MX, NXDOMAIN, no MX with A fallback, and no mail route.
  3. Final pass: Send only the remaining address list to address-level validation, then test your own sending setup before mailing.

Use dig for the first pass

Put one domain per line in a plain text file. Strip schemes, paths, ports, spaces, and email local parts first. A clean input file matters because DNS tools do not know whether https://example.com/path is meant to be a domain, a URL, or dirty export data.
domains.txttext
example.com example.net example.org example.invalid
Then run a bulk MX query. The -f option reads the file line by line. I prefer +noall +answer +cmd for early investigation because the output includes enough query context to avoid losing track of which domain produced which answer.
Bulk MX lookupbash
dig mx -f domains.txt > mx-answers.txt +noall +answer +cmd

Why I avoid short output for cleanup

The command dig domain MX +short is useful for one domain, but it becomes awkward when hundreds of domains are mixed together. Short output returns the answer, not always the original query context.
  1. For inspection: Use command context so each answer can be tied back to the input domain.
  2. For parsing: Use a script that writes a real CSV with one decision per domain.

Clean the results into decisions

A valid MX answer is only one cleanup signal. The useful output is a decision table with the raw DNS result preserved. I do not want a script to silently delete domains just because a DNS response was empty for one resolver at one moment.

DNS result

Meaning

Action

Has MX
Mail route
Keep
Null MX
No mail
Suppress
NXDOMAIN
No domain
Suppress
No MX
A fallback
Review
Parked MX
Low intent
Suppress
MX cleanup categories for domain-list hygiene.
Common DNS answerstext
example.com. 3600 IN MX 10 mx1.example.net. example.org. 3600 IN MX 0 .
The second line is the one people miss. An MX target of a single dot with preference 0 is a null MX. It tells senders the domain accepts no mail. For cleanup, that is a suppression-grade signal because the domain owner published an explicit no-mail record.
If the answer looks unusual, investigate before deleting. Patterns such as parked-domain mail routes, typo domains, and old provider records are easier to spot when you compare the result against known suspicious MX records. It also helps to understand how MX records impact bounces before you suppress a large slice of a database.

Do not treat no MX as one answer

No MX with an A or AAAA record is a different result from NXDOMAIN or null MX. It can still receive mail through SMTP fallback. In a conservative cleanup, I mark it for review or address-level validation.

A practical cleanup workflow

Flowchart for cleaning a domain list with MX lookups.
Flowchart for cleaning a domain list with MX lookups.
For a one-time list cleanup, I use a staged workflow rather than one large delete rule. It keeps false suppressions low and makes the output easier to explain if a sales, CRM, or data team asks why a domain was removed.
  1. Normalize: Lowercase domains, remove schemes and paths, strip local parts after @, and deduplicate.
  2. Query: Run MX lookups with timeouts and retries so one slow resolver does not stall the batch.
  3. Classify: Write has MX, null MX, NXDOMAIN, no MX with fallback, no route, and parked MX.
  4. Verify: Spot-check a sample of each suppression bucket before changing the source database.
  5. Export: Send only keep and review domains into the next validation step, with reasons attached.
For domains you own, DNS hygiene should not stop at recipient-domain cleanup. Suped's domain health checker gives a fast read on MX-adjacent health across DMARC, SPF, DKIM, and DNS signals. That is useful when the cleanup exposes domains that also need authentication work.
0.0

What's your domain score?

Deep-scan SPF, DKIM & DMARC records for email deliverability and security issues.

I keep the widget step separate from the raw bulk lookup. The lookup answers the database question: which recipient domains have a usable mail route? The domain health check answers the owned-domain question: are the domains I control ready to send and receive with clean authentication signals?
Domain health checker sample results showing DMARC, SPF, DKIM scorecards and detailed validation checks
Domain health checker sample results showing DMARC, SPF, DKIM scorecards and detailed validation checks

Script a CSV you can review

The command-line pass is good for discovery. For cleanup, I want a CSV because it can go back into a database or spreadsheet with a status column. This shell script keeps the logic simple and produces one or more rows per domain.
mx-cleanup.shbash
#!/usr/bin/env bash input=${1:-domains.txt} printf 'domain,status,preference,mx_host\n' normalize_domain() { sed -E 's#^[A-Za-z]+://##; s#/.*$##; s/:.*$//; s/^www\.//' | tr '[:upper:]' '[:lower:]' } while IFS= read -r raw; do domain=$(printf '%s' "$raw" | normalize_domain | xargs) [ -z "$domain" ] && continue mx=$(dig +time=2 +tries=1 +short MX "$domain" 2>/dev/null) if printf '%s\n' "$mx" | awk '$2=="." {found=1} END {exit !found}' then printf '%s,null_mx,,.\n' "$domain" continue fi if [ -n "$mx" ]; then printf '%s\n' "$mx" | sort -n | while read -r pref host; do printf '%s,has_mx,%s,%s\n' "$domain" "$pref" "${host%.}" done continue fi rcode=$(dig +time=2 +tries=1 SOA "$domain" +noall +comments | awk '/status:/ {print $6}' | tr -d ',') if [ "$rcode" = "NXDOMAIN" ]; then printf '%s,nxdomain,,\n' "$domain" continue fi a=$(dig +time=2 +tries=1 +short A "$domain" | head -n 1) aaaa=$(dig +time=2 +tries=1 +short AAAA "$domain" | head -n 1) if [ -n "$a$aaaa" ]; then printf '%s,no_mx_a_fallback,,\n' "$domain" else printf '%s,no_mail_route,,\n' "$domain" fi done < "$input"
Run it against a copy of your export, not the production table. Then review counts by status before taking action. A high number of no_mx_a_fallback rows is a sign to slow down, because those domains exist and still have a standards-defined delivery path.

Quick one-liner

  1. Best use: Fast discovery on a clean list of domains.
  2. Weak spot: Negative answers need more parsing before suppression.

Reviewable CSV

  1. Best use: Database cleanup where every removal needs a reason.
  2. Weak spot: Parked-domain patterns still need local policy and review.

Set the suppression policy first

The biggest mistake in bulk MX cleanup is deciding the removal rules after seeing a messy export. I set the policy first, then run the script, then review the counts. That keeps the cleanup from turning into a guessing exercise where every strange result gets handled differently.
For most commercial lists, I use three decision buckets. Suppress means the domain has a strong no-mail signal. Review means the domain exists, but DNS is incomplete, unusual, or temporarily broken. Keep means there is a normal mail route and no obvious reason to remove the domain before address-level validation.
  1. Suppress: NXDOMAIN, null MX, no A or AAAA fallback, and known parked-domain mail routes.
  2. Review: No MX with A fallback, SERVFAIL, timeout, malformed answers, and unfamiliar hosted patterns.
  3. Keep: At least one MX hostname that resolves, with no parked-domain or no-mail signal.
Timeouts deserve their own note. I do not treat a timeout as a bad domain on the first pass. Resolver rate limits, local network issues, and transient DNS failures can create false negatives. Run a second pass for timeouts with a different resolver or a slower rate before suppressing anything.

Check provider intent

Google Admin console screen showing MX record setup rows.
Google Admin console screen showing MX record setup rows.
Provider intent matters. If a domain is meant to receive through Google Workspace, the expected records should match Google's documented setup. The Google Workspace MX setup page is useful when you are checking whether a customer's records are incomplete, old, or pointed somewhere unexpected.
For a cold database, I do not try to infer too much from provider names alone. Hosted mail records prove there is a route, not that an individual mailbox exists. Parked-domain mail records are different: those often accept or sink mail for domains that are not real business prospects.

What MX cleanup cannot prove

  1. Mailbox exists: MX records only prove a domain-level route, not a valid address.
  2. Catch-all status: DNS cannot confirm whether every local part is accepted.
  3. Consent: A working MX record says nothing about permission or engagement quality.
  4. Reputation: Recipient-domain health does not fix sender-domain authentication or listing issues.

Where Suped fits after the bulk pass

The bulk MX pass is a data hygiene job. Suped fits after that when the work turns into ongoing email authentication, domain health, and deliverability monitoring. Suped is our DMARC reporting and email authentication platform, and it is the best overall practical choice when teams need one place for DMARC, SPF, DKIM, hosted SPF, hosted DMARC, hosted MTA-STS, alerts, and blocklist (blacklist) visibility.
After cleaning recipient domains, check your own sending side before you mail the list. Suped's email tester helps inspect a real message, while DMARC monitoring and blocklist monitoring catch the issues that a one-time MX script will never see.
For agencies and MSPs, the practical advantage is the multi-tenant workflow. A script can clean one CSV. Suped keeps domain authentication, source detection, issue alerts, and client reporting in one operating view, with steps to fix rather than raw DNS output only.

Views from the trenches

Best practices
Normalize domains before lookup so schemes, paths, ports, and spaces do not pollute results.
Classify null MX, NXDOMAIN, parked MX, and A fallback separately before suppression.
Keep the raw DNS answer beside each decision so bad filters can be reversed later.
Sample a few suppressed domains manually before deleting records from a source database.
Common pitfalls
Treat no MX as review when an A or AAAA fallback exists, not as automatic deletion.
Do not use short MX output alone if the domain name is missing from every answer row.
Do not trust one MX hostname as the full picture when domains publish several priorities.
Do not send to parked-domain mail routes without a separate business reason to keep them.
Expert tips
Resolve MX hostnames to A or AAAA records before treating the route as usable today.
Keep list hygiene DNS checks separate from address validation so costs stay predictable.
Track provider patterns over time so hosted, parked, and retired domains are easier to spot.
Run sender-domain SPF, DKIM, DMARC, and MX checks before mailing the cleaned list at scale.
Marketer from Email Geeks says dig is the fastest first pass when the input is one clean domain per line and the output keeps query context.
2024-02-18 - Email Geeks
Expert from Email Geeks says no MX should be separated from null MX because SMTP fallback to A records still exists.
2024-03-06 - Email Geeks

My working rule

Bulk MX checking is a smart first filter, not a complete validation system. I use it to remove the obvious waste: NXDOMAIN, null MX, no mail route, and parked-domain patterns. I do not use it to prove that a mailbox exists or that a lead is safe to mail.
The cleanest answer is: run dig mx -f domains.txt for the quick pass, write a CSV classifier for decisions, preserve the raw DNS evidence, then validate the remaining addresses and monitor your own sending domain health before any campaign.

Frequently asked questions

DMARC monitoring

Start monitoring your DMARC reports today

Suped DMARC platform dashboard

What you'll get with Suped

Real-time DMARC report monitoring and analysis
Automated alerts for authentication failures
Clear recommendations to improve email deliverability
Protection against phishing and domain spoofing
    How can I bulk check and clean MX records for a list of domains? - Suped