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

Nodemailer无法发送密码重置邮件问题求助

排查Nodemailer异步发送邮件失败问题

1. 先暴露具体错误信息

当前代码的catch块仅返回通用提示,无法定位核心问题。先修改错误处理逻辑,打印完整错误日志:

catch (error) {
  console.error('邮件发送错误详情:', error);
  res.status(500).json({message: "Failed to send mail", error: error.message});
}

同时,将Password.create移入try块——await Password.create失败时会直接抛出错误,当前的if(entry)判断无法捕获该错误,会直接走到else分支丢失关键信息:

router.post("/forgetpassword", async (req, res) => {
  const { username } = req.body;

  try {
    const user = await User.findOne({ username: username });

    if (!user) {
      return res.status(404).json({ message: "User not found" });
    }

    const userID = shortId.generate();
    const entry = await Password.create({
      username: username,
      userID: userID,
    });

    const resetPasswordLink = Frontend_URL + "/reset/" + userID;

    var mailOptions = {
      from: `"CampusLink" <${process.env.GMAIL}>`,
      to: username,
      subject: "Reset Your Password",
      html: `
      <p>Hello,</p>
      <p>We received a request to reset your password. Click the link below to reset your password:</p>
      <p><a target="_blank" href="${resetPasswordLink}">Reset Password</a></p>
      <p><strong>Please note that this link is valid for only 5 minutes.</strong></p>
      <p>If you didn't request this, you can safely ignore this email.</p>
      <p>Best regards,<br/>CampusLink Team</p>
    `,
    };

    const info = await transporter.sendMail(mailOptions);
    console.log('邮件发送成功返回:', info); // 打印发送回执信息
    res.status(200).json({message: "Success"});
  } catch (error) {
    console.error('请求处理错误:', error);
    if (error.message.includes('User not found')) {
      res.status(404).json({message: "User not found"});
    } else {
      res.status(500).json({message: "Failed to process request", error: error.message});
    }
  }
});

2. 检查Gmail SMTP配置有效性

  • 验证环境变量加载:在transporter初始化前打印环境变量,确认账号密码已正确读取:
    console.log('GMAIL账号:', process.env.GMAIL);
    console.log('GMAIL密码状态:', process.env.GPASSWORD ? '已配置' : '未配置');
    var transporter = nodemailer.createTransport({...});
    
  • 简化Gmail配置:设置service: "Gmail"时,Nodemailer会自动填充host、port等参数,重复配置可能引发冲突,简化为:
    var transporter = nodemailer.createTransport({
      service: "Gmail",
      auth: {
        user: process.env.GMAIL,
        pass: process.env.GPASSWORD,
      },
    });
    
  • 确认密码类型:若Gmail账号开启两步验证,必须使用**应用专用密码(App Password)**而非普通登录密码;未开启两步验证的账号,需确保已开启“不太安全的应用访问”(Google已逐步淘汰该选项,优先推荐App Password)。

3. 验证SMTP连接状态

transporter初始化可能静默失败,添加连接验证逻辑:

transporter.verify(function(error, success) {
  if (error) {
    console.error('SMTP连接失败:', error);
  } else {
    console.log('SMTP连接正常,可发送邮件');
  }
});

4. 排查邮件投递问题

  • 检查收件邮箱的垃圾邮件文件夹,测试邮件常被归类为垃圾邮件;
  • 确认mailOptions.from格式合规,Gmail会拦截格式异常的发件人地址;
  • 服务器网络限制:若部署在云服务器,检查是否允许587端口的出站连接,部分服务商默认限制SMTP端口。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 13:59:33