IAM Secret Access Key转SMTP凭证失败:Nodemailer认证错误排查
解决AWS SES SMTP凭证认证失败(535 Invalid login)的问题
核心问题:硬编码的日期值完全错误
AWS SES SMTP凭证生成要求使用生成凭证当天的日期(YYYYMMDD格式),你的代码里硬写了const date = "11111111",这直接导致签名无效,是认证失败的主要原因。
次要问题:签名过程的编码处理不当
原sign函数里用digest("latin1")再转字符数组,容易出现字节丢失或编码偏差,应该直接操作二进制Buffer,避免不必要的字符转换。
修复后的代码
修正SMTP密码生成函数
const crypto = require('crypto'); const region = "eu-central-1"; const service = "ses"; const terminal = "aws4_request"; const message = "SendRawEmail"; const versionInBytes = [0x04]; // 动态获取当前UTC日期的YYYYMMDD格式 const getCurrentDate = () => { const now = new Date(); return `${now.getUTCFullYear()}${String(now.getUTCMonth() + 1).padStart(2, '0')}${String(now.getUTCDate()).padStart(2, '0')}`; }; function sign(key, msg) { return crypto.createHmac('sha256', key) .update(Buffer.from(msg, 'utf8')) .digest(); } export const generateSmtpPassword = (key) => { const date = getCurrentDate(); let signature = sign(Buffer.from(`AWS4${key}`, 'utf8'), date); signature = sign(signature, region); signature = sign(signature, service); signature = sign(signature, terminal); signature = sign(signature, message); // 拼接版本字节和签名Buffer const signatureAndVersion = Buffer.concat([ Buffer.from(versionInBytes), signature ]); return signatureAndVersion.toString('base64'); };
额外检查项
- 确认IAM用户的Access Key状态为Active(你的日志显示状态正常,这部分没问题)
- 沙盒模式下,发件人和收件人必须是已验证的邮箱地址
- SMTP端点
email-smtp.eu-central-1.amazonaws.com与区域eu-central-1匹配,端口587搭配secure: false会自动触发STARTTLS,配置正确
内容的提问来源于stack exchange,提问作者Fiisa
相关产品推荐
相关产品推荐

