Lambda中使用AWS SES发送邮件无响应问题求助
问题原因与解决方案
核心问题出在Lambda handler中使用forEach遍历异步任务,导致函数提前退出,SES的发送操作还未完成或后续日志未输出就被终止。
具体原因
forEach方法无法正确处理异步函数,它不会等待内部的await sesClient.send(command)执行完成。你的handler是异步函数,但在遍历完event.Records后就直接结束了,此时Lambda的执行环境会被立即销毁,内部的异步回调还在后台运行,所以sesClient.send()后的日志不会被输出,甚至邮件发送操作可能中途中断。
修复方案
替换forEach为支持异步等待的循环方式,比如for...of,或者用Promise.all批量处理所有异步任务,确保Lambda等待所有邮件发送操作完成后再退出。
方案1:使用for...of循环(推荐,适合顺序处理)
import { SESClient, SendEmailCommand } from "@aws-sdk/client-ses"; const sesClient = new SESClient({ region: "us-west-2" }); export const handler = async (event) => { // 用for...of替代forEach,确保等待每个异步操作完成 for (const msg of event.Records) { try { const args = JSON.parse(msg.body); const command = new SendEmailCommand({ Source: (args.senderEmailAddr || process.env.DEFAULT_SENDER_ADDRESS), Destination: { ToAddresses: [args.recipientEmailAddr] }, Message: { Body: { Text: { Data: args.emailContents } }, Subject: { Data: args.subject }, }, }); const resp = await sesClient.send(command); console.log('++++++++++++++++++++++++++++++++'); console.log(`Email send response ${JSON.stringify(resp)}`); } catch (err) { console.log(`Failed to send email - ${err}`); } } };
方案2:使用Promise.all(适合并行处理多个任务)
import { SESClient, SendEmailCommand } from "@aws-sdk/client-ses"; const sesClient = new SESClient({ region: "us-west-2" }); export const handler = async (event) => { // 将每个消息处理转为Promise,用Promise.all等待全部完成 const sendPromises = event.Records.map(async (msg) => { try { const args = JSON.parse(msg.body); const command = new SendEmailCommand({ Source: (args.senderEmailAddr || process.env.DEFAULT_SENDER_ADDRESS), Destination: { ToAddresses: [args.recipientEmailAddr] }, Message: { Body: { Text: { Data: args.emailContents } }, Subject: { Data: args.subject }, }, }); const resp = await sesClient.send(command); console.log('++++++++++++++++++++++++++++++++'); console.log(`Email send response ${JSON.stringify(resp)}`); return resp; } catch (err) { console.log(`Failed to send email - ${err}`); throw err; // 可选:如果需要捕获失败的Promise } }); // 等待所有邮件发送任务完成 await Promise.all(sendPromises); };
额外优化说明
- 日志中输出
resp时,建议用JSON.stringify(resp),否则直接打印对象会显示[object Object],看不到具体内容。 - 如果需要处理SQS消息的删除逻辑,确保邮件发送成功后再手动删除消息(如果Lambda的触发配置不是自动删除的话)。
内容的提问来源于stack exchange,提问作者satyendra
相关产品推荐
相关产品推荐

