MERN项目使用nodemailer仅网站运行时可发送邮件问题求解
问题根因
你当前将邮件发送逻辑注册为了Express中间件,这类中间件仅会在后端收到前端发来的HTTP请求时才会执行——也就是只有用户在浏览器打开网站、前端向后端发起请求时,才会触发邮件检查和发送逻辑。服务端没有收到请求时,这段代码自然不会自动运行,也就出现了网站未运行时无法发邮件的问题。
修复方案
你需要额外引入定时任务库,让邮件检查逻辑可以脱离HTTP请求,在服务端后台自动按指定周期运行,推荐使用node-schedule,操作步骤如下:
- 安装依赖
npm install node-schedule
- 重构邮件发送模块,移除中间件属性,抽成独立定时任务
修改后的sendEmail文件参考代码:
const asyncHandler = require("express-async-handler"); const nodemailer = require("nodemailer"); const schedule = require('node-schedule'); // 独立邮件发送逻辑,删除原有的req/res/next中间件参数 const sendRemainderEmail = asyncHandler(async () => { const transporter = nodemailer.createTransport({ service: "替换为你的邮件服务商", host: "替换为你的SMTP host", port: 465, secure: true, auth: { user: "替换为你的发件邮箱", pass: "替换为你的邮箱授权码", }, }); transporter.verify((err, success) => { if (err) console.error("邮箱配置错误:", err); console.log("邮箱配置校验通过"); }); // 保留你原有遍历数据库、匹配触发日期的逻辑 const mailOptions = { from: "替换为发件人邮箱", to: "替换为收件人邮箱", subject: "待办提醒", text: `这是你的定时提醒邮件!`, }; transporter.sendMail(mailOptions, async (error, info) => { if (error) { console.log("邮件发送失败:", error); } else { console.log("邮件发送成功: " + info.response); // 建议增加逻辑:发送成功后将对应数据库记录标记为已发送,避免重复触发 } transporter.close(); }); }) // 配置定时规则,使用cron表达式指定运行周期 // cron语法:秒 分 时 日 月 周 // 示例规则:每天凌晨0点执行一次邮件检查 const emailJob = schedule.scheduleJob('0 0 0 * * *', async () => { console.log("开始执行定时邮件检查任务"); await sendRemainderEmail(); }); module.exports = { sendRemainderEmail, emailJob };
- 修改server.js引入逻辑,不需要挂载为中间件,直接引入即可自动注册定时任务
// 直接引入定时任务文件即可,不需要app.use挂载 require("./替换为你的sendEmail文件路径"); // 其他原有服务逻辑保持不变
注意事项
- 如果你将服务部署在无服务器(Serverless)平台(比如Vercel免费版、Netlify免费版),这类平台会在无请求时自动休眠,定时任务也会暂停运行。如果需要稳定触发定时任务,需要将服务部署在支持持续运行的云服务器上。
- 可以根据需求调整cron表达式,比如需要每小时检查一次触发日期,可将表达式修改为
0 0 * * * *。 - 务必增加发送标记逻辑,避免同一提醒被多次重复发送。
内容的提问来源于stack exchange,提问作者Hessah
相关产品推荐
相关产品推荐

