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

Nodemailer运行一段时间后停止发邮件无响应无报错该如何排查?

故障原因分析与修复方案

你遇到的故障不是Nodemailer的已知问题,是代码实现存在资源泄漏和请求处理缺陷导致的,具体问题和修复方法如下:

  • 重复创建SMTP传输实例导致连接资源泄漏
    你将nodemailer.createTransport初始化逻辑写在了/send接口的请求回调内,每收到一次发送请求就会新建一个SMTP连接实例,旧实例使用完后没有主动销毁,长时间运行会逐步占满服务器的文件句柄、SMTP连接数配额,后续请求无法新建连接就会陷入无限等待。
    修复方案:将transporter初始化逻辑移到接口外层,全局仅初始化一次,同时开启内置连接池控制最大连接数,参考代码:
    // 全局初始化,仅运行一次
    let transporter = nodemailer.createTransport(smtpTransport({
      pool: true, // 开启连接池
      maxConnections: 5, // 最大连接数按需调整
      name: "myname",
      host: "myhost",
      port: 465,
      secure: true,
      auth: {
        user: "info@myhost.nl",
        pass: "123456",
      },
      tls: {
        rejectUnauthorized: false,
      },
      logger: true,
      debug: true,
    }));
    // 监听连接层面的报错,避免遗漏日志
    transporter.on('error', err => {
      console.log('SMTP连接异常:', err);
    })
    
  • 错误场景未返回响应导致请求堆积
    你在transporter.sendMail的错误回调中仅打印了错误日志,没有给客户端返回响应、结束当前请求,出错的请求会一直挂在服务端占用连接资源,长时间运行后服务的请求连接队列被占满,新请求就会无响应。
    修复方案:错误分支也正常返回响应结束请求,参考代码:
    transporter.sendMail(mailOptions, (error, info) => {
      if (error) {
        console.log(error);
        // 错误场景返回响应
        return res.status(500).render("contact", { msg: "邮件发送失败" });
      }
      res.render("contact", { msg: "Email has been sent" });
      console.log("Email has been sent");
    });
    
  • 同步读取模板文件阻塞事件循环
    每次请求都调用fs.readFileSync同步读取邮件模板,同步操作会阻塞Node.js事件循环,长时间运行或者并发量升高时会导致服务响应卡顿。
    修复方案:启动时一次性读取模板缓存到内存,不需要每次请求都读:
    // 全局预读取模板
    const emailTemplate = fs.readFileSync('employee.html').toString();
    // 接口内直接替换token
    const output = emailTemplate.replace("${token}", token);
    
辅助定位方法

如果需要进一步确认根因,可以做以下排查:

  • 运行时监控服务器的文件句柄占用、TCP连接数变化,确认是否存在资源持续上涨不释放的情况,Linux可使用lsof -p 进程ID、netstat -anp | grep 465命令查看,Windows可通过资源监视器查看对应进程的网络连接、句柄占用。
  • 给Express添加全局超时中间件,避免请求无限挂起,同时超时的时候可以打印日志定位问题:
    app.use((req, res, next) => {
      res.setTimeout(10000, () => {
        console.log('请求超时:', req.path, req.body);
        return res.status(408).send('请求超时');
      })
      next();
    })
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 10:57:05