部署至Lambda函数后邮件无法发送的问题求助
Lambda部署Nodemailer发送邮件超时失败
本地使用Nodemailer结合SES或Gmail发送邮件完全正常,但部署到AWS Lambda后无法发送,API Gateway超过30秒时限后返回“Endpoint request timed out”错误。已确认Lambda函数具备发送SES邮件的全部权限,更换为Gmail后问题依旧。
CloudWatch日志显示连接超时错误:
2022-11-16T06:54:23.547Z 6d967bf2-0837-4bd8-ae5f-011842656d15 INFO Error: Connection timeout at SMTPConnection._formatError (/var/task/node_modules/nodemailer/lib/smtp-connection/index.js:790:19) at SMTPConnection._onError (/var/task/node_modules/nodemailer/lib/smtp-connection/index.js:776:20) at Timeout.<anonymous> (/var/task/node_modules/nodemailer/lib/smtp-connection/index.js:235:22) at listOnTimeout (node:internal/timers:559:17) at processTimers (node:internal/timers:502:7) { code: 'ETIMEDOUT', command: 'CONN' }
当前使用的邮件发送函数:
const transporter = nodemailer.createTransport ({ service: 'gmail', host: 'smtp.gmail.com', port: 587, secure: true, auth: { user: config.REACT_APP_EMAIL, pass: config.REACT_APP_EMAIL_PASS, }, }); const sendOutMail = async (receiver, emailSubject, body) => { return transporter.sendMail({ from: config.REACT_APP_EMAIL, to: receiver, subject: emailSubject, text: body, html: '<div> ' + emailSubject + '</div>', }) .then( results => { console.log("Success:", results); return true }) .catch ( error => { console.log("Error:", error); return false }) }
解决方法
1. 检查Lambda网络配置
Lambda默认运行在VPC私有子网时,无法直接访问公网(如SMTP服务器)。如果配置了VPC:
- 给私有子网配置NAT网关,让Lambda通过NAT访问公网;
- 或直接将Lambda移出VPC,使用默认公共网络环境(业务允许的情况下)。
2. 修正Nodemailer配置参数冲突
你的Gmail配置存在参数不匹配问题:
- 端口587对应
secure: false(587端口用STARTTLS加密,465端口才用secure: true),参数冲突会导致连接异常。修正后配置:
const transporter = nodemailer.createTransport ({ service: 'gmail', host: 'smtp.gmail.com', port: 587, secure: false, // 587端口需设为false auth: { user: config.REACT_APP_EMAIL, pass: config.REACT_APP_EMAIL_PASS, }, });
3. 调整Lambda超时时间
API Gateway默认超时30秒,但Lambda默认仅3秒,需将Lambda超时时间调整至接近30秒(如28秒),避免Lambda先于API Gateway超时。
4. 改用AWS SES SDK替代SMTP方式
在AWS环境下,直接使用SES SDK比SMTP更高效,还能避免网络连接问题:
const AWS = require('aws-sdk'); const ses = new AWS.SES({ region: '你的AWS区域' }); const sendOutMail = async (receiver, emailSubject, body) => { const params = { Destination: { ToAddresses: [receiver] }, Message: { Body: { Html: { Data: `<div>${emailSubject}</div>` }, Text: { Data: body } }, Subject: { Data: emailSubject } }, Source: config.REACT_APP_EMAIL }; try { const result = await ses.sendEmail(params).promise(); console.log("Success:", result); return true; } catch (error) { console.log("Error:", error); return false; } }
内容的提问来源于stack exchange,提问作者Akugbe Stephen
相关产品推荐
相关产品推荐

