LIST HYGIENE

How to clean an email list before your next send

A 10K list with a 4 % bounce rate will scorch a domain you spent six weeks warming. List hygiene isn't optional — it's the cheapest insurance you can buy before a send. This guide walks you through the exact five-pass process SparrowiMailer runs on every upload.

How dirty is your list?

Most lists degrade at 2–3 % per month. People change jobs, companies fold, ISPs retire domains. A list sitting unused for six months can easily carry a 15–20 % invalid-address rate. Before you do anything else, run a quick audit:

  • Export to CSV and sort by created_at — anything older than 12 months is high-risk.
  • Check your last campaign bounce report. Hard-bounce rate > 2 % is a red flag.
  • Look for free-mail domains that spike after a giveaway or lead-magnet launch — those are often throwaway signups.

Pass 1 — Syntax

The cheapest check: does the address even look like an email address? A regex test catches obvious garbage — missing @, double dots, illegal characters. This is a pre-filter only; it won't catch fake@gmail.com but it will drop name @domain or user@.com.

# Quick Python syntax pre-filter
import re, csv

EMAIL_RE = re.compile(r'^[^@\s]+@[^@\s]+\.[a-z]{2,}$', re.IGNORECASE)

with open('raw_list.csv') as f, open('syntax_pass.csv', 'w') as out:
    reader = csv.reader(f)
    writer = csv.writer(out)
    for row in reader:
        if EMAIL_RE.match(row[0].strip()):
            writer.writerow(row)

Expect to remove about 0.5–2 % of addresses here, mostly from messy import sources.

Pass 2 — MX lookup

For each remaining address, resolve the domain's MX record. No MX means the domain can't receive email — period. This kills unregistered domains, expired domains, and mistyped TLDs. Run it in parallel threads to keep it fast:

import dns.resolver, csv, concurrent.futures

def has_mx(domain):
    try:
        dns.resolver.resolve(domain, 'MX', lifetime=5)
        return True
    except Exception:
        return False

with open('syntax_pass.csv') as f:
    rows = list(csv.reader(f))

domains = {r[0].split('@')[1].lower() for r in rows}
with concurrent.futures.ThreadPoolExecutor(max_workers=100) as ex:
    mx_ok = {d: ex.submit(has_mx, d) for d in domains}
    mx_ok = {d: fut.result() for d, fut in mx_ok.items()}

with open('mx_pass.csv', 'w') as out:
    csv.writer(out).writerows(r for r in rows if mx_ok.get(r[0].split('@')[1].lower()))

Pass 3 — SMTP ping

With MX confirmed, open a real SMTP connection and issue RCPT TO without actually delivering. Most servers respond with 550 No such user for unknown mailboxes. This is the deepest pass and costs the most time — allocate 5–15 seconds per domain. SparrowiMailer's validator engine does this at ~80K addresses per minute using a distributed pool.

Important: Don't SMTP-ping from your production sending IP. Use a separate probe IP or — better — use SparrowiMailer's validator API so your sender reputation is never at risk.

Pass 4 — Catch-all detection

Some mail servers accept all RCPT TO commands regardless of whether the mailbox exists. These are "catch-all" or "accept-all" domains. You can detect them by probing with a guaranteed-junk address (noreply-zz99xyz@domain.com) — if the server says 250, it's a catch-all.

Catch-all addresses should be segmented, not deleted outright. Send to them at a lower volume and watch bounce feedback carefully. Remove any that hard-bounce on first send.

Pass 5 — Role accounts & disposables

Even a syntactically valid, MX-verified, SMTP-confirmed address can hurt you if it's a role account (info@, support@, admin@) or a disposable-mail provider. Role accounts are rarely individuals — they're shared mailboxes or ticketing systems that frequently flag marketing mail as spam. Disposables expire within hours or days.

Maintain a blocklist of ~120 disposable-mail domains and a role-prefix list. SparrowiMailer's validator flags both automatically in the result CSV.

Across 400M validations in 2025, SparrowiMailer flagged between 12 % and 18 % of uploaded addresses as invalid or high-risk. If your list cleans below 10 %, that's unusual — great hygiene or a very young list. If it cleans above 25 %, don't send until you understand where those addresses came from.

Email validation dashboard showing pass rates per category
SparrowiMailer's validator breaks down results by pass — syntax, MX, SMTP, catch-all, and role/disposable — so you know exactly what to do with each segment.

Working with the result CSV

After all five passes, your CSV will have a status column with one of these values:

Status Meaning Action
validPassed all five passesSend normally
invalidFailed syntax, MX, or SMTPRemove immediately
catch_allDomain accepts all RCPT TOSend at lower volume; remove if hard-bounce
roleRole account prefix detectedSuppress or put in a separate low-vol list
disposableKnown disposable-mail providerRemove — deliverability is near zero
riskyHistorical spam-trap signalRemove — never send to known traps

Import valid addresses into your send list. Archive the rest in a suppression file — you'll need it for future uploads to avoid re-adding cleaned addresses.

How often to clean

  • Before every major campaign if the list hasn't been mailed in 3+ months.
  • Quarterly for active lists mailed regularly.
  • At import — any new list from a third-party source should be validated before a single send.
  • After a bounce spike — if a campaign comes back with > 1.5 % hard bounces, clean before the next one.

The economics

SparrowiMailer charges 1 validator credit per address. At the Growth tier (₹999/mo), you receive 1,000 free validator credits. A 10K list costs 10 credits — less than ₹10 at pay-as-you-go rates. Compare that to the cost of a sender reputation repair or a fresh domain purchase. The maths are obvious.

Run validation as part of every import workflow, not as a one-off rescue. Clean lists compound — each campaign you send to a hygienically maintained list improves your sender score, which improves the next campaign, and so on.

Share: Twitter / X LinkedIn Validate your list free →

Related reads

Clean your next list in minutes

200 free validation credits when you sign up. No credit card required.

Start for free → See pricing