基于Node.js与MongoDB实现用户文档过期邮件通知方案求助
实现文档到期自动邮件通知(Node.js + MongoDB)
1. 调整数据库模型
首先给文档集合补充必要字段,用于记录过期时间和通知状态,同时关联用户信息以获取邮箱:
// models/Document.js const mongoose = require('mongoose'); const DocumentSchema = new mongoose.Schema({ title: String, content: String, // 用户手动设置的过期日期 expireAt: { type: Date, required: true }, // 标记是否已发送通知,避免重复触发 notified: { type: Boolean, default: false }, // 关联用户ID,用于查询用户邮箱 userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true } }); // 添加复合索引,提升到期文档查询效率 DocumentSchema.index({ expireAt: 1, notified: 1 }); module.exports = mongoose.model('Document', DocumentSchema); // models/User.js const UserSchema = new mongoose.Schema({ email: { type: String, required: true, unique: true }, // 其他用户字段(如用户名、密码等) }); module.exports = mongoose.model('User', UserSchema);
2. 实现定时任务与邮件发送
使用node-schedule做定时调度,nodemailer处理邮件发送,先安装依赖:
npm install node-schedule nodemailer
编写核心逻辑:
const schedule = require('node-schedule'); const nodemailer = require('nodemailer'); const Document = require('./models/Document'); const User = require('./models/User'); // 配置邮件发送器(以Gmail为例,其他邮箱需对应调整SMTP参数) const transporter = nodemailer.createTransport({ service: 'Gmail', auth: { user: 'your-service-email@gmail.com', pass: 'your-app-specific-password' // 注意使用邮箱应用专用密码,而非登录密码 } }); // 定时任务:每天凌晨1点扫描到期未通知的文档 const notifyJob = schedule.scheduleJob('0 1 * * *', async () => { try { // 查询当前时间前到期、且未发送过通知的文档,同时关联用户信息 const expiredDocs = await Document.find({ expireAt: { $lte: new Date() }, notified: false }).populate('userId'); for (const doc of expiredDocs) { const targetUser = doc.userId; if (!targetUser.email) continue; // 构造邮件内容 const mailContent = { from: 'your-service-email@gmail.com', to: targetUser.email, subject: `文档「${doc.title}」已过期`, text: `您好,您存储的文档「${doc.title}」已于${doc.expireAt.toLocaleString()}到期,请及时查看或处理。` }; // 发送邮件 await transporter.sendMail(mailContent); // 标记文档已发送通知 await Document.findByIdAndUpdate(doc._id, { notified: true }); console.log(`已向${targetUser.email}发送文档「${doc.title}」的过期通知`); } } catch (err) { console.error('处理到期文档通知时出错:', err); // 可添加错误日志持久化或告警逻辑 } }); console.log('文档到期通知定时任务已启动');
3. 关键注意事项
- 避免重复通知:必须通过
notified字段标记已处理的文档,防止定时任务重复发送邮件。 - 邮件服务适配:不同邮箱服务商的SMTP配置不同,比如QQ邮箱需开启SMTP服务并使用授权码,企业邮箱需填写对应SMTP地址和端口。
- 调度频率调整:测试阶段可将任务设为每分钟执行(
* * * * *),生产环境根据业务需求调整为每天/每小时执行。 - 容错处理:对于邮件发送失败的情况,可引入重试机制(如
async-retry库),或把失败任务存入队列后续再处理。
内容的提问来源于stack exchange,提问作者Yatndeep Dubey
相关产品推荐
相关产品推荐

