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

Node.js使用Nodemailer发邮件遇证书错误及无发送结果问题求助

问题描述

我使用Nodemailer编写了如下代码发送邮件:

const from = "info@my_domain.com";
const to = 'some_mail@gmail.com';
const subject = 'my subject';
const html = '<b>Hello world</b>';

const smtpOptions = {
  "host": "mail.my_domain.com",
  "port": 587,
  "secure": false,
  "auth": {
    "user": "info@my_domain.com",
    "pass": "12345679"
  },
}

const transporter = nodemailer.createTransport(smtpOptions);

try {
  const a = await transporter.sendMail({
    from,
    to,
    subject,
    html
  });
} catch (err) {
  console.log(err);
}   

运行后出现错误:

Error: self signed certificate at TLSSocket.onConnectSecure
(node:_tls_wrap:1532:34) at TLSSocket.emit (node:events:527:28) at
TLSSocket._finishInit (node:_tls_wrap:946:8) at
TLSWrap.ssl.onhandshakedone (node:_tls_wrap:727:12) { code:
'ESOCKET', command: 'CONN' }

尽管我拥有有效的SSL证书,经查询后我在smtpOptions中添加了如下配置:

tls: {
    rejectUnauthorized: false
}

现在不再报错,但邮件仍未发送。请问该错误产生的原因是什么,如何解决才能正常发送邮件?


原因分析

1. 初始自签名证书错误的根源

你提到有有效SSL证书,但触发self signed certificate错误通常是这几种情况:

  • SMTP服务器的证书链不完整,缺少中间证书,导致Node.js无法验证证书合法性
  • 服务器使用私有CA颁发的证书,而Node.js默认根证书库不包含该CA
  • SMTP服务器主机名与证书上的域名不匹配

2. 关闭证书验证后邮件未发送的原因

rejectUnauthorized: false只是绕过了TLS握手的证书校验,但没解决实际的发送问题,常见原因包括:

  • SMTP服务器的端口与secure参数不匹配(比如587端口需要支持STARTTLS,而你当前配置可能未触发该流程)
  • 用户名/密码错误,但关闭校验后错误未被正确抛出
  • 应用服务器IP被SMTP服务器的防火墙拦截,或邮件被放入服务器发送队列但无反馈
  • 代码未打印发送结果,无法确认是否真的触发了发送请求

解决步骤

步骤1:修复证书验证问题(不推荐长期关闭校验)

直接关闭证书验证有安全风险,建议优先修复证书问题:

  • 检查SMTP服务器配置,确保安装了完整的证书链(包含根证书和中间证书)
  • 如果是私有CA证书,在tls选项中指定CA证书路径:
const fs = require('fs');
// ...
tls: {
  ca: fs.readFileSync('/path/to/your/ca-cert.pem')
}

步骤2:验证SMTP服务器配置匹配度

  • 确认端口与secure参数的对应关系:
    • 端口587对应secure: false,但需服务器支持STARTTLS
    • 端口465对应secure: true
  • 用命令行工具测试SMTP连接(比如swaks),确认服务器是否正常响应:
swaks --to some_mail@gmail.com --from info@my_domain.com --server mail.my_domain.com:587 --auth-user info@my_domain.com --auth-password 12345679 --tls

步骤3:完善代码的日志与错误处理

添加详细日志,明确发送状态:

try {
  const info = await transporter.sendMail({
    from,
    to,
    subject,
    html
  });
  console.log('邮件发送成功,消息ID:', info.messageId);
  console.log('预览链接:', nodemailer.getTestMessageUrl(info));
} catch (err) {
  console.error('发送失败详情:', err);
  console.error('错误代码:', err.code);
  console.error('服务器响应:', err.response);
}

步骤4:检查SMTP服务器的发送限制

  • 确认应用服务器IP在SMTP服务器的白名单内
  • 检查邮箱账户是否开启了SMTP服务,是否需要使用应用专用密码(比如Gmail开启两步验证后需用应用密码)
  • 确认未触发邮件服务器的发送频率限制

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 06:45:32