我们为什么用Claude、Instantly和Supabase构建自己的冷邮件系统
每个公司都说他们讨厌冷邮件。我们也这样想——直到我们意识到问题不在冷邮件本身,而在于我们尝试使用的每个工具。通用模板。"Hi {firstName}"的气质。每月300美元的平台仍然需要数小时的手工工作。所以我们做了开发者会做的事:自己动手搭建了一个系统。
这不是一篇理论性的架构文章。我们已经在生产环境中运行这个系统好几个月了,发送了数千封真正能获得回复的个性化邮件。我会详细介绍我们为什么要构建它、各个部分如何组合在一起,以及我们艰难地学到的东西。
目录
- 现成工具的问题
- 我们的技术栈及选择原因
- 架构概览
- 使用Hunter寻找和增强潜在客户
- 使用Claude进行AI个性化
- Supabase作为编排层
- 使用Instantly大规模发送
- 自动化粘合层
- 结果和我们学到的东西
- 成本分析
- 常见问题

现成工具的问题
我们尝试过常见的工具。Lemlist。Apollo。Woodpecker。它们都是很好的工具,可以处理许多用例。但作为一个无头网络开发机构,我们的外联需求非常特殊,这些平台无法满足。
以下是不断出现的问题:
通用个性化字段不是真正的个性化。 在2025年,向模板中插入某人的公司名称和职位不会愚弄任何人。我们需要的邮件能够引用潜在客户的实际技术栈、他们的网站性能问题,或他们公网可见的特定架构决定。
研究步骤是瓶颈。 我们最好的外联总是涉及团队中的某个人实际查看潜在客户的网站、通过PageSpeed Insights运行、检查他们的框架,并写下一些特定的东西。这需要每条线索花费10-15分钟。按规模计算,这需要全职工作。
数据分散在太多地方。 一个电子表格中的线索、另一个平台中的电子邮件序列、第三个仪表板中的结果。我们无法建立反馈回路,因为没有任何东西相互连接。
AI集成很肤浅。 某些平台添加了"AI写作"功能,但它们基本上是生成相同乏味副本的GPT封装,每个人都在发送。无法输入自定义上下文、无法控制提示、无法构建多步骤推理链。
我们需要一个AI进行研究的系统,而不仅仅是写作。
我们的技术栈及选择原因
经过几次迭代,我们落定在以下方案:
| 组件 | 工具 | 角色 | 月成本 |
|---|---|---|---|
| 潜在客户寻找和电子邮件验证 | Hunter.io | 查找和验证电子邮件地址 | $49(Starter) |
| AI研究和文案写作 | Claude(Anthropic API) | 分析潜在客户、生成个性化邮件 | ~$30-60 |
| 数据库和编排 | Supabase | 存储潜在客户、管理状态、触发工作流 | $25(Pro) |
| 电子邮件发送和预热 | Instantly.ai | 可交付性、发送基础设施、预热 | $30(Growth) |
| 自动化粘合层 | 自定义Edge Functions + Cron | 连接所有内容 | $0(包含在Supabase中) |
我们评估了很多替代方案。以下是我们选择这些工具的简短版本:
Claude而不是GPT-4: 我们广泛测试了两者。Claude 3.5 Sonnet(以及现在2025年的Claude 4 Sonnet)持续生成听起来更自然、更不"AI化"的邮件。它在遵循复杂系统提示而不偏离方面也更好。定价相当,但Claude更长的上下文窗口意味着我们可以为每个潜在客户输入更多研究数据。
Supabase而不是Airtable或自定义Postgres设置: 我们需要一个真实的数据库,具有行级安全性,但我们不想管理基础设施。Supabase为我们提供了Postgres、Edge Functions、Cron任务和一个不错的仪表板——都在一个地方。我们在客户项目中也大量使用Supabase,所以团队已经很熟悉了。
Instantly而不是Lemlist或Smartlead: Instantly的预热网络非常好,他们的API很简洁,定价对我们的数量来说很合理。我们不需要Instantly内置的序列构建器,因为我们自己处理序列逻辑。
Hunter而不是Apollo或Snov.io: Hunter的电子邮件验证是我们测试过最准确的。他们的域搜索API快速,数据质量很高。Apollo有更多数据点,但我们发现他们的电子邮件准确度较低,这会杀死可交付性。
架构概览
该系统分五个阶段工作,每个阶段独立运行:
[潜在客户来源] → [Hunter增强] → [Supabase数据库] → [Claude研究+文案] → [Instantly发送]
↑ ↑ |
| | |
+----------- 反馈回路 -----------+-------------------------------------------+
- 摄入:我们从各种来源输入潜在客户域(手动列表、爬虫、推荐数据)
- 增强:Hunter查找联系人并验证电子邮件
- 存储:所有内容都进入Supabase,带有状态跟踪
- 研究+写作:Claude分析每个潜在客户并生成个性化副本
- 发送:批准的邮件推送到Instantly活动
- 学习:回复数据流回Supabase,通知未来的个性化
每个阶段都是解耦的。如果Hunter的API出现故障,增强队列只是积压——它不会破坏发送。如果我们想用不同的模型替换Claude,我们只需改变一个功能。

