基于React前端时间参数,实现NodeJS定时发送邮件
问题:使用node-schedule处理前端传入的日期时间实现定时发送邮件失败
背景
我有一个ReactJS应用,支持用户提交日期、时间及文本内容并提交到NodeJS后端。当前后端实现即时发送邮件的代码如下:
app.post("/send", function (req, res) { let mailOptions = { from: `${req.body.vals.email}`, to: process.env.EMAIL, subject: 'SUBJECT INFO', html: `${req.body.vals.date} ${req.body.vals.time} ${req.body.vals.info}`, }; transporter.sendMail(mailOptions, function (err, data) { if (err) { res.json({ status: "fail", }); } else { console.log("email sent"); res.json({ status: "success", }); } }); });
需求与问题
希望根据前端传入的指定日期和时间定时发送邮件,使用node-schedule库时,日期时间格式处理出现问题,导致定时任务未生效。
前端传入的日期格式为2022-08-28,时间格式为14:07。
尝试的无效代码
app.post("/send", function (req, res) { let mailOptions = { from: `${req.body.vals.email}`, to: process.env.EMAIL, subject: 'SUBJECT INFO', html: `${req.body.vals.date} ${req.body.vals.time} ${req.body.vals.info}`, }; const dateParsed = new Date(`${req.body.vals.date}T${req.body.vals.time}Z`) schedule.scheduleJob(dateParsed, function(){ transporter.sendMail(mailOptions, function (err, data) { if (err) { res.json({ status: "fail", }); } else { console.log("email sent"); res.json({ status: "success", }); } }); }) });
解决方案
1. 修正日期时间解析问题
原代码中直接拼接T${time}Z会将时间解析为UTC时区,若前端传入的是本地时间,会导致定时时间偏差。正确做法是拆分日期时间字段,构建对应时区的Date对象:
// 拆分日期和时间字段 const [year, month, day] = req.body.vals.date.split('-'); const [hour, minute] = req.body.vals.time.split(':'); // 构建本地时间Date对象(注意月份从0开始,需减1) const scheduledDate = new Date(year, month - 1, day, hour, minute);
2. 修正响应时机问题
原代码在定时任务回调中返回HTTP响应是错误的,因为POST请求的连接会在任务调度完成后就关闭,无法等到定时任务执行。应先返回任务调度成功的响应,再在定时任务内部处理邮件发送结果。
完整修正代码
app.post("/send", function (req, res) { const { email, date, time, info } = req.body.vals; const mailOptions = { from: email, to: process.env.EMAIL, subject: 'SUBJECT INFO', html: `${date} ${time} ${info}`, }; // 解析前端传入的日期时间为本地时间 const [year, month, day] = date.split('-'); const [hour, minute] = time.split(':'); const scheduledDate = new Date(year, month - 1, day, hour, minute); // 校验日期有效性 if (isNaN(scheduledDate.getTime())) { return res.json({ status: "fail", message: "无效的日期时间格式" }); } // 调度定时邮件任务 schedule.scheduleJob(scheduledDate, function(){ transporter.sendMail(mailOptions, function (err) { if (err) { console.error("定时邮件发送失败:", err); } else { console.log("定时邮件发送成功"); } }); }); // 立即返回任务创建成功的响应 res.json({ status: "success", message: "定时邮件任务已创建" }); });
额外注意事项
- 若服务器使用UTC时区,需将前端本地时间转换为UTC时间后再构建Date对象,避免时差问题。
- 确保已正确安装依赖:
npm install node-schedule - 若需服务器重启后保留定时任务,需将任务信息存入数据库,重启时重新加载调度。
内容的提问来源于stack exchange,提问作者helpmepie
相关产品推荐
相关产品推荐

