AWS SES邮件长度超限及切换SESv2后Nodemailer报错求助
1. 初始错误:消息长度超限
本地用Postman测试负载时,触发AWS SDK for SES的InvalidParameterValue错误,提示「Message length is more than 10485760 bytes long」,报错栈如下:
2023-11-30 13:50:04.482 [error] - [ReqId : 77b1409d-4174-4974-a22a-8f1f1c00a981] : InvalidParameterValue: Message length is more than 10485760 bytes l at throwDefaultError (/mnt/d/Repos/document-engine/node_modules/@smithy/smithy-client/dist-cjs/default-error-handler.js:8:22) at /mnt/d/Repos/document-engine/node_modules/@smithy/smithy-client/dist-cjs/default-error-handler.js:18:39 at de_SendRawEmailCommandError (/mnt/d/Repos/document-engine/node_modules/@aws-sdk/client-ses/dist-cjs/protocols/Aws_query.js:2418:20) at processTicksAndRejections (node:internal/process/task_queues:95:5) at /mnt/d/Repos/document-engine/node_modules/@smithy/middleware-serde/dist-cjs/deserializerMiddleware.js:7:24 at /mnt/d/Repos/document-engine/node_modules/@aws-sdk/middleware-signing/dist-cjs/awsAuthMiddleware.js:14:20 at /mnt/d/Repos/document-engine/node_modules/@smithy/middleware-retry/dist-cjs/retryMiddleware.js:27:46 at /mnt/d/Repos/document-engine/node_modules/@aws-sdk/middleware-logger/dist-cjs/loggerMiddleware.js:7:26 { '$fault': 'client', '$metadata': [Object], Type: 'Sender', Code: 'InvalidParameterValue' } (in message_controller.ts:58) Call Stack: at DSLogger.error (/mnt/d/Repos/document-engine/src/shared/utils/log/logger.ts:101:15) at DSLogService.error (/mnt/d/Repos/document-engine/src/shared/services/log/log.service.ts:91:18) at MessageController.sendEmail (/mnt/d/Repos/document-engine/src/shared/controllers/message_controller.ts:58:20)
2. 切换SESv2后的TypeError
参考帖子改用@aws-sdk/client-sesv2后,触发TypeError:
TypeError: ses.sendRawEmail is not a function at
/mnt/d/Repos/document-engine/node_modules/nodemailer/lib/ses-transport/index.js:267:43
at
/mnt/d/Repos/document-engine/node_modules/nodemailer/lib/ses-transport/index.js:251:43
at processTicksAndRejections (node:internal/process/task_queues:95:5)
[ERROR] 17:54:43 TypeError: ses.sendRawEmail is not a function
当前使用的SESv2配置代码如下:
import { Transporter, createTransport } from 'nodemailer'; import { Attachment } from 'nodemailer/lib/mailer'; import { MailOptions } from 'nodemailer/lib/sendmail-transport'; import { SESv2, SESv2ClientConfig, SendEmailCommand } from '@aws-sdk/client-sesv2'; // import { SES, SESClientConfig, SendRawEmailCommand } from '@aws-sdk/client-ses'; import { BadRequestException, Injectable } from '@nestjs/common'; import { EmailContents } from '@shared/models/mail/mail.content'; import { DSEmailResponseModel } from '@shared/models/response/email_response.model'; import { DSAWSConfig } from '@shared/utils/aws/aws.config'; /** * Utility class to for configuring Node mailer. * * This class uses Amazon SES to send email. * * Note : Do not use this class directly instead use IQEmailService class. * * @export * @class DSMailer */ @Injectable() export class DSMailer extends DSAWSConfig { private transporter: Transporter; /** * Function to configure Node mailer. * * This function throws system error which should be handled by the caller. * * @memberof DSMailer */ configEmail(options: SESv2ClientConfig): void { const ses: any = new SESv2(options); this.transporter = createTransport({ SES: { ses, aws: { SendEmailCommand } } }); this.logService.info('Mailer configured successfully.'); } ...more code... }
解决方案
针对消息长度超限问题
AWS SES的SendRawEmail接口单条消息上限为10MB(10485760字节),解决思路:
- 拆分包含大附件的邮件,分开发送
- 用S3预签名链接替代直接添加大附件,邮件中只放链接
- 检查邮件内容是否有冗余数据(比如重复的HTML内容、过大的内嵌资源),精简后再发送
针对SESv2与Nodemailer适配问题
当前配置的核心错误是传入了SendEmailCommand而非SESv2对应的SendRawEmailCommand,Nodemailer的SES传输层需要这个命令来映射sendRawEmail方法。修正后的配置代码如下:
import { Transporter, createTransport } from 'nodemailer'; import { Attachment } from 'nodemailer/lib/mailer'; import { MailOptions } from 'nodemailer/lib/sendmail-transport'; // 注意导入SESv2的SendRawEmailCommand import { SESv2, SESv2ClientConfig, SendRawEmailCommand } from '@aws-sdk/client-sesv2'; import { BadRequestException, Injectable } from '@nestjs/common'; import { EmailContents } from '@shared/models/mail/mail.content'; import { DSEmailResponseModel } from '@shared/models/response/email_response.model'; import { DSAWSConfig } from '@shared/utils/aws/aws.config'; @Injectable() export class DSMailer extends DSAWSConfig { private transporter: Transporter; configEmail(options: SESv2ClientConfig): void { const ses = new SESv2(options); this.transporter = createTransport({ SES: { ses, aws: { SendRawEmailCommand } // 替换为SendRawEmailCommand } }); this.logService.info('Mailer configured successfully.'); } // ...其他代码 }
额外注意事项:
- 确保
@aws-sdk/client-sesv2和Nodemailer的版本兼容,建议升级到两者的最新稳定版 - 如果修正后仍有问题,可以直接调用SESv2的API发送邮件,绕过Nodemailer传输层,示例逻辑:通过
SendRawEmailCommand构造请求,用SESv2客户端的send方法执行
内容的提问来源于stack exchange,提问作者Antonio Pavicevac-Ortiz