使用Hunter寻找和增强潜在客户
Hunter.io处理两个关键工作:找到公司中的合适人选并验证其电子邮件确实有效。
以下是我们增强功能的简化版本:
import { createClient } from '@supabase/supabase-js';
const HUNTER_API_KEY = Deno.env.get('HUNTER_API_KEY');
async function enrichLead(domain: string) {
// 域搜索以查找决策者
const searchRes = await fetch(
`https://api.hunter.io/v2/domain-search?domain=${domain}&department=executive,it&api_key=${HUNTER_API_KEY}`
);
const searchData = await searchRes.json();
const contacts = searchData.data.emails
.filter((e: any) => e.confidence > 70)
.slice(0, 3); // 每个域的前3名联系人
// 验证每封电子邮件
for (const contact of contacts) {
const verifyRes = await fetch(
`https://api.hunter.io/v2/email-verifier?email=${contact.value}&api_key=${HUNTER_API_KEY}`
);
const verifyData = await verifyRes.json();
if (verifyData.data.status === 'valid') {
await supabase.from('leads').insert({
domain,
email: contact.value,
first_name: contact.first_name,
last_name: contact.last_name,
position: contact.position,
confidence: contact.confidence,
status: 'enriched',
enriched_at: new Date().toISOString()
});
}
}
}
我们过滤executive和it部门,因为这些是我们的买家——CTO、工程副总裁、技术创始人。Hunter的部门过滤不完美,但它消除了很多噪音。
我们学到的一点:永远不要跳过电子邮件验证。 即使使用Hunter的置信度分数,我们仍然验证每个地址。反弹率高于3%会摧毁您发送域的声誉。我们见过域从95%收件箱位置掉到40%垃圾邮件文件夹,仅因为一批不好的数据。
我们每周运行大约500个Hunter搜索信用,这轻松适合他们的Starter计划。
使用Claude进行AI个性化
这是事情变得有趣的地方。Claude集成不仅仅是"给我写一封冷邮件"。这是一个多步骤研究和写作管道。
第1步:网站分析
在Claude写任何东西之前,我们提供有关潜在客户网站的数据。我们使用轻量级函数抓取基本信息:
async function analyzeProspectSite(domain: string) {
// 获取主页和关键页面
const homepage = await fetch(`https://${domain}`);
const html = await homepage.text();
// 从HTML中提取技术信号
const signals = {
hasNextJs: html.includes('__next') || html.includes('_next/static'),
hasReact: html.includes('react') || html.includes('__REACT'),
hasWordPress: html.includes('wp-content') || html.includes('wp-includes'),
hasShopify: html.includes('shopify') || html.includes('cdn.shopify'),
hasGatsby: html.includes('gatsby'),
usesJQuery: html.includes('jquery'),
metaGenerator: extractMeta(html, 'generator'),
pageSize: html.length,
// ... 更多信号
};
// 通过API运行PageSpeed检查
const psiData = await fetchPageSpeedInsights(domain);
return {
...signals,
performanceScore: psiData.lighthouseResult.categories.performance.score * 100,
lcp: psiData.lighthouseResult.audits['largest-contentful-paint'].numericValue,
cls: psiData.lighthouseResult.audits['cumulative-layout-shift'].numericValue,
fid: psiData.lighthouseResult.audits['max-potential-fid'].numericValue
};
}
这给Claude真实数据可以处理。不是"嘿,我注意到你的公司做X"——更像"你的主页LCP是4.2秒,你仍在运行jQuery和React,这为你的初始包增加了90KB"。
第2步:Claude研究提示
我们使用Claude的API和精心设计的系统提示。这是一个简化版本:
const researchPrompt = `You are a senior web developer analyzing a prospect's website for a headless development agency. Given the following technical data about their site, identify:
1. Their current tech stack (be specific)
2. 2-3 concrete performance or architecture issues
3. What a migration to a modern headless architecture could improve
4. A specific, non-obvious observation that shows genuine analysis
Do NOT be generic. If you can't find something specific, say so.
Do NOT mention "in today's digital landscape" or similar filler.
Be direct and technical.
Site data:
${JSON.stringify(siteAnalysis, null, 2)}
Prospect: ${lead.first_name} ${lead.last_name}, ${lead.position} at ${lead.domain}`;
const research = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1000,
messages: [{ role: 'user', content: researchPrompt }]
});
第3步:电子邮件生成
研究输出被输入到生成实际电子邮件的第二个Claude调用中。将研究与写作分开是一个关键洞察——当我们试图在一个提示中做两者时,邮件会更差。Claude为了加快写作速度会跳过研究。
const emailPrompt = `Write a cold email from a senior developer at a headless web agency.
Research notes:
${research.content[0].text}
Rules:
- 4-6 sentences max. Every sentence must earn its place.
- Lead with the most specific technical observation.
- No flattery. No "I love what you're doing."
- One clear CTA: ask if they'd want to see a performance audit.
- Sound like a developer, not a salesperson.
- Use their first name. No last name in greeting.
- Subject line: short, specific to their tech issue, lowercase.`;
结果是什么?邮件以"你的Shopify Plus商店正在服务器渲染可以静态生成的产品页面——这为每个产品视图增加了2秒以上"之类的东西开头,而不是"我注意到你印象深刻的公司,想要联系"。
Supabase作为编排层
Supabase是操作的大脑。这是我们的核心模式:
create table leads (
id uuid primary key default gen_random_uuid(),
domain text not null,
email text,
first_name text,
last_name text,
position text,
confidence int,
status text default 'new', -- new, enriched, researched, drafted, approved, sent, replied, bounced
site_analysis jsonb,
research_notes text,
email_subject text,
email_body text,
instantly_campaign_id text,
sent_at timestamptz,
opened_at timestamptz,
replied_at timestamptz,
created_at timestamptz default now(),
updated_at timestamptz default now()
);
create index idx_leads_status on leads(status);
create index idx_leads_domain on leads(domain);
status字段驱动一切。Supabase Cron任务每15分钟运行一次,处理各个阶段的潜在客户并将他们推向下一阶段:
-- Cron: 通过Claude研究处理增强的潜在客户
select cron.schedule(
'process-research',
'*/15 * * * *',
$$select net.http_post(
'https://your-project.supabase.co/functions/v1/process-research',
'{}',
'{"Authorization": "Bearer your-service-key"}'::jsonb
)$$
);
我们每次运行批处理20个潜在客户,以保持在Claude的速率限制内并保持成本可预测。
site_analysis JSONB列非常有用。我们可以跨所有潜在客户查询以查找模式——比如"显示所有运行WordPress且性能分数低于50的潜在客户"——并从这些细分中构建有针对性的活动。
使用Instantly大规模发送
Instantly处理实际的电子邮件传递。我们通过他们的API推送批准的邮件:
async function pushToInstantly(lead: Lead) {
const response = await fetch('https://api.instantly.ai/api/v1/lead/add', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
api_key: INSTANTLY_API_KEY,
campaign_id: lead.instantly_campaign_id,
skip_if_in_workspace: true,
leads: [{
email: lead.email,
first_name: lead.first_name,
last_name: lead.last_name,
company_name: lead.domain,
personalization_1: lead.email_subject,
personalization_2: lead.email_body
}]
})
});
if (response.ok) {
await supabase
.from('leads')
.update({ status: 'sent', sent_at: new Date().toISOString() })
.eq('id', lead.id);
}
}
Instantly的活动模板使用{{personalization_1}}和{{personalization_2}}变量,它们映射到我们的Claude生成的主题和正文。活动本身只是一个shell——所有智能都在我们的系统中。
在发送任何外联之前,我们通过Instantly的预热为至少2周的3个发送帐户运行。域名预热不是可选的。我们在第一个域名在一周内被标记时以艰难的方式学到了这一点。
可交付性设置
我们的发送基础设施:
- 3个域(我们品牌的变体,不是我们的主要域)
- 在所有域上配置SPF、DKIM和DMARC
- Google Workspace账户(不是Outlook——Google在我们的测试中处理冷邮件更好)
- Instantly预热连续运行,即使在活跃发送日期
- 每个账户每天最多35封邮件
- 发送间隔随机3-7分钟
自动化粘合层
Supabase Edge Functions连接一切。以下是伪代码中的流程:
每15分钟:
1. 拿起status='new'的潜在客户,运行Hunter增强 → status='enriched'
2. 拿起status='enriched'的潜在客户,运行网站分析 → status='analyzed'
3. 拿起status='analyzed'的潜在客户,运行Claude研究+电子邮件生成 → status='drafted'
4. (人工在Supabase仪表板中审查草稿邮件)
5. 拿起status='approved'的潜在客户,推送到Instantly → status='sent'
6. 从Instantly API拉取参与数据 → 更新opened_at、replied_at
第4步很重要。我们不会完全自动化发送。每封邮件在发出之前都经过人工审查。这会捕捉偶尔的幻觉(Claude曾声称一个网站是用Remix构建的,而它显然是Next.js),并让我们添加个人风格。
审查步骤花费约2-3秒每封邮件,因为Claude正确执行95%的工作。我们使用简单的Supabase仪表板视图批量批准。
结果和我们学到的东西
我们自2025年第一季度以来一直在运行这个系统。以下是实际数字:
| 指标 | 我们的系统 | 行业平均值(2025) |
|---|---|---|
| 打开率 | 62% | 24% |
| 回复率 | 8.4% | 1-3% |
| 正面回复率 | 4.1% | 0.5-1% |
| 反弹率 | 0.8% | 3-5% |
| 每条联系潜在客户的成本 | $0.18 | $0.50-2.00 |
| 每条潜在客户的时间(人工) | ~5秒(审查) | 10-15分钟 |
打开率很高,因为主题行很具体。"your shopify lcp is 4.2s"会被打开。"Quick question"不会。
回复率很高,因为邮件展示了真正的技术知识。当CTO阅读正确识别他们的技术栈和真实性能问题的邮件时,他们更可能参与——即使他们知道这是外联。
什么不起作用
完全自动化发送(无人工审查): 我们尝试了两周。Claude幻觉了约5%的技术栈细节。这对于LLM来说是低误差率,但发送一封说"你的React应用"给运行Vue的人的邮件比发送通用邮件更糟。信任伤害是真实的。
长邮件: 我们最初的Claude提示生成8-10句邮件。回复率是我们现在看到4-6句邮件的一半。更短总是更好。
每个账户每天发送超过40封邮件: 可交付性直线下降。30-35是2025年的最佳点。
使用Claude根据打开生成后续邮件: 我们尝试生成由打开触发的后续邮件。后续邮件感觉很咄咄逼人,转换不值得成本。我们现在发送一个简单的、非AI的后续邮件三天后。
成本分析
这是我们每月处理大约2,000条潜在客户的成本:
| 服务 | 月成本 | 说明 |
|---|---|---|
| Hunter.io(Starter) | $49 | 500个搜索+验证 |
| Anthropic API(Claude) | $45 | ~2,000个研究+电子邮件生成 |
| Supabase(Pro) | $25 | 数据库、Edge Functions、Cron |
| Instantly(Growth) | $30 | 发送、预热、分析 |
| Google Workspace(3个账户) | $21 | 发送基础设施 |
| 域(3个) | $10 | 年度成本摊销 |
| 总计 | ~$180 | 每条潜在客户$0.09 |
与Apollo的$79/月计划(受限增强、基本序列)或Lemlist的$69/月每座相比。我们花费更少,获得了显著更好的结果,因为个性化是真实的,而不是基于模板的。
为了了解背景,这个系统直接产生了转化为Next.js开发和Astro开发项目的潜在客户,价值月成本的50-100倍。ROI是荒唐的。
常见问题
构建这个系统需要多长时间? 第一个有效版本花了大约两周的兼职工作——总共可能40小时。我们从那时起持续迭代它,主要是调整Claude提示和添加边界情况处理。如果你对Supabase Edge Functions和REST API感到满意,你可以在一个周末内启动一个基本版本。
这不是只是多了几个步骤的垃圾邮件吗? 公平的问题。区别在于每封邮件都包含有关收件人网站的真实技术观察。我们不是向10,000人发送"我们一起通话吧"。我们向有我们解决的问题的有针对性的人列表发送特定的、有用的见解。我们的取消订阅率低于0.5%,这表明收件人也不将其视为垃圾邮件。
为什么选Claude而不是GPT-4或Gemini? 我们测试了所有三个。Claude更可靠地遵循我们的系统提示——特别是约束条件,如"不要通用"和"不要使用填充短语"。GPT-4即使有明确指示也会漂向销售类语言。Gemini很快,但输出质量不一致。这可能随着模型发展而改变,我们的系统设计为轻松交换模型。
你如何处理GDPR和CAN-SPAM合规性? 我们的所有外联目标都是商业电子邮件(不是个人),包括我们的实际地址,并在每封邮件中都有明确的选择退出。对于GDPR,我们根据B2B外联的合法利益处理数据,维护处理活动的记录,并通过自动化webhook立即尊重删除请求。我们也自动清除数据库中早于90天的潜在客户。为了您的具体情况,请咨询律师——这不是法律建议。
当潜在客户回复时会发生什么? 回复从Instantly的API流回Supabase。我们为每条回复获得Slack通知,人工立即接管对话。我们从不使用AI处理回复。一旦有人参与,他们就值得一个真实的人。感兴趣的潜在客户被指向我们的联系页面或直接到呼叫预订链接。
这种方法能对非技术服务工作吗? 网站分析部分特定于网络开发,但架构模式——增强潜在客户、使用AI进行研究和个性化、通过专用工具发送——对任何B2B外联都有效。你只需要不同的研究输入。设计机构可能会分析视觉设计和UX模式。营销机构可能会拉取SEO指标。关键是向Claude提供真实数据,而不是要求它编造东西。
维护这个系统最难的部分是什么? 提示维护。随着Claude模型的更新,有效的提示有时需要调整。我们还花费时间监控电子邮件可交付性——检查Google Postmaster工具、观察垃圾邮件率峰值、轮换发送账户。总共每周大约2-3小时的维护。
你会把这个作为产品销售吗? 我们考虑过,但诚实地说竞争优势太有价值了。如果每个机构都运行这个确切的系统,有效性会下降,因为收件人会开始看到AI研究的邮件无处不在。现在,我们将其保留为内部工具。如果你想帮助为你的业务构建类似的系统,联系我们——我们帮助了一些客户作为无头CMS开发工作的一部分设置类似的系统。