通过Lambda转发S3原始邮件至SES时遇byteLength未定义错误
问题解决:SES SendRawEmail 报 byteLength 错误且邮件变纯文本
错误原因
Cannot read properties of undefined (reading 'byteLength'):SES的SendRawEmailCommand要求RawMessage.Data必须是二进制类型(Node.js环境为Buffer,边缘/浏览器环境为Uint8Array),你之前将S3中的原始邮件转成字符串直接传入,SES无法读取字符串的byteLength属性,因此触发报错。- 转数组后邮件变纯文本:直接将字符串转成普通数组破坏了原始邮件的MIME多部分编码结构,导致SES无法解析富文本、附件等格式,只能按纯文本处理。
解决方案
核心思路:保留原始邮件的二进制编码完整性,修改邮件头时先转成字符串修改,再转回二进制格式传入SES。
修改后的完整代码
import { s3 } from "./libs/s3Client.mjs"; import { GetObjectCommand } from "@aws-sdk/client-s3"; import { ses } from "./libs/sesClient.mjs"; import { SendRawEmailCommand } from "@aws-sdk/client-ses"; // 修改getObject函数,返回Buffer而非字符串 const getObject = async (Bucket, Key) => { const getObjectCommand = new GetObjectCommand({ Bucket, Key }); const response = await s3.send(getObjectCommand); // 将S3响应流转换为Buffer const chunks = []; for await (const chunk of response.Body) { chunks.push(chunk); } return Buffer.concat(chunks); }; export const handler = async (event) => { const msgInfo = JSON.parse(event.Records[0].Sns.Message); console.log(msgInfo); const action = msgInfo.receipt.action; // 获取原始邮件的Buffer let rawMailBuffer = await getObject(action.bucketName, action.objectKey); // 将Buffer转成utf-8字符串,修改From头 let rawMailStr = rawMailBuffer.toString('utf-8'); rawMailStr = rawMailStr.replace(/From: .*/, 'From: <some other email>'); // 将修改后的字符串转回Buffer const modifiedMailBuffer = Buffer.from(rawMailStr, 'utf-8'); // 传入Buffer类型的Data const sendRawEmailCommand = new SendRawEmailCommand({ RawMessage: { Data: modifiedMailBuffer }, Destinations: ['some-other-destination'] }); const response = await ses.send(sendRawEmailCommand); console.log(response); };
关键修改点说明
getObject返回Buffer:S3存储的原始邮件是二进制格式,直接读取为Buffer可完整保留MIME编码信息,避免转字符串时丢失编码细节。- 修改时转字符串再转回Buffer:先将Buffer转成utf-8字符串修改From头,再转回Buffer,既满足修改需求,又保证SES能正确识别邮件的MIME结构,同时符合
SendRawEmailCommand对数据类型的要求。 - 避免直接转普通数组:使用
Buffer.from()生成标准二进制Buffer,而非普通数组,确保SES能解析邮件的多部分内容(如富文本、附件等)。
内容的提问来源于stack exchange,提问作者Shawn-Ross
相关产品推荐
相关产品推荐

