Fewer bounces start before the send.
Most hard bounces come from addresses that were already dead when you sent. Verify the list right before each send, drop invalid and D or F grades, hold catch-all addresses to a smaller test batch, and re-verify any list you have not checked in months.
Five rules that cut bounces
- / 01
Verify at the door
Check addresses when they enter your system, at sign-up or import, with validate_email. Bad syntax, no mail server and disposable domains never make it onto the list.
- / 02
Verify again before you send
An address that was fine six months ago may be gone. Run the list through the CLI right before a campaign, not just once.
- / 03
Drop invalid, D and F
Remove
invalidresults and any grade D or F. Reasons such asmailbox_not_found,no_mxanddomain_not_foundare hard bounces waiting to happen. - / 04
Treat catch-all with care
A catch-all domain accepts any name at the door, so the mailbox cannot be proven. These come back
riskywith the reasoncatch_all_domain. Send to them in a separate, smaller batch and watch what bounces. - / 05
Feed bounces back
When your sending tool reports a hard bounce, suppress that address for good. Do not re-verify it and send again.
Pre-send check
# Verify the campaign list right before sending
npx ravn enrich campaign.csv --tool validate_email --column Email --out campaign-checked.csv
# At sign-up or import: one address, one call
curl https://api.askravn.com/v1/tools/validate_email \
-H "Authorization: Bearer $RAVN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "new.signup@example.com"}'
# Exit codes for scripts: 0 ok, 1 error, 2 usage, 3 auth, 4 rate limited, 5 provider key
# In Claude
Verify campaign.csv with Ravn. Split it into: main send (valid, grade A or B),
catch-all test batch (risky with reason catch_all_domain), and suppress
(invalid, grade D or F, disposable). Give me counts for each.Verdict to action
| Result | Typical reason | Action |
|---|---|---|
| valid, A or B | mailbox_exists | Send |
| valid, C | mailbox_exists, with flags such as role_account | Send if the source is good; watch engagement |
| risky | catch_all_domain | Small test batch, separate from the main send |
| risky | disposable_domain | Suppress |
| unknown | mailbox not checked | Hold back or test in a small batch |
| invalid, or D / F | mailbox_not_found, no_mx, domain_not_found, bad_syntax | Suppress |
We never call an address valid if the mailbox was not checked. Field meanings are in the validate_email docs.
Re-verifying is lookups only
Every check is one lookup from your plan, and verification is our own check, so re-verifying before each send needs no provider key and does not add a per-record bill.
Worked example: a 12,000-address newsletter list, re-checked before a monthly send. On Ravn ($24/mo, 10,000 lookups included, then $1 per 1,000) that is the 10,000 included plus 2,000 at $1 per 1,000, so $2 on top of the plan. The free plan's 1,000 lifetime lookups is enough to test the process on a sample.
See the email verification API, pricing, and the related playbook on verifying a list before sending.
Before you reach out. Contact people only where you have a lawful basis, honour every opt-out, and never use this data for credit, employment, insurance or housing decisions (FCRA uses are forbidden by our terms). People who opt out at our opt-out page are never returned again. The full rules are on the compliance page.
Will verification get my bounce rate to zero?
No service can promise that. Catch-all domains cannot be proven, some servers refuse to answer, and mailboxes close between the check and the send. Verifying close to the send removes the addresses that are already known to be dead.
How often should I re-verify a list?
Before any large send, and on a regular schedule such as quarterly for lists you mail often. Business addresses go stale as people change jobs.
Is a role address like sales@ a bounce risk?
Not necessarily. Role accounts often exist and accept mail, and we flag them with role_account so you can choose. They tend to suit service messages better than personal outreach.
Can I check addresses in my signup form in real time?
Yes, call validate_email from your backend when the form is submitted. Keep the key server-side, and if you get a 429, accept the sign-up and check it later rather than turning the person away.
More in use cases
Every page uses the same account, plan and tools. See pricing →