How to Clean a List After Import: Invalid, Bounced and Unsubscribed Contacts
Cleaning a list after import means three passes, not one: reject addresses that can't receive mail, suppress everyone who already bounced or complained, and remove opt-outs and non-consented contacts before anything is sent. Do that in the import dialog and the suppression list, verify the totals add up, then warm up with a small batch instead of mailing the whole file.
What you'll set up and what you need
An imported CSV almost always carries three kinds of problems, and they need different handling.
- Invalid addresses. Typos, missing
@, trailing commas, spaces inside the address, placeholder rows liketest@test. These are syntactically bad and should never enter your sendable list. - Previously bounced contacts. Addresses that hard-bounced in your old tool, or that you know are dead. If they aren't suppressed, your first send will bounce again and damage your sending reputation.
- Unsubscribed or non-consented contacts. People who opted out in the previous system, plus anyone you can't show a lawful basis for. These must be suppressed permanently, not deleted and forgotten.
Before you start, gather:
- The raw CSV, untouched.
- Your old suppression/opt-out file, if the previous tool lets you export one.
- Access to the import settings so you can map custom fields and apply tags.
- A sending domain with DKIM, SPF and DMARC configured and verified — do this before any send, not after.
In Mailerflow, the pieces you'll use are CSV import with duplicate and validity checks, custom fields and tags, and automatic suppression of bounces and complaints. The Free plan covers 2,500 contacts and 10,000 emails a month, so check your file size against your plan before importing.
Step-by-step: cleaning the list
1. Export and inspect the raw file. Open the CSV in a spreadsheet and look at the columns before touching anything. Check that email addresses sit in one column, that date columns use a single format, and that there are no merged header rows or totals rows at the bottom. Sort by the email column and scan for obvious junk.
2. Prepare the CSV. One email address per row, one consistent header row, no blank rows, no formulas. Add a source column (for example event-2023) so you can trace where each contact came from later. Save as UTF-8 CSV.
3. Import with checks enabled. In the import dialog, turn on duplicate checking and validity checking. Map your CSV columns to the matching fields — email, first name, last name, and any custom fields you created. Apply a source tag such as import-legacy-event so this batch stays identifiable.
4. Read the import report. The report splits rows into accepted, duplicates skipped, and invalid rejected. Write those three numbers down; you'll reconcile them in the verification step.
5. Keep the rejected addresses out. Export or copy the rejected list into a separate file and store it. If you ever re-import a corrected version of the same file, you'll want to know which rows were already judged invalid.
6. Handle bounced contacts. If your previous tool exports a bounce list, import those addresses into your suppression list before your first send. Going forward, Mailerflow suppresses bounces and complaints automatically, so you only need the historical file once.
7. Handle unsubscribes first. Import your opt-out file into suppression before importing the main list, or at minimum before the first campaign. Suppression beats deletion: a suppressed address can't be mailed even if someone re-imports it by accident.
8. Tag by engagement source. If your CSV has a column for last open, last click, or signup date, map it to a custom field and tag contacts accordingly (engaged-2024, dormant-2y). This is what makes step 9 possible.
9. Set warm-up limits before the first send. Don't mail the full list on day one. Start with a small batch, watch delivery and bounce numbers, and increase gradually.
A worked example
The numbers below are illustrative, not a real customer.
A sender imports an old event list of 12,400 rows.
| Stage | Rows | Running total |
|---|---|---|
| Raw CSV rows | 12,400 | 12,400 |
| Blank or malformed email removed in prep | 310 | 12,090 |
| Duplicates skipped at import | 640 | 11,450 |
| Invalid addresses rejected by validity check | 180 | 11,270 |
| Matched against suppression list (unsubscribes + historical bounces) | 470 | 10,800 |
| Sendable contacts | 10,800 |
The import report should read: 11,270 accepted, 640 duplicates skipped, 180 invalid rejected. Those three add up to 12,090 — the number of rows uploaded after prep, not the raw 12,400. The 470 suppressed contacts are matched after import, so they don't appear in the import report at all; they still exist as records, just excluded from every send.
The sender applies the tag import-legacy-event, then builds a segment: tag is import-legacy-event AND last engagement is older than 12 months. Say that segment holds about two-thirds of the 10,800. The first campaign goes to a 500-contact warm-up slice drawn from the more recently engaged part of the list, not the whole file.
How to check it works
Run these checks before the first real send.
- Reconcile the report. Accepted + duplicates skipped + invalid rejected should equal the rows you uploaded. If it doesn't, something was silently dropped.
- Test the suppression. Build a segment of contacts you know are on the suppression list and confirm the count is zero. If suppressed addresses appear, stop and fix the import before sending.
- Confirm the tag. Filter by your source tag and check the count matches the accepted number from the report.
- Send a small test campaign. Look at delivery, bounces and complaints in the campaign analytics. Watch for hard bounces and complaints; any hard bounce means bad addresses are still in the list, so go back to the validity check and the suppression import.
- Watch reputation over time. Reputation monitoring is the ongoing check, not a one-off. If it trends down after a send, pause and re-segment rather than pushing more volume.
Common mistakes and fixes
Re-importing the same file. Duplicate checks catch most of it, but only if they're enabled. Always apply a source tag so you can spot and merge accidental double imports.
Mailing unsubscribes. This happens when opt-outs are imported after the first campaign, or not at all. Import opt-outs into suppression first, every time.
Treating soft and hard bounces the same. A soft bounce (full mailbox, temporary server issue) may recover; a hard bounce (address doesn't exist) won't. Suppress hard bounces permanently and let soft bounces retry.
Skipping warm-up. Blasting a large imported list on day one is a common way to damage your sending reputation. Use warm-up limits and grow volume gradually.
Assuming imported contacts consented. They didn't consent to you unless you can show it. Imported lists need a lawful basis, and for new signups the cleanest path is an embeddable form with double opt-in and consent records, so the evidence exists from the start.
Not segmenting by engagement. A stale list drags down the whole send. Segment by recency and activity so your engaged contacts carry the campaign.
Next steps
To keep the list clean going forward:
- Build dynamic segments on engagement and website behavior so future sends target active contacts automatically.
- Use AI segmentation from a plain-language description when you want to split the list quickly — for example, "contacts who opened nothing in six months but clicked a pricing link."
- Route new signups through an embeddable form with double opt-in and consent records, so the evidence exists from the start and the problem doesn't recur.
- Re-check the import report after every future import, and reconcile the three numbers each time.
If you're moving from another tool, free migration help covers contacts, suppression lists, templates and core automations on eligible paid plans. You can review what's included on the Mailerflow features page.
FAQ
Should I delete bounced contacts or just suppress them? Suppress them. Deletion removes the record, which means a later import can bring the address straight back in. Suppression keeps it out of every send permanently.
Can I re-import a cleaned file without creating duplicates? Yes, as long as duplicate checking is enabled during import. The report will show how many rows were skipped as duplicates, so you can confirm nothing was added twice.
How long should I wait before mailing an imported list? There's no fixed number of days. What matters is that suppression is loaded, the domain is verified, and you start with a small warm-up batch rather than the full list.
What counts as an invalid address?
Anything that can't receive mail: missing @, spaces or commas inside the address, malformed domains, or placeholder entries. Validity checks catch the structural problems; suppression handles the addresses that look fine but have already bounced.
Ready to make the next import unnecessary? Create an embeddable signup form with double opt-in and build dynamic segments in Mailerflow — start free.

