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

使用Nodemailer对接mail.com SMTP时出现版本号错误的解决咨询

Nodemailer配置mail.com SMTP时SSL版本错误的问题解决

问题详情

配置Nodemailer通过mail.com的SMTP服务器发送邮件时,触发以下SSL相关错误:

Error: AC650000:error:0A00010B:SSL routines:ssl3_get_record:wrong version number:c:\ws\deps\openssl\openssl\ssl\record\ssl3_record.c:355:
{
 library: 'SSL routines',
 reason: 'wrong version number',
 code: 'ESOCKET',
 command: 'CONN'
}

当前使用的Nodemailer配置代码:

import nodemailer from 'nodemailer';
import dotenv from 'dotenv';
import path from 'path';

// Load environment variables from .env file
dotenv.config({ path: path.resolve('.env') });

console.log('EMAIL_USERNAME:', process.env.EMAIL_USERNAME);
console.log('EMAIL_PASSWORD:', process.env.EMAIL_PASSWORD);

// Create a Nodemailer transporter using SMTP with mail.com
const transporter = nodemailer.createTransport({
  host: 'smtp.mail.com',
  port: 587, // Use 587 for STARTTLS
  secure: false, // Use false for STARTTLS
  auth: {
    user: process.env.EMAIL_USERNAME,
    pass: process.env.EMAIL_PASSWORD,
  },
  tls: {
    rejectUnauthorized: false, // Allow self-signed certificates if necessary
  },
});

export const requestPasswordReset = async (req, res) => {
  const { email } = req.body;

  try {
    const user = await User.findOne({ email });
    if (!user) {
      return res.status(400).json({ message: 'Utilisateur non trouvé' });
    }

    const resetToken = crypto.randomBytes(32).toString('hex');
    const hashedToken = crypto.createHash('sha256').update(resetToken).digest('hex');
    user.resetPasswordToken = hashedToken;
    user.resetPasswordExpires = Date.now() + 3600000; // 1 hour

    await user.save();

    const resetUrl = `http://localhost:3000/reset/${resetToken}`;

    const mailOptions = {
      to: user.email,
      from: process.env.EMAIL_FROM,
      subject: 'Réinitialisation du mot de passe',
      text: `Vous recevez cet email parce que vous (ou quelqu'un d'autre) avez demandé la réinitialisation du mot de passe de votre compte.\n\n
             Cliquez sur le lien suivant ou copiez-le dans votre navigateur pour compléter le processus :\n\n
             ${resetUrl}\n\n
             Si vous n'avez pas demandé cette réinitialisation, veuillez ignorer cet email et votre mot de passe restera inchangé.\n`,
    };

    await transporter.sendMail(mailOptions);

    res.status(200).json({ message: 'Email de réinitialisation envoyé' });
  } catch (error) {
    console.error('Erreur lors de la demande de réinitialisation de mot de passe :', error);
    res.status(500).json({ message: 'Erreur lors de la demande de réinitialisation de mot de passe' });
  }
};

已尝试操作:

  • 验证邮箱账号和密码正确;
  • 确认.env文件加载正常,变量可访问;
  • 测试secure: true+端口465、secure: false+端口587等组合,均触发相同错误。

环境信息:

  • Node.js版本:20.15.0
  • Nodemailer版本:6.9.14
  • 操作系统:Windows 11

错误原因

该错误核心是客户端与mail.com SMTP服务器的SSL/TLS版本协商不兼容。Windows环境下Node.js默认的SSL配置可能与mail.com服务器要求的版本不匹配,或者本地网络(防火墙、代理、SSL拦截工具)篡改了SSL握手数据包,导致服务器识别到错误的版本号。

解决方案

1. 强制指定兼容的TLS版本

在transporter的tls配置中明确指定支持的TLS版本范围,覆盖Node.js默认配置:

const transporter = nodemailer.createTransport({
  host: 'smtp.mail.com',
  port: 587,
  secure: false,
  auth: {
    user: process.env.EMAIL_USERNAME,
    pass: process.env.EMAIL_PASSWORD,
  },
  tls: {
    rejectUnauthorized: false,
    minVersion: 'TLSv1.2',
    maxVersion: 'TLSv1.3'
  },
});

2. 排查本地网络干扰

  • 临时关闭Windows防火墙、杀毒软件的网络拦截功能,测试连接是否正常;
  • 如果使用代理,暂时关闭代理后重试;
  • 检查是否存在SSL拦截工具(如部分VPN、企业安全软件),这类工具会篡改SSL证书,导致握手失败。

3. 核对mail.com官方SMTP配置细节

mail.com官方SMTP要求:

  • 端口587(STARTTLS):必须设置secure: false,连接后自动升级TLS;
  • 端口465(SSL):必须设置secure: true;
  • 确保mailOptions.from的邮箱地址与auth.user完全一致,部分邮件服务器要求发件人必须为认证账号本身。

4. 更新依赖或测试Node.js版本

  • 执行npm update nodemailer更新到最新版本,修复可能存在的兼容性问题;
  • 若条件允许,测试Node.js 18.x版本,部分Windows环境下该版本的SSL配置兼容性更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 08:17:35