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

如何为Nodemailer的SMTPTransport挂载日志器?自定义Winston日志器无错误日志

解决Nodemailer SMTPTransport自定义Winston日志器不记录错误的问题

我来帮你排查这个头疼的问题——自定义Winston日志器挂到SMTPTransport后完全不记录错误,结合你给出的代码片段,咱们一步步拆解可能的原因和解决办法:

1. 先确认Winston日志器本身能正常工作

这是最基础的排查步骤:先脱离Nodemailer,单独测试你的Winston实例能不能输出错误日志。比如在代码里加一行:

customLogger.error('测试错误日志');

如果这行都没有输出,那问题根本不在Nodemailer集成上,而是你的Winston配置有问题:

  • 检查transports是否正确配置(比如文件传输的路径是否有权限,控制台传输是否启用)
  • 确认日志级别(level)设置是否包含error,如果设成了info或更高,error日志会被过滤
  • 检查format是否正确,有没有把日志内容格式化到能被你看到的地方

2. 正确给SMTPTransport挂载自定义Winston日志器

从你代码里的this.logger = shared.getLogger(...)来看,你可能还在使用Nodemailer内置的日志工具,而不是直接传入自定义Winston实例。正确的做法是在初始化SMTPTransport时,直接把Winston实例传给options的logger字段:

const winston = require('winston');

// 先创建你的自定义Winston日志器
const customLogger = winston.createLogger({
  level: 'error',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.Console()
  ]
});

// 初始化SMTPTransport时传入自定义logger
const transporter = nodemailer.createTransport({
  host: 'your-smtp-host',
  port: 587,
  auth: {
    user: 'your-email',
    pass: 'your-password'
  },
  // 关键:直接传Winston实例
  logger: customLogger,
  // 可选:给日志加组件标识,方便区分
  component: 'smtp-transport'
});

3. 确保错误回调里显式调用日志方法

Nodemailer的内置logger会自动处理错误日志,但自定义logger不会自动帮你做这件事。你需要在send方法的错误回调里,手动调用Winston的error方法:

send(mail, callback) {
  // ...你的其他代码
  connection.send(envelope, mail.message.createReadStream(), (err, info) => {
    if (err) {
      // 手动记录错误日志,带上上下文信息(比如信封、错误详情)
      this.logger.error('SMTP邮件发送失败', {
        error: err.stack || err.message,
        envelope: envelope,
        timestamp: new Date().toISOString()
      });
      // 别忘了把错误传给回调
      return callback(err);
    }
    // 可选:记录成功日志
    this.logger.info('SMTP邮件发送成功', { messageId: info.messageId });
    callback(null, info);
  });
}

4. 监听SMTPTransport的全局错误事件

SMTPTransport继承了EventEmitter,有些底层错误可能不会在send回调里抛出,而是通过error事件触发。所以要额外监听这个事件,避免遗漏日志:

transporter.on('error', (err) => {
  customLogger.error('SMTPTransport全局错误', {
    error: err.stack || err.message,
    timestamp: new Date().toISOString()
  });
});

最后再检查一个细节:Nodemailer的logLevel设置

如果你同时设置了logLevel选项,要确保它的级别低于或等于Winston的级别。比如Winston设为error,Nodemailer的logLevel就不能设为info(否则错误日志会被Nodemailer过滤掉)。不过用自定义logger时,logLevel通常会被忽略,但保险起见可以检查一下。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:33:48