我用200行代码构建了自己的Mailchimp替代方案
I’m happy to translate the article for you, but I need the actual text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll keep the source link, formatting, markdown, and any code blocks exactly as they are while translating the rest into Simplified Chinese.
架构概览
系统由三部分组成:
- 配置文件 – 定义邮件序列。
- Cron 任务 – 查找已准备好接收下一封邮件的订阅者。
- 队列工作者 – 发送邮件。
配置文件
{
"workflowSteps": [
{
"step": 1,
"hoursAfterSignup": 24,
"template": {
"subject": "Welcome! 🎉",
"heading": "Hi {{name}}!",
"body": "Thanks for signing up..."
}
},
{ "step": 2, "hoursAfterSignup": 96, ... },
{ "step": 3, "hoursAfterSignup": 264, ... }
]
}
Cron 任务 – 查找已准备好的订阅者
app.job('*/15 * * * *', async (req, res) => {
const conn = await Datastore.open();
for (const stepConfig of workflowSteps) {
const cutoffTime = new Date(Date.now() - stepConfig.hoursAfterSignup * 60 * 60 * 1000);
// Stream subscribers (constant memory usage)
await conn.getMany('subscribers', {
subscribed: true,
createdAt: { $lte: cutoffTime }
}).forEach(async (subscriber) => {
if (!subscriber.emailsSent?.includes(stepConfig.step)) {
// Atomically mark as sent
const updated = await conn.updateOne(
'subscribers',
{ _id: subscriber._id, emailsSent: { $nin: [stepConfig.step] } },
{ $push: { emailsSent: stepConfig.step } }
);
if (updated) {
await conn.enqueue('send-email', { subscriberId: subscriber._id, step: stepConfig.step });
}
}
});
}
});
队列工作者 – 发送邮件
app.worker('send-email', async (req, res) => {
const { subscriberId, step } = req.body.payload;
const template = await getTemplate(step);
await sendEmail(subscriber.email, template.subject, generateHTML(template));
res.end();
});
内存高效处理
而不是一次性将所有订阅者加载到内存中:
// ❌ Memory issues with 50k+ subscribers
const subscribers = await conn.getMany('subscribers').toArray();
我们改为流式处理:
// ✅ Constant memory usage
await conn.getMany('subscribers').forEach(async (sub) => {
await processSubscriber(sub);
});
这样即使是 10 万+ 订阅者也能轻松扩展,毫无压力。
防止重复邮件
原子更新确保在给定的订阅者/步骤上只有一个 cron 实例能够排队发送:
const updated = await conn.updateOne(
'subscribers',
{ _id: subscriber._id, emailsSent: { $nin: [step] } },
{ $push: { emailsSent: step } }
);
if (updated) {
await conn.enqueue('send-email', { subscriberId, step });
}
如果发送失败,工作进程会回滚标记,以便下次 cron 运行时重新尝试:
catch (error) {
await conn.updateOne(
'subscribers',
{ _id: subscriberId },
{ $pull: { emailsSent: step } }
);
// Next cron run will retry
}
部署与配置
npm install -g codehooks
coho create my-drip --template drip-email-workflow
coho deploy
设置你的邮件提供商(示例:SendGrid):
coho set-env EMAIL_PROVIDER "sendgrid"
coho set-env SENDGRID_API_KEY "SG.your-key"
coho set-env FROM_EMAIL "hello@yourdomain.com"
你的滴灌活动现在已经运行。
Codehooks 为您提供的功能
- 无服务器函数
- NoSQL 数据库(兼容 MongoDB)
- 定时任务调度
- 队列工作者
- 环境密钥
一站式平台——无需将 AWS Lambda、SQS、CloudWatch、EventBridge 等拼凑在一起。
Source: …
成本比较
| 订阅者数量 | 每月费用(Codehooks + SendGrid) | 年费用 | Mailchimp(Standard) |
|---|---|---|---|
| 5 000 | $19 + $19.95 = $38.95 | $467 | $1 020 |
| 50 000 | $19 + $89.95 = $108.95 | $1 307 | $3 600‑4 800 |
随着列表规模的增长,节省的费用也会增加。
模板功能
- 完整的工作系统
- 用于订阅者管理的 REST API
- 响应式 HTML 电子邮件模板
- 带干运行模式的电子邮件审计日志
- 集成:SendGrid、Mailgun、Postmark
- 示例配置(入职、课程、培育)
何时不使用此
- 您需要亚分钟级的交付 SLA(使用专用事务服务)
- 高级细分 UI
- 无代码工作流构建器
- 非技术团队成员管理活动
此方案面向希望拥有控制权和所有权的开发者。
快速开始
coho create my-campaign --template drip-email-workflow
cd my-campaign
coho deploy
我为自己的 SaaS 构建了它,认为其他人可能会觉得有用。除了是一个满意的用户外,没有任何关联。
有问题吗?请在下方留言!