You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在NestJS中使用AWS SES同时发送PDF附件与HTML模板邮件

在NestJS中使用AWS SES同时发送HTML模板邮件与PDF附件

AWS SES的sendTemplatedEmail确实不支持直接添加附件,要同时实现HTML模板渲染和PDF附件,你需要用sendRawEmail方法,自己构建包含渲染后HTML内容和附件的MIME格式邮件。下面是具体实现步骤和代码示例:

实现步骤

  • 先渲染你的HTML模板为最终的HTML字符串
  • 构建符合MIME标准的邮件内容,包含HTML正文、PDF附件、发件人/收件人/主题等信息
  • 调用SES的sendRawEmail接口发送邮件

代码示例

1. 模板渲染(以Handlebars为例)

先安装依赖:

npm install handlebars @nestjs/handlebars

在NestJS模块中配置Handlebars:

import { Module } from '@nestjs/common';
import { HandlebarsAdapter } from '@nestjs-modules/mailer/dist/adapters/handlebars.adapter';
import { MailerModule } from '@nestjs-modules/mailer';
import { join } from 'path';

@Module({
  imports: [
    MailerModule.forRoot({
      defaults: {
        from: '"Your App" <your-email@example.com>',
      },
      template: {
        dir: join(__dirname, 'templates'),
        adapter: new HandlebarsAdapter(),
        options: {
          strict: true,
        },
      },
    }),
  ],
})
export class MailModule {}

在Service中封装模板渲染逻辑:

import { Injectable } from '@nestjs/common';
import { MailerService } from '@nestjs-modules/mailer';

@Injectable()
export class TemplateRenderService {
  constructor(private readonly mailerService: MailerService) {}

  async render(templateName: string, context: any): Promise<string> {
    return this.mailerService.render(templateName, context);
  }
}

2. 构建MIME邮件内容并发送

使用nodemailer来构建MIME消息(比手动拼接更可靠),先安装依赖:

npm install nodemailer aws-sdk

在Service中实现核心发送逻辑:

import { Injectable } from '@nestjs/common';
import { SES } from 'aws-sdk';
import * as nodemailer from 'nodemailer';
import { TemplateRenderService } from './template-render.service';

@Injectable()
export class SesEmailService {
  private ses: SES;

  constructor(private readonly templateRender: TemplateRenderService) {
    this.ses = new SES({
      region: 'your-aws-region', // 如us-east-1
      accessKeyId: process.env.AWS_ACCESS_KEY_ID,
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
    });
  }

  async sendTemplatedWithAttachment(
    to: string[],
    subject: string,
    templateName: string,
    templateContext: any,
    pdfBuffer: Buffer,
    pdfFileName: string,
  ) {
    // 1. 渲染HTML模板
    const htmlContent = await this.templateRender.render(templateName, templateContext);

    // 2. 用nodemailer生成MIME格式字符串
    const transporter = nodemailer.createTransport({
      SES: { ses: this.ses, aws: require('aws-sdk') },
    });

    const rawMessage = await transporter.sendMail({
      from: '"Your App" <your-email@example.com>',
      to,
      subject,
      html: htmlContent,
      attachments: [
        {
          filename: pdfFileName,
          content: pdfBuffer,
          contentType: 'application/pdf',
        },
      ],
      raw: true, // 仅生成MIME内容,不实际发送
    });

    // 3. 调用SES的sendRawEmail接口发送
    const params = {
      RawMessage: {
        Data: rawMessage,
      },
    };

    return this.ses.sendRawEmail(params).promise();
  }
}

3. 使用示例(搭配PDF生成)

假设用pdfkit生成PDF:

import { Injectable } from '@nestjs/common';
import { SesEmailService } from './ses-email.service';
import * as PDFDocument from 'pdfkit';

@Injectable()
export class InvoiceService {
  constructor(private readonly sesEmail: SesEmailService) {}

  async sendCustomerInvoice(to: string) {
    // 生成PDF Buffer
    const pdfBuffer = await this.generateInvoicePdf();

    // 触发邮件发送
    await this.sesEmail.sendTemplatedWithAttachment(
      [to],
      '您的账单已生成',
      'invoice', // templates目录下的invoice.hbs模板
      { userName: 'John Doe', invoiceAmount: 99.99 },
      pdfBuffer,
      '2024-invoice.pdf',
    );
  }

  private async generateInvoicePdf(): Promise<Buffer> {
    return new Promise((resolve) => {
      const doc = new PDFDocument();
      const buffers: Buffer[] = [];
      doc.on('data', buffers.push.bind(buffers));
      doc.on('end', () => resolve(Buffer.concat(buffers)));

      doc.text('Customer Invoice', { align: 'center', size: 16 });
      doc.text(`Name: John Doe`, { marginTop: 20 });
      doc.text(`Amount: $99.99`);
      doc.end();
    });
  }
}

关键说明

  • sendTemplatedEmail仅支持AWS预定义模板,无附件扩展能力,因此必须用sendRawEmail实现混合需求
  • 用nodemailer生成MIME内容可避免手动拼接的格式错误,提升可靠性
  • 确保AWS SES账号已验证发件人邮箱/域名,收件人邮箱处于已验证列表(或账号已脱离沙箱环境)

内容的提问来源于stack exchange,提问作者ashraf ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 05:54:09