You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 22:12:14