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

基于Node.js栈,如何用Nodemailer实现年度日期提前一周自动发提醒邮件?

嘿,作为编程新手能想到做这个功能超棒的!我来一步步帮你拆解,每个环节都尽量讲得直白,跟着做就能搞定:

第一步:先搞定依赖安装与基础项目结构

首先打开终端,在你的项目文件夹里安装需要的包:

npm install express mongoose nodemailer node-schedule dotenv

给你简单说下每个包的作用:

  • express:用来搭建Web服务器,处理表单提交请求
  • mongoose:帮你连接和操作MongoDB数据库
  • nodemailer:专门用来发送邮件的工具
  • node-schedule:实现定时任务,比如每天自动检查要发的提醒
  • dotenv:用来存邮箱密码、数据库链接这类敏感信息,避免硬编码在代码里

推荐的项目结构大概是这样(不用完全照搬,能理清逻辑就行):

  • /models:放MongoDB的数据模型
  • /routes:处理表单提交的路由
  • /controllers:处理具体的业务逻辑
  • /utils:放邮件发送、定时任务这类工具函数
  • .env:存配置信息
  • server.js:项目入口文件
第二步:创建数据库模型存储用户数据

我们需要把用户输入的邮箱和重要日期存到MongoDB里,所以先写一个数据模型。在/models/UserReminder.js里写:

const mongoose = require('mongoose');

const userReminderSchema = new mongoose.Schema({
  email: {
    type: String,
    required: true,
    unique: true, // 避免同一个邮箱重复提交
    trim: true,
    lowercase: true // 统一转小写,防止大小写不同导致重复
  },
  importantDate: {
    type: Date,
    required: true
  }
});

module.exports = mongoose.model('UserReminder', userReminderSchema);
第三步:实现表单提交的功能

首先在server.js里搭建基础的Express服务器,连接MongoDB:

require('dotenv').config();
const express = require('express');
const mongoose = require('mongoose');
const reminderRoutes = require('./routes/reminders');
const path = require('path');

const app = express();

// 中间件:解析表单数据和JSON
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
// 托管静态页面(比如我们的表单页面)
app.use(express.static(path.join(__dirname, 'public')));

// 连接MongoDB,记得在.env里填你的数据库链接
mongoose.connect(process.env.MONGO_URI)
  .then(() => console.log('成功连接MongoDB!'))
  .catch(err => console.error('MongoDB连接失败:', err));

// 挂载路由
app.use('/api/reminders', reminderRoutes);

// 启动服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`服务器跑在端口${PORT}啦!`));

然后写路由文件/routes/reminders.js:

const express = require('express');
const router = express.Router();
const { createReminder } = require('../controllers/reminderController');

// 处理表单提交的POST请求
router.post('/', createReminder);

module.exports = router;

接着写控制器/controllers/reminderController.js,处理表单提交的逻辑:

const UserReminder = require('../models/UserReminder');

exports.createReminder = async (req, res) => {
  try {
    const { email, importantDate } = req.body;
    
    // 先检查用户有没有填全
    if (!email || !importantDate) {
      return res.status(400).send('邮箱和日期都不能为空哦!');
    }

    // 检查这个邮箱是不是已经设置过提醒了
    const existingReminder = await UserReminder.findOne({ email });
    if (existingReminder) {
      return res.status(400).send('这个邮箱已经设置过提醒啦!');
    }

    // 把数据存到数据库
    const reminder = new UserReminder({ email, importantDate });
    await reminder.save();

    res.status(201).send('提醒设置成功!');
  } catch (err) {
    console.error('创建提醒出错:', err);
    res.status(500).send('服务器出小问题啦,稍后再试吧!');
  }
};

最后写一个简单的表单页面/public/index.html,让用户能输入信息:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>设置重要日期提醒</title>
</head>
<body>
  <h1>设置你的重要日期提醒</h1>
  <form action="/api/reminders" method="POST">
    <div>
      <label for="email">你的邮箱:</label>
      <input type="email" id="email" name="email" required>
    </div>
    <div style="margin: 10px 0;">
      <label for="importantDate">重要日期:</label>
      <input type="date" id="importantDate" name="importantDate" required>
    </div>
    <button type="submit">确认设置提醒</button>
  </form>
</body>
</html>
第四步:配置Nodemailer发送邮件

