Data Quality for Outbound: Catching Bad Records Before You Send
Last updated on .
Before you start
4 things to have ready. Each one is assumed by a step below; get it first.
A spreadsheet export of the list
Every check works on a copy, so any change can be traced back.
Your do-not-contact and customer lists
Records are removed against these lists, so export them up to date before you start; an outdated list lets blocked contacts back in.
Bounce and reply reports from past sends
Step 6 sets your stop line from these reports. Without them, send a smaller pilot and read its bounces before sending more.
Write access to the source records
Failures are fixed or flagged where the data lives; otherwise the same bad records return with the next import.
The steps
7 steps, in order. Tick each one once its check passes; “How you know it worked” is what you should see before moving on.
- Copy the list and tag sources
- Standardise every field format
- Remove duplicates and blocked contacts
- Check every email address
- Confirm titles and company details
- Send a small pilot batch
- Log failures and suppress them
Work on a copy and keep the original untouched. Add a source column and a collected-on date to each record, so every later failure can be traced back to where it came from.
How you know it workedEvery row carries a source and a collection date, and the original export is saved apart.
If it failsSome rows have no source: label them unknown and check that group more closely than the rest.
Trim stray spaces, fix capitalisation, split full names into given and family name, and add each company's web domain. Flag any required field left empty rather than guessing its value.
How you know it workedNames, titles and domains follow the same format on every row, and empty required fields are flagged.
If it failsNames arrive in mixed order or with titles attached: split them by rule, then read a sample by eye.
Match on email address, then on person plus company domain, since the same contact often enters under different addresses. Take out anyone on your do-not-contact list and any current customer or open deal.
How you know it workedSorting by email address and by person and domain shows no repeats, and no blocked contact remains.
If it failsDuplicates survive because addresses differ in spelling: compare the name part and the domain part separately, then merge by hand.
Run syntax and domain checks on each address, then ask the receiving mail server whether the mailbox exists. Label results good, risky or bad: shared inboxes such as info@ and catch-all domains (which accept any address) go in risky, never in good.
How you know it workedEach address carries a status of good, risky or bad, and no row is left without a status.
If it failsMany results come back unknown when a server will not answer: label them risky and keep them out of the main send.
Compare each record's title and company with a current public source, such as the company's own site or team page. Automate the match on domain and name, mark mismatches as unconfirmed, and read a sample by hand.
How you know it workedEach record is marked confirmed or unconfirmed, and the sample you checked by hand matches the automated result.
If it failsMany records come back unconfirmed: group them by source and age, and work through the older groups before the rest.
Before sending, write down your stop line: the bounce level at which you pause, taken from past send reports. Send to a small slice mixing sources and ages, read bounces and replies, and continue only inside that line.
How you know it workedThe pilot's bounce level stays inside your written stop line, and replies do not point to wrong contacts.
If it failsBounces pass the line: stop the send, trace failing rows to their source tag, and repeat the address and title checks on that group.
Write each failed record back to its source with the reason it failed. Add hard bounces (permanent failures) and opt-outs to your suppression list, so the same records are not imported or sent again.
How you know it workedEach failure has a reason in the source system, and the suppression list contains every hard bounce.
If it failsThe source system accepts no notes: keep a separate failure log keyed by email address and reload it before each new import.
Tick each step once its check passes.
Keep going: a step whose check fails is redone, not skipped.
Every step ticked. Run the final checks below.
Did it work?
5 checks before you call it done. If one fails, the line says which step to redo.
No duplicate or blocked contact remains
Pass whenA fresh comparison against the do-not-contact list and the sheet itself returns no matches.
If notredo step 3 · Remove duplicates and blocked contacts
Only good addresses remain in the main send
Pass whenNo risky or bad address sits in the main send file, and the risky group is kept apart.
If notredo step 4 · Check every email address
Titles and companies are marked
Pass whenEach record is marked confirmed or unconfirmed, and unconfirmed rows are held out of the main send or sent for review.
If notredo step 5 · Confirm titles and company details
The pilot stayed inside your stop line
Pass whenBounce and reply reports of the pilot are saved next to the written stop line, and the line was not crossed.
If notredo step 6 · Send a small pilot batch
Every failure is logged and blocked
Pass whenThe failure log lists a reason for each record, and importing the same file again leaves them blocked.
If notredo step 7 · Log failures and suppress them
A check that fails sends you back to one step, never to the start.
If something breaks
4 failures people hit once the steps are done, and what to do about each.
Bounces stay high after cleaning
Do thisThe records may be fine while the sending domain has a poor reputation: pause the send, check the domain's authentication records, and rest the domain before reusing the list.
Replies say you reached the wrong person
Do thisTitles went stale between the check and the send: confirm titles again close to the send date and drop roles that no longer match your target.
Addresses passed but bounce later
Do thisMailboxes closed between the check and the send: check addresses again close to the send date and add each hard bounce to the suppression list.
The same bad records return on the next import
Do thisFailures were fixed on the sheet but not at the source: write each reason back to the source and reload the suppression list before every import.
Related questions
Any record that will bounce, reach the wrong person or waste a send: invalid or risky addresses, stale titles, closed or renamed companies, duplicates, empty required fields and contacts on your do-not-contact list.
No fixed rate fits every list. Data ages as people change roles and companies close, merge or rebrand; sectors with high staff turnover tend to age faster. Date-stamp each record and compare your own failure rate by record age.
Mailbox providers may read bounces as a sign that you send to lists you do not maintain. Mail to dead or trap addresses can damage the sending domain's reputation, so even good records may land in spam.
No outside figure fits every sender, so set your own: read the bounce reports of past sends, write a stop line before the pilot, and pause the full send whenever the pilot goes past it.
Run them in order: standardise fields, remove duplicates and blocked contacts, check email addresses, confirm titles and companies, then send a small pilot batch. Cheap, mechanical checks come before costly ones.
Automate the match on domain and name against a current public source such as the company's own site, then check by hand a random sample, to catch false matches, and the unconfirmed rows, grouped by source and record age.
This page walks through one procedure; it does not score tools.