OXYGENOxygen/ Docs
Providers

Email verification

Check whether addresses you already have are safe to send to, including catch-all domains.

Verification answers one question about an address you already have: is it safe to send to? It is separate from finding an address — finding produces a candidate, verifying grades one.

Oxygen runs one verifier chain for this, and every surface resolves to it: the verify_email table column, oxygen verify email, the oxygen_verify_email MCP tool, and POST /api/cli/verify/run. The same address cannot get a different verdict, or a different price, depending on where you asked.

Verdicts

VerdictMeaningSend to it?
validA verifier confirmed the mailbox exists.Yes
invalidThe mailbox does not exist, or the address is disposable, a spam trap, or do-not-mail.No
catch_allThe domain accepts mail for every address, so no verifier can confirm this specific mailbox.Judgement call — see below
unknownNo verifier could answer. This is an absent answer, not a bad address.Don't drop these; re-run

The two that get misread are catch_all and unknown. Filtering "everything that isn't valid" throws away good contacts: unknown usually means a verifier had a bad moment, and catch_all is extremely common on well-run corporate domains.

Catch-all domains

A catch-all (or "accept-all") domain answers yes to every address, so probing anything@company.com succeeds whether or not the mailbox is real. A generalist verifier can only flag this.

When that happens, Oxygen automatically escalates the address to a catch-all specialist that resolves a large share of them, including addresses behind secure email gateways. You do not configure this; it is the default chain.

Two rules keep the cost sane:

  • Escalation fires only on a catch_all verdict — never speculatively, and never on unknown (an inconclusive cheap pass is not evidence of a catch-all domain).
  • If the specialist cannot resolve it either, the address keeps catch_all. Oxygen never upgrades a catch-all to verified because the escalation was unavailable.

For addresses that stay catch_all, the honest play is to send a small watched batch first, or confirm the person independently — verification alone cannot clear them.

Cost, and sizing the ceiling

Cost is not flat per address. Every address pays the first pass; only catch-all addresses additionally pay the escalation, which is several times more. A ceiling sized as "N addresses × first pass" runs out as soon as a few turn out to be catch-all.

Run the free preview first. It returns real numbers:

oxygen verify email a@acme.com b@acme.com --json
{
  "estimate": {
    "first_pass_credits_per_email": 2.245,
    "catch_all_escalation_credits_per_email": 17,
    "min_credits": 4.49,
    "max_credits": 38.49,
    "recommended_max_credits": 38.49
  }
}

Pass recommended_max_credits (the all-catch-all worst case) as --max-credits. It is a ceiling, not a charge — you are billed for what actually runs, so over-reserving costs nothing.

oxygen verify email a@acme.com b@acme.com --mode live --max-credits 38.49 --json

If the ceiling runs out mid-batch, verification does not fail. The remaining catch-all addresses come back unescalated with escalation_skipped: budget_exhausted — a budget signal, not a provider outage. Re-run those with a higher ceiling.

escalation_skippedCauseFix
budget_exhaustedRemaining ceiling could not cover an escalation, so it was never dialled.Re-run with recommended_max_credits.
escalation_unavailableThe call was attempted and failed (no credential, or a provider error).Check the connection, then retry.
not_configuredEscalation was explicitly disabled.Nothing, if intended.

Verifying a whole table

Add a verify_email enrichment column pointed at the column holding your addresses. It runs the same chain, including the automatic catch-all escalation, and writes the verdict into the cell so you can filter and segment on it.

Do not hand-build a single-provider action column for this — that skips the escalation, so every catch-all row comes back unresolved.

  • Waterfalls — finding a value you don't have
  • Runs — per-cell provenance and attempt traces

On this page