DEV Community

Gerald Mitchell
Gerald Mitchell

Posted on

How to Clean an Email List Locally with a Free Open-Source Node CLI

Disclosure: we built and maintain the tool in this post (email-list-cleaner, MIT). This article was written with AI assistance and reviewed by us.

Bounces hurt sender reputation, and many "list verification" services require uploading your contacts to a third party. If you just need to catch the obvious problems, you can do it on your own machine with a zero-dependency Node.js CLI.

Repo: https://github.com/5012763083a-oss/email-list-cleaner

What it checks

  • Syntax: is the address well-formed?
  • MX lookup: does the domain publish mail servers? Public DNS only, with no SMTP probing, so no mail server is contacted.
  • Disposable domains: flags throwaway inbox providers.
  • Role accounts: flags info@, admin@, support@ and similar addresses.
  • Typos: suggests fixes like gmial.com → gmail.com.
  • Duplicates: removed case-insensitively.

Nothing in your list leaves your machine. The only network traffic is DNS lookups for the domains.

Usage

Run it straight from GitHub with npx (Node required):

npx github:5012763083a-oss/email-list-cleaner contacts.csv -o cleaned.csv
Enter fullscreen mode Exit fullscreen mode

Options:

--column email   # which CSV column holds the address
--no-mx          # skip DNS lookups (fully offline)
--no-dedupe      # keep duplicates
Enter fullscreen mode Exit fullscreen mode

For example, if your export has the address in a Email Address column and you're offline:

npx github:5012763083a-oss/email-list-cleaner export.csv --column "Email Address" --no-mx -o cleaned.csv
Enter fullscreen mode Exit fullscreen mode

Reading the output

Your original columns are kept, and these are appended:

normalized,status,reason,syntaxValid,domain,hasMx,mxHosts,isDisposable,isRoleAccount,isFreeProvider,didYouMean
Enter fullscreen mode Exit fullscreen mode

status is one of valid, invalid, risky or unknown. A practical workflow:

  1. Drop invalid rows (bad syntax or no MX).
  2. Review risky rows: disposable or role addresses may be fine for a B2B list but not for a newsletter.
  3. Check didYouMean: fixing jane@gmial.com recovers a real subscriber instead of losing them.
  4. unknown usually means a DNS lookup failed; rerun later. It's also the status you get for every address with --no-mx, with the reason mx_not_checked.

Open cleaned.csv in a spreadsheet and filter by status.

Limits

MX checks tell you a domain can receive mail, not that a specific mailbox exists. That's deliberate: confirming mailboxes requires SMTP probing, which is slow and can get your IP flagged. For most list hygiene, syntax + MX + disposable + typo checks catch the bulk of bad addresses.

The free edition processes the first 500 rows per file. It's MIT-licensed, so you can fork it and change FREE_LIMIT in bin/email-clean.js.

Run the tests with npm test.


If you'd rather support the project, Email List Cleaner Pro ($9) removes the cap and adds batch mode and a summary report: https://6907000850732.gumroad.com/l/khnxbj?ref=devto

Top comments (0)