首先在.env文件里填你的邮箱配置(以Gmail为例,其他邮箱类似):

MONGO_URI=mongodb://localhost:27017/reminderApp
PORT=3000
EMAIL_USER=你的gmail邮箱地址
EMAIL_PASS=你的gmail应用密码(注意:要开启两步验证才能生成应用密码)
EMAIL_SERVICE=gmail

敲黑板!如果用Gmail,一定要先开启两步验证,然后去Google账号里生成“应用密码”,不能直接用你的登录密码。如果是QQ邮箱,要开启POP3/SMTP服务,获取授权码当密码用。

然后写邮件工具函数/utils/email.js:

const nodemailer = require('nodemailer');
require('dotenv').config();

// 创建邮件传输器
const transporter = nodemailer.createTransport({
  service: process.env.EMAIL_SERVICE,
  auth: {
    user: process.env.EMAIL_USER,
    pass: process.env.EMAIL_PASS
  }
});

// 发送提醒邮件的函数
exports.sendReminderEmail = async (email, importantDate) => {
  // 把日期格式化成用户易读的样子
  const formattedDate = importantDate.toLocaleDateString('zh-CN', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  });
  
  const mailOptions = {
    from: `日期提醒助手 <${process.env.EMAIL_USER}>`,
    to: email,
    subject: '📅 重要日期即将到来!',
    text: `您好!您设置的重要日期${formattedDate}还有一周就要到啦,请记得做好准备哦!`,
    html: `<p>您好!</p><p>您设置的重要日期<strong>${formattedDate}</strong>还有一周就要到啦,请记得做好准备哦!</p>`
  };

  try {
    await transporter.sendMail(mailOptions);
    console.log(`提醒邮件已成功发送到:${email}`);
  } catch (err) {
    console.error(`发送邮件失败到${email}:`, err);
  }
};
第五步:实现定时自动发送提醒的功能

用node-schedule来设置每天自动检查数据库,看看哪些用户的重要日期在一周后,然后发送邮件。写/utils/scheduler.js:

const schedule = require('node-schedule');
const UserReminder = require('../models/UserReminder');
const { sendReminderEmail } = require('./email');

// 设置每天凌晨1点执行检查任务(cron表达式:分 时 日 月 周)
const reminderJob = schedule.scheduleJob('0 1 * * *', async () => {
  console.log('开始检查需要发送提醒的用户...');
  
  try {
    const today = new Date();
    // 计算一周后的日期
    const oneWeekLater = new Date(today);
    oneWeekLater.setDate(today.getDate() + 7);

    // 取出所有用户的提醒记录
    const allReminders = await UserReminder.find();

    for (const reminder of allReminders) {
      const userImportantDate = reminder.importantDate;
      // 生成今年的重要日期(因为要每年提醒)
      let targetDate = new Date(today.getFullYear(), userImportantDate.getMonth(), userImportantDate.getDate());
      
      // 如果今年的日期已经过了,就用明年的
      if (targetDate < today) {
        targetDate.setFullYear(today.getFullYear() + 1);
      }

      // 检查目标日期和一周后的日期是不是同一天(允许一天的误差,避免时区问题)
      const isMatch = targetDate.toDateString() === oneWeekLater.toDateString();
      if (isMatch) {
        await sendReminderEmail(reminder.email, targetDate);
      }
    }

    console.log('检查完成!');
  } catch (err) {
    console.error('定时任务执行出错:', err);
  }
});

module.exports = reminderJob;

然后在server.js里引入这个定时任务,加一行:

require('./utils/scheduler');

这样服务器启动后,定时任务就会自动运行啦!如果想测试,可以把cron表达式改成*/10 * * * * *,这样每10秒执行一次,测试完再改回凌晨1点的。

一些新手必看的小提示
  1. 本地测试的时候,要确保MongoDB服务已经启动哦!
  2. 时区问题要注意:MongoDB存的是UTC时间,用户输入的是本地时间,所以代码里用toDateString()来比较,避免时区差异导致提醒时间不对。
  3. 后续可以扩展功能:比如让用户修改、删除提醒,或者查看自己的提醒记录。
  4. 如果部署到服务器上,要确保服务器一直运行,比如用pm2来管理Node.js进程,避免服务器重启后任务停止。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:51:56