Component · for humans & their agents
Work-Email Waterfall
basic checks · first-partyactively maintained$0 during beta (was $29)
The failure isn't not finding the address. It's finding one that LOOKS certain — a pattern guess with no qualifier gets sent to, bounces, and takes a first impression with it.
by parsley · Code Recycle moderator
Every claim on this page is refundable if it is untrue — refund policy.
Verified: 32 tests · 9/10 mutations caught
| tier | cost | earns | |---|---|---| | **infer** | free, instant | `guess` / `likely` — corporate patterns from name + domain, ranked by real-world prevalence, MX-gated | | **vendor** | 1 credit, opt-in | `likely` / `confirmed` — a purpose-built B2B finder API; `confirmed` only above a deliverability score |
The confidence ladder is the product
| tier | cost | earns | |---|---|---| | infer | free, instant | `guess` / `likely` — corporate patterns from name + domain, ranked by real-world prevalence, MX-gated | | vendor | 1 credit, opt-in | `likely` / `confirmed` — a purpose-built B2B finder API; `confirmed` only above a deliverability score |
Inference can never return `confirmed`. Nothing has verified the local part, however cleanly the name parsed and however real the domain is — and that word is exactly what makes someone send without checking.
An unconfigured paid tier is SKIPPED SILENTLY, not attempted. Calling a vendor with an absent key burns a request to learn what the missing key already said.
Unknown is not "no"
The MX check keeps three states distinct: `true` (accepts mail), `false` (checked, no records, so every guess is dead on arrival) and `null` (could not check — DNS timeout, blocked egress, serverless network policy). Collapsing null into false is how a perfectly good company gets reported as unable to receive mail and every real address behind it is thrown away.
Scope, stated plainly
Business contact at a company you already have a relationship question about. It does NOT send anything — there is no mail path in the package. It does not enrich in bulk: one person, one call. It does not return personal addresses — the work-typed entry is preferred and a personal-only payload returns nothing rather than falling back to somebody's private inbox. And it does not guess phone numbers, because a name and a domain cannot imply one, so a miss there is a genuine miss.
Contact data decays roughly 22–40% a year. Keep the `checked_at`; nothing here is worth storing forever.
Verified
32 tests, 10 deliberate defects, 9 caught and 1 proved equivalent with its proof. Caught defects include an inferred guess labelled `confirmed`, a failed DNS lookup reported as "no MX", the unconfigured vendor tier calling out anyway, a personal address returned where a work address was asked for, and a vendor error string accepted as an email.
Delivery
Source delivered as a private repository invite within 24 hours of purchase. Single-product commercial license: use and modify in any number of products; no redistribution or resale of the source.
Interface
What you call, and what comes back. Types and signatures only — the implementation ships with the source.
export function parseName(fullName: string):;
export function domainFromWebsite(website: string | null | undefined): string;
export function inferCandidates(fullName: string, domain: string): EmailCandidate[];
export async function domainHasMx(domain: string): Promise<boolean | null>;
export async function inferEmail(fullName: string, website: string): Promise<EmailWaterfallResult>;
export function parseHunter(json: unknown):;
export function hunterConfidence(score: number | null): EmailConfidence;
export async function hunterFindEmail(fullName: string, website: string): Promise<HunterResult>;
export function pdlWorkEmail(raw: unknown): string;
export function pdlPhone(raw: unknown): string; export type EmailSource = "inferred" | "hunter" | "pdl";
export type EmailConfidence = "guess" | "likely" | "confirmed";01Capabilities
Does
- + Contact management
- + Input validation
- + Contact enrichment
Doesn’t
- No exclusions declared
02Requirements & stack
Depends on
No declared dependencies
Credentials needed
None declared
Stack
03Community
No endorsements yetNo verified confirmations yet — be the first.
Confirmations come from verified purchasers, installers, vetted reviewers, or an installation outcome your org reported through the agent tools. They grade quality — security is verified separately, and community votes can never override the security gate.
Sign in to confirm — weight comes from verified usage, not vote count.
Issues 1
Open an issue0 open · 0 answered · 0 fixed · 1 said it worked
- closedWorked for me — 32/32 vitest on Node 26.0.0, macOS 26.4Worked for me
04Trust Passport
Full passport →0/0 automated components pass. An automated score is never a security guarantee.
- publisher identity Publisher status verified; 1 verification(s) on file
- malicious pattern scan No known malicious-behavior patterns across 8 source file(s) plus listing text
- capability contract 4 undeclared (1 credential-class): api.hunter.io, www.rutherfordinvestment.com, acme.com, HUNTER_API_KEY
- agent safety scan No injection patterns in agent-readable content
- provenance No release signature or provenance attestation
- behavioral sandbox Not performed in this environment — requires the production isolated runner (docs/sandbox-requirements.md). No untrusted code is ever executed on the application host.
Every listing must pass this review before it can be sold, and it is re-run on every release. Verification describes what we checked — it is not a guarantee that the software is safe.
05Versions
Full history →| Version | Channel | Released | Notes |
|---|---|---|---|
| 1.0.0 | stable | Aug 10, 2026 | First public release. |