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

如何使用MongoDB Atlas Triggers向特定期限未登录用户发送自动化邮件

方案1:使用MongoDB Atlas 定时触发器(Scheduled Trigger)实现

你要找的无集合操作触发的触发器就是Atlas的定时触发器,和你之前看到的数据库事件触发器是两类不同的触发器,专门用于定时执行任务:

  • 进入Atlas对应集群的「Triggers」面板,点击「Add Trigger」,触发器类型选择Scheduled
  • 配置触发规则:可以直接选择按天固定时间执行,也可以用cron表达式自定义频率,例如下方cron表示每天北京时间上午9点执行:0 1 * * *(注意Atlas默认用UTC时区,北京时间要减8小时换算)
  • 在触发器的函数编辑区写入核心逻辑,示例代码如下:
// 引入依赖,需要提前在触发器的Dependencies面板添加nodemailer和dayjs
const nodemailer = require('nodemailer');
const dayjs = require('dayjs');

exports = async function() {
  // 1. 格式化当日日期,格式要和你streaks数组中存储的日期格式完全一致
  const today = dayjs().format('YYYY-MM-DD');
  // 2. 获取users集合实例
  const usersCollection = context.services.get("你的集群服务名").db("你的库名").collection("users");
  // 3. 查询所有streaks不包含当日日期的用户
  const targetUsers = await usersCollection.find({
    streaks: { $ne: today }
  }).toArray();
  // 4. 初始化邮件发送客户端,邮箱密钥存在Atlas的Values&Secrets中,不要硬编码
  const transporter = nodemailer.createTransport({
    service: '你的邮箱服务商,比如QQ邮箱、Gmail',
    auth: {
      user: context.values.get("EMAIL_ACCOUNT"),
      pass: context.values.get("EMAIL_AUTH_CODE")
    }
  });
  // 5. 批量发送邮件,建议用异步池控制并发,避免触发邮箱频率限制
  for (const user of targetUsers) {
    await transporter.sendMail({
      from: '你的发件人名称 <发件人邮箱>',
      to: user.email,
      subject: '提醒:今日还未登录哦',
      text: '登录账号保持你的连续登录天数吧~'
    });
  }
  return { success: true, count: targetUsers.length };
};
  • 额外配置:
    • 在触发器的「Dependencies」面板添加nodemailer和dayjs依赖
    • 在Atlas项目的「Values & Secrets」面板添加邮箱账号、授权码等敏感配置,避免硬编码泄露

方案2:自有Express服务实现(适合不想全依赖Atlas的场景)

如果你不想用Atlas触发器,直接在现有的Node.js服务中集成定时任务即可,和现有Mongoose逻辑完全兼容:

  • 先安装依赖:npm install node-cron nodemailer dayjs
  • 在Express服务中添加定时任务代码:
const cron = require('node-cron');
const nodemailer = require('nodemailer');
const dayjs = require('dayjs');
const User = require('./models/User'); // 你现有的Mongoose User模型

// 每天北京时间9点执行
cron.schedule('0 9 * * *', async () => {
  const today = dayjs().format('YYYY-MM-DD');
  // 用现有Mongoose模型查询目标用户
  const targetUsers = await User.find({ streaks: { $ne: today } });
  // 初始化邮件客户端,密钥存在你的.env文件中
  const transporter = nodemailer.createTransport({
    service: process.env.EMAIL_SERVICE,
    auth: {
      user: process.env.EMAIL_ACCOUNT,
      pass: process.env.EMAIL_AUTH_CODE
    }
  });
  // 发送邮件逻辑和方案1一致
  for (const user of targetUsers) {
    await transporter.sendMail({
      from: process.env.EMAIL_FROM,
      to: user.email,
      subject: '提醒:今日还未登录哦',
      text: '登录账号保持你的连续登录天数吧~'
    });
  }
}, {
  timezone: 'Asia/Shanghai' // 直接指定时区,不需要换算
});
  • 生产环境优化建议:如果你的Express服务是多实例部署,建议加分布式锁(比如用Redis存当日任务执行标记),避免重复发送邮件。

注意事项

如果你的streaks数组存储的是ISODate类型而非格式化字符串,查询时需要匹配当日的时间范围,避免时分秒不匹配导致查询错误:

const startOfToday = dayjs().startOf('day').toDate();
const endOfToday = dayjs().endOf('day').toDate();
const targetUsers = await User.find({
  streaks: { $not: { $elemMatch: { $gte: startOfToday, $lte: endOfToday } } }
});

内容的提问来源于stack exchange,提问作者seshkebab

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 10:24:03