邮件与通知服务
问题
如何在 Node.js 中实现邮件发送和多渠道通知?
答案
通知渠道
| 渠道 | 适用场景 | 方案 |
|---|---|---|
| 邮件 | 验证码、账单、营销 | Nodemailer + SMTP / SendGrid / AWS SES |
| 短信 | 验证码、告警 | Twilio / 阿里云短信 |
| App 推送 | 消息提醒 | Firebase FCM / APNs |
| WebSocket | 站内实时通知 | Socket.IO / ws |
| Webhook | 系统间通知 | HTTP POST 回调 |
邮件发送
email-service.ts
import nodemailer from 'nodemailer';
const transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 587,
secure: false,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
interface SendEmailOptions {
to: string;
subject: string;
html: string;
}
async function sendEmail({ to, subject, html }: SendEmailOptions) {
await transporter.sendMail({
from: '"My App" <noreply@example.com>',
to,
subject,
html,
});
}
// 使用模板
function getWelcomeEmailHtml(name: string): string {
return `
<h1>欢迎加入, ${name}!</h1>
<p>感谢你的注册。</p>
<a href="https://example.com/verify?token=xxx">验证邮箱</a>
`;
}
// 异步发送(不阻塞主流程)
app.post('/api/register', async (req, res) => {
const user = await createUser(req.body);
// 丢进队列异步发送
await emailQueue.add('welcome', { userId: user.id, email: user.email });
res.json(user);
});
通知服务架构
notification-service.ts
// 统一的通知服务,支持多渠道
interface NotificationPayload {
userId: string;
type: 'email' | 'sms' | 'push' | 'in-app';
template: string;
data: Record<string, unknown>;
}
class NotificationService {
async send(payload: NotificationPayload) {
switch (payload.type) {
case 'email':
return this.sendEmail(payload);
case 'sms':
return this.sendSMS(payload);
case 'push':
return this.sendPush(payload);
case 'in-app':
return this.sendInApp(payload);
}
}
// 批量发送(如营销邮件)
async sendBatch(payloads: NotificationPayload[]) {
// 分批入队,避免一次性发送过多
for (const batch of chunk(payloads, 100)) {
await notificationQueue.addBulk(
batch.map(p => ({ name: 'send', data: p }))
);
}
}
}
常见面试问题
Q1: 邮件发送为什么要异步?
答案:
SMTP 网络请求可能需要数秒,同步发送会阻塞用户请求。应该将邮件任务丢进消息队列异步处理,接口立即返回。
Q2: 如何避免邮件进垃圾箱?
答案:
- 配置 SPF、DKIM、DMARC 记录
- 使用专业邮件服务商(SendGrid、AWS SES)
- 维护发件人信誉,避免频繁发送
- 提供退订链接
Q3: 验证码的安全设计?
答案:
- 限制发送频率(1 分钟内不重复发送)
- 设置有效期(5-10 分钟)
- 限制验证次数(错误 5 次后失效)
- 验证后立即失效
相关链接
- 消息队列 - 异步处理
- Node.js 安全 - 邮件安全