Email (work addresses & domains)
Resolve a company NAME to the domain it actually sends mail from — the first step for any lead that arrives as a person plus an employer with no website.
Resolve a company NAME to the domain it actually sends mail from — the first step for any lead that arrives as a person plus an employer with no website. Returns the one domain worth acting on, and deliberately returns null for it when the closest match is not the company you asked for. Direct API, no browser.
Also known as: email domain, work email, company domain, email lookup, mail domain
Call it
bowmark.email.findDomain(company: string, limit?: number, options?: CallOptions): Promise<DomainMatch>Functions
| Function | What it does |
|---|---|
findDomain | Turns a company NAME into the domain it sends mail from — findDomain("Basecamp LLC") resolves to basecamp.com. |
Types
// One candidate email domain for a company. Nulls mean "the source does not
// report it", never "we failed to read it".
type DomainCandidate = {
source: string // which source this came from
company: string // the company as the SOURCE records it — often not the string you asked for
domain: string // the domain it sends mail from, e.g. "basecamp.com". Never empty
emailCount: number // addresses the source holds there. NOT a confidence score; 0 is real
logo: string | null
}
type DomainMatch = {
query: string // the company name as asked, verbatim
bestMatch: DomainCandidate | null // the one domain worth acting on; null when the
// source's best candidate is NOT the company you asked for
candidates: DomainCandidate[] // the source's OWN ranking order — best name match first
warnings: string[] // always present; empty when nothing was dropped. A
// source named here answered NOTHING — and if
// EVERY source did, this THROWS rather than
// returning a confident "no such domain"
}
type CallOptions = {
timeoutMs?: number // per-provider budget in ms, default 30000, clamped to 1000-55000.
// A provider slower than this is DROPPED from the results and
// NAMED in warnings — never silently absent
}Examples
// A lead arrived as a person and an employer, with no website. Get the domain
// the company actually sends mail from before spending anything keyed on it.
const match = await bowmark.email.findDomain("Basecamp LLC");
for (const w of match.warnings) log(w);
if (!match.bestMatch) {
// NOT "no such company" — it means the closest thing the sources hold is not
// the company that was asked for. The candidates are still worth showing.
return { resolved: null, closest: match.candidates.slice(0, 3) };
}
return {
domain: match.bestMatch.domain, // "basecamp.com"
recordedAs: match.bestMatch.company, // "Basecamp" — the source's own spelling
addressesOnFile: match.bestMatch.emailCount,
};// Resolve a whole lead list, and keep the unresolved ones SEPARATE rather than
// silently taking each list's first guess — that is the mistake bestMatch exists
// to make impossible.
const companies = ["Stripe", "Kettlewell Colours", "Tamarack Fabricating"];
const resolved = [], unresolved = [];
for (const name of companies) {
const match = await bowmark.email.findDomain(name, 10);
if (match.bestMatch) resolved.push({ name, domain: match.bestMatch.domain });
else unresolved.push({ name, closest: match.candidates.map(c => c.domain).slice(0, 3) });
}
log(`${resolved.length} of ${companies.length} resolved`);
return { resolved, unresolved };Providers behind it
| Provider | |
|---|---|
hunter | Hunter |