Skip to content

Commit 3f76733

Browse files
fix(enrichment): address PR review on mononyms + Icypeas verify email map
- work-email LeadMagic: pass full_name + domain so single-token (mononym) names are no longer skipped - work-email Icypeas: firstname/lastname are optional on the API, so run a mononym with firstname alone instead of self-skipping - icypeas_verify_email mapItem reads item.email (verify payload shape) with a fallback to the nested results.emails[0].email Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent b9aae9d commit 3f76733

3 files changed

Lines changed: 29 additions & 15 deletions

File tree

apps/sim/enrichments/work-email/work-email.test.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,15 @@ describe('work-email enrichment cascade', () => {
102102

103103
describe('leadmagic', () => {
104104
const p = provider('leadmagic')
105-
it('splits the name and requires a domain', () => {
105+
it('passes full_name + domain and keeps mononym rows', () => {
106106
expect(p.toolId).toBe('leadmagic_find_email')
107-
expect(p.buildParams(nameDomain)).toEqual({
108-
first_name: 'John',
109-
last_name: 'Doe',
107+
expect(p.buildParams(nameDomain)).toEqual({ full_name: 'John Doe', domain: 'acme.com' })
108+
expect(p.buildParams({ fullName: 'John Doe' })).toBeNull()
109+
// single-token name still runs (no longer skipped)
110+
expect(p.buildParams({ fullName: 'Cher', companyDomain: 'acme.com' })).toEqual({
111+
full_name: 'Cher',
110112
domain: 'acme.com',
111113
})
112-
expect(p.buildParams({ fullName: 'John Doe' })).toBeNull()
113-
expect(p.buildParams({ fullName: 'Cher', companyDomain: 'acme.com' })).toBeNull()
114114
expect(p.mapOutput({ email: 'j@acme.com' })).toEqual({ email: 'j@acme.com' })
115115
})
116116
})
@@ -132,13 +132,18 @@ describe('work-email enrichment cascade', () => {
132132

133133
describe('icypeas', () => {
134134
const p = provider('icypeas')
135-
it('splits the name and requires a domain/company', () => {
135+
it('splits the name when possible and keeps mononym rows', () => {
136136
expect(p.toolId).toBe('icypeas_find_email')
137137
expect(p.buildParams(nameDomain)).toEqual({
138138
firstname: 'John',
139139
lastname: 'Doe',
140140
domainOrCompany: 'acme.com',
141141
})
142+
// single-token name runs with firstname alone (lastname is optional)
143+
expect(p.buildParams({ fullName: 'Cher', companyDomain: 'acme.com' })).toEqual({
144+
firstname: 'Cher',
145+
domainOrCompany: 'acme.com',
146+
})
142147
expect(p.buildParams({ fullName: 'John Doe' })).toBeNull()
143148
expect(p.mapOutput({ email: 'j@acme.com' })).toEqual({ email: 'j@acme.com' })
144149
})

apps/sim/enrichments/work-email/work-email.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,12 @@ export const workEmailEnrichment: EnrichmentConfig = {
154154
label: 'LeadMagic',
155155
toolId: 'leadmagic_find_email',
156156
buildParams: (inputs) => {
157-
const name = splitName(inputs.fullName)
157+
// LeadMagic accepts full_name + domain, so pass the whole name and let it
158+
// split — this keeps single-token (mononym) rows in play.
159+
const fullName = str(inputs.fullName)
158160
const domain = normalizeDomain(inputs.companyDomain)
159-
if (!name || !domain) return null
160-
return { first_name: name.firstName, last_name: name.lastName, domain }
161+
if (!fullName || !domain) return null
162+
return { full_name: fullName, domain }
161163
},
162164
mapOutput: (output) => {
163165
const email = str(output.email)
@@ -189,10 +191,15 @@ export const workEmailEnrichment: EnrichmentConfig = {
189191
label: 'Icypeas',
190192
toolId: 'icypeas_find_email',
191193
buildParams: (inputs) => {
192-
const name = splitName(inputs.fullName)
194+
// Icypeas only requires domainOrCompany; firstname/lastname are optional,
195+
// so a mononym still runs with firstname alone rather than self-skipping.
196+
const fullName = str(inputs.fullName)
193197
const domainOrCompany = normalizeDomain(inputs.companyDomain)
194-
if (!name || !domainOrCompany) return null
195-
return { firstname: name.firstName, lastname: name.lastName, domainOrCompany }
198+
if (!fullName || !domainOrCompany) return null
199+
const name = splitName(inputs.fullName)
200+
return name
201+
? { firstname: name.firstName, lastname: name.lastName, domainOrCompany }
202+
: { firstname: fullName, domainOrCompany }
196203
},
197204
mapOutput: (output) => {
198205
const email = str(output.email)

apps/sim/tools/icypeas/verify_email.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ const MAX_POLL_TIME_MS = 120000
3333
/** Map a raw Icypeas item object to the verify-email output shape. */
3434
function mapItem(item: Record<string, unknown>): IcypeasVerifyEmailOutput {
3535
const status = (item.status as string | undefined) ?? null
36-
// Results are nested under item.results; emails are in item.results.emails[0].email
36+
// Verify payloads put the address on item.email; fall back to the nested
37+
// results.emails[0].email shape that some responses use.
3738
const results = (item.results as Record<string, unknown> | undefined) ?? {}
3839
const emails = Array.isArray(results.emails) ? (results.emails as Record<string, unknown>[]) : []
39-
const email = (emails[0]?.email as string | undefined) ?? null
40+
const email =
41+
(item.email as string | undefined) ?? (emails[0]?.email as string | undefined) ?? null
4042
const valid = status !== null ? VALID_STATUSES.has(status) : null
4143
return {
4244
searchId: (item._id as string | undefined) ?? null,

0 commit comments

Comments
 (0)