ravn
Claude skill

Verify an email list before a campaign

Check every address on a list with Ravn, drop the ones that would bounce or hurt your sender reputation, and hand back a send-ready file plus a short report of what was removed and why.

Download SKILL.md Start free

Install

One command.

Installs into ~/.claude/skills for Claude Code. In Claude, upload the downloaded file under Settings → Capabilities → Skills.

npx ravn skill install verify-email-list

When to use

  • The user has a CSV, a pasted list or a CRM export and is about to send a campaign.
  • The list came from a purchase, an event, an old database or a form with no confirmation step.
  • The user asks "is this list safe to send?" or "clean these emails".

Do not use this to find new emails. For that, see the find-work-email or enrich-csv skills.

Before you start

  1. Check the connection. With MCP, call get_account with {}. With the CLI, run npx ravn whoami. Both are free.
  2. Note the plan and fair_use.lookups_remaining_5h. Each unique address costs 1 lookup.
  3. Count unique addresses in the list. If that number is bigger than the lookups left, tell the user. Ravn ($24/month) includes 10,000 lookups a month, then $1 per 1,000 up to the spending cap; the Free plan has 1,000 lookups in total.

Steps

  1. Find the email column. If there is more than one (for example Email and Work Email), ask which one to verify.
  2. Small lists (up to 1,000 addresses) over MCP: call validate_emails once.
{ "emails": ["jane@acme.com", "info@acme.com", "bob@gmial.com"] }
  1. CSV files with the CLI: dry run, then a sample, then the full run.
npx ravn enrich list.csv --tool validate_email --column Email --dry-run
npx ravn enrich list.csv --tool validate_email --column Email --limit 10 --out sample.csv
npx ravn enrich list.csv --tool validate_email --column Email --out verified.csv

The dry run prints the row count, the lookups it will use and your remaining lookups. Show the sample to the user before the full run. The run saves progress every 25 rows; rerun the same command to resume after an interruption.

  1. Sort each row into a bucket using the verdict (status over MCP, rw_verdict in the CSV): - valid: keep. - invalid: remove. The reason says why, for example mailbox_not_found, no_mx, domain_not_found or bad_syntax. - risky: remove from the send. Usually a catch-all domain (catch_all: true) or a disposable domain. - unknown: hold back. The mailbox could not be checked; never treat it as valid.
  2. Also flag role_account: true (info@, sales@) and free_provider: true if the campaign is B2B. Ask the user whether to keep them.
  3. Write two files: send-ready.csv (valid only, minus anything the user opted to drop) and removed.csv (everything else, with the reason).

Output

The verified CSV keeps every original column and adds:

  • rw_status: ok, not_found, error or dropped (dropped means the run stopped on the rate limit before reaching that row).
  • rw_verdict: valid, invalid, risky or unknown.
  • rw_risk_score (A to F), rw_reason, rw_domain, rw_provider, rw_disposable, rw_free_provider, rw_role_account, rw_catch_all, rw_mailbox_checked.

Finish with a summary: total rows, unique addresses, counts per verdict, and the top three removal reasons.

Rules

  • Never send to anyone who opted out or asked not to be contacted. Remove them before verifying; Ravn's own opt-out list is at /privacy#optout.
  • Drop invalid and risky addresses before any send. Do not quietly keep unknown rows.
  • No FCRA uses: never verify lists to decide credit, employment, insurance or housing.
  • If the list is larger than the lookups left this window, ask before starting a run that will pause and wait.
  • On exit code 4 or a 429 fair_use_exhausted, the window is full; the run waits for the reset unless --no-wait is set. Rows not reached show rw_status = dropped; rerun later to finish.

Example prompt

Here's our webinar sign-up list (signups.csv). We're emailing everyone tomorrow. Clean it so we don't bounce, and tell me what you removed.