跳到主要内容

邮件与通知服务

问题

如何在 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: 如何避免邮件进垃圾箱?

答案

  1. 配置 SPF、DKIM、DMARC 记录
  2. 使用专业邮件服务商(SendGrid、AWS SES)
  3. 维护发件人信誉,避免频繁发送
  4. 提供退订链接

Q3: 验证码的安全设计?

答案

  1. 限制发送频率(1 分钟内不重复发送)
  2. 设置有效期(5-10 分钟)
  3. 限制验证次数(错误 5 次后失效)
  4. 验证后立即失效

相关链接