# How to clean an email list before a cold outreach campaign

_2026-07-18 · Boundstone (https://boundstone.io/blog/clean-email-list-cold-outreach)_


You bought a list, or scraped one, or exported it from a form that never validated a thing. Now you want to run a cold outreach campaign against it. Before you load it into your sending tool, clean the email list before cold outreach starts — because every hard bounce you send is a vote against your sender reputation, and mailbox providers count votes. This is the hygiene pass that happens before warm-up, before sequencing, before you touch send. It removes the bounces you can see coming.

## The bounces you can see coming, and the ones you can't

A hard bounce is a permanent rejection. Some are predictable from the address alone: it's malformed, the domain publishes no mail server, it's a throwaway domain, or it's a shared inbox nobody reads. Others stay invisible until the receiving server tells you — the mailbox was deleted last month, the account is full, the server accepts everything and reads none of it. Validation handles the first group. It cannot handle the second, and any tool that claims otherwise is guessing. That split matters, and we'll come back to it.

## Four checks that remove avoidable bounces

`POST /v1/verify/email` runs four checks and reports each one:

- **Syntax** — is the address well-formed at all? `valid_syntax`.
- **MX** — does the domain actually publish a mail server? `mx_found`. No MX record means nothing there is set up to accept mail. Near-certain bounce.
- **Disposable** — is this a throwaway domain (mailinator, ten-minute-mail and friends)? `disposable`. These evaporate before your first follow-up.
- **Role account** — is it `info@`, `sales@`, `support@`? `role_account`. A desk, not a person, and usually an unattended distribution list.

Example:

```bash
curl -X POST https://api.boundstone.io/v1/verify/email \
  -H "Authorization: Bearer bs_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"info@example.com"}'
```

Response (trimmed):

```json
{
  "valid_syntax": true,
  "domain": "example.com",
  "mx_found": true,
  "disposable": false,
  "role_account": true,
  "free_provider": false,
  "checks": {
    "performed": ["syntax", "mx", "disposable_list", "role_list"],
    "not_performed": ["smtp_mailbox", "catch_all"]
  }
}
```

The `checks` block rides on every response and tells you exactly what was measured. `free_provider` is returned too (gmail, outlook, and the rest) — handy for segmenting personal from business addresses, not a reason to drop anyone on its own.

## Run the whole list in one pass

You don't validate a cold list one address at a time. Send the entire file to the bulk endpoint as raw CSV.

```csv
email
jordan@acme.com
info@vendor.io
temp@mailinator.com
notanemail
```

Then:

```bash
curl -X POST https://api.boundstone.io/v1/bulk/email \
  -H "Authorization: Bearer bs_live_YOUR_KEY" \
  -H "Content-Type: text/csv" \
  --data-binary @list.csv
```

You get back `HTTP 202` and a `job_id`. Pull the results when it finishes:

```bash
curl https://api.boundstone.io/v1/bulk/JOB_ID/results.csv \
  -H "Authorization: Bearer bs_live_YOUR_KEY"
```

One credit is reserved per row and refunded for any row that errors, so the address that breaks the parser costs you nothing. Free jobs run up to 250 rows; paid jobs up to 10k. Prefer no code at all? The dashboard has a CSV upload and a paste box that runs the same job. The bulk flow is covered step by step in our [bulk email validation walkthrough](/blog/bulk-email-validation-csv), and the hosted [email validator](/tools/email-validator) checks a single address in the browser when you just want a spot check.

## What "clean" actually means here

Here's the part most vendors skate past. Boundstone confirms the address is well-formed, the domain can receive mail, it isn't disposable, and it isn't an obvious role account. It does not knock on the mailbox door. SMTP mailbox verification and catch-all detection are `not_performed`, and we print that on every response instead of implying a certainty we don't have. It also doesn't flag spam traps or predict inbox placement — those ride on sending-reputation signals that live nowhere in an address.

So a clean result means "no reason to bounce that we can see from the outside." It does not mean "this specific person still works there and reads this inbox." The mailbox could have closed yesterday. The domain could be a catch-all that accepts everything and forwards nothing. Only the receiving server knows, and it only tells you when you send. Validation shrinks the avoidable-bounce pile — it does not promise zero. If you want the longer argument for why we won't fake a mailbox-level prediction, read [how we think about bounce rate](/blog/reduce-email-bounce-rate).

## Validation is hygiene, not warm-up

Removing dead addresses protects your reputation. It does not build one. If your sending domain is cold, a clean list still needs the unglamorous disciplines: warm the domain up, ramp volume gradually, keep SPF, DKIM, and DMARC in order, and watch your reply and complaint signals. Validation is the first gate, not the whole gauntlet. Clean the list, then send like you have something to lose — because you do.

## The short version

- **Sender reputation is the whole game.** Cold outreach lives or dies on it, and hard bounces are the fastest way to spend it.
- **`POST /v1/verify/email` removes the avoidable bounces.** Bad syntax, no MX, disposable, role account — and every response lists `checks.performed` and `checks.not_performed`.
- **Bulk-validate the whole file** with `POST /v1/bulk/email` — one credit per row, refunded on error, up to 10k rows on a paid plan.
- **Validation does not confirm the mailbox exists.** It does not flag spam traps or predict inbox placement either. `smtp_mailbox` and `catch_all` are `not_performed`; the bounces only the receiving server knows stay invisible until you send.
- Clean first, then warm up and ramp. Hygiene isn't reputation.
- Free tier: 250 credits a month, no card, and they never expire.
