如何使用AWS的SES服务发送邮件和40M的附件

背景介绍

SMTP协议

SMTP(Simple Mail Transfer Protocol):简单邮件传送协议

  • STMP端口号为25, 使用TCP建立连接.
  • SMTP限于传送7位的ASCII码

MIME协议

MIME (Multipurpose Internet Mail Extension)

flowchart LR A1[user1] <-- 不止7位ASCII码 --> B1[MIME] B1 <-- 7位ASCII码 --> C1[SMTP] C1 <-- 7位ASCII码 --> C2[SMTP] C2 <-- 7位ASCII码 --> B2[MIME] B2 <-- 不止7位ASCII码 --> A2[user2]

前置条件

  1. 首先要有一个AWS的账户,并且SES服务可以正常使用。
  2. 在SES服务中,提前verified 要使用的email

Overview

SES的三种发送邮件的方式

SES本身有三种发送邮件的方式,如下图所示:

flowchart LR SES --> B1["1. 直接发送邮件内容"] SES --> B2["2. 发送邮件内容和附件,包括但不限于 txt,csv,pdf,image..."] SES --> B3["3. 使用template发送邮件"]

在这里,我们主要讨论的是带附件的邮件的发送。

SES V1 和 V2 对于附件大小的限制

ses v1 ses v2
附件大小的限制 10M 40M

附件类型的定义

  • Content-Type: application/octet-stream ===> attachment.pdf
  • Content-Type: application/json ===> attachment.json
  • Content-Type: application/msword ===>attachment.docx
  • Content-Type: text/plain ===> attachment.txt

方法一: 使用AWS SES V1版本发送邮件和附件

使用 ses v1 发送邮件和附件,附件的限制大小是 10M.

1. 定义 payload

  • 使用 boundary 来分割大文件部分
  • boundary 可以级联 sub boundary
js 复制代码
// define file
let file = fs.readFileSync('./src/util/testData.csv',
    {encoding:'base64', flag:'r'}
);

// define payload
const payload = `From: ${email}
To: ${email}
Subject: Customer service contact info
Content-Type: multipart/mixed;
    boundary="a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a"

--a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a
Content-Type: multipart/alternative;
    boundary="sub_a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a"

--sub_a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable

Please see the attached file for a list of customers to contact.

--sub_a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a
Content-Type: text/html; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable

<html>
<head></head>
<body>
<h1>Hello!</h1>
<p>Please see the attached file for a list of customers to contact.</p>
</body>
</html>

--sub_a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a--

--a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a
Content-Type: text/plain; name="attachment.csv"
Content-Description: attachment.csv
Content-Disposition: attachment;filename="attachment.csv";
    creation-date="Sat, 05 Aug 2017 19:35:36 GMT";
Content-Transfer-Encoding: base64

${file}

--a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a--
`;

2.发送邮件

js 复制代码
import * as AWS from "@aws-sdk/client-ses";
import fs from "fs";
const client = new AWS.SES();

const email = "test@test.com.cn";

(async () => {
    const params = {
        RawMessage: {
            Data: Buffer.from(payload)
        },
        Source: email,
        Destinations: [],
    };

    try {
        return await client.sendRawEmail(params);
    } catch (e) {
        console.error(e);
        console.error("Failed to send email.");
        return e;
    }
})();

方法二: 使用AWS SES V2版本发送邮件和附件

使用 ses v2 发送邮件和附件,附件的限制大小是 40M.

实现代码

js 复制代码
import fs from "fs";
import { SESv2Client, SendEmailCommand } from "@aws-sdk/client-sesv2"
const client = new SESv2Client();

const email = "test@test.com.cn";

let file = fs.readFileSync('./src/util/testData.csv',
    {encoding:'base64', flag:'r'}
);

const payload = `From: ${email}
To: ${email}
Subject: Customer service contact info
Content-Type: multipart/mixed;
    boundary="a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a"

--a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a
Content-Type: multipart/alternative;
    boundary="sub_a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a"

--sub_a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable

Please see the attached file for a list of customers to contact.

--sub_a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a
Content-Type: text/html; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable

<html>
<head></head>
<body>
<h1>Hello!</h1>
<p>Please see the attached file for a list of customers to contact.</p>
</body>
</html>

--sub_a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a--

--a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a
Content-Type: text/plain; name="attachment.csv"
Content-Description: attachment.csv
Content-Disposition: attachment;filename="attachment.csv";
    creation-date="Sat, 05 Aug 2017 19:35:36 GMT";
Content-Transfer-Encoding: base64

${file}

--a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a--
`;


(async () => {
    const command = new SendEmailCommand({
        Content: {
            Raw: {
                Data: Buffer.from(payload)
            }
        },
        Destination: {
            ToAddresses: [email],
        },
    });

    try {
        return await client.send(command);
    } catch (e) {
        console.error(e);
        console.error("Failed to send email.");
        return e;
    }
})();
相关推荐
I'm Jie2 小时前
深入了解 Vue 3 组件间通信机制
前端·javascript·vue.js
用户90443816324603 小时前
90%前端都踩过的JS内存黑洞:从《你不知道的JavaScript》解锁底层逻辑与避坑指南
前端·javascript·面试
PPPPickup4 小时前
easychat项目复盘---获取联系人列表,联系人详细,删除拉黑联系人
java·前端·javascript
老前端的功夫4 小时前
前端高可靠架构:医疗级Web应用的实时通信设计与实践
前端·javascript·vue.js·ubuntu·架构·前端框架
脾气有点小暴5 小时前
前端页面跳转的核心区别与实战指南
开发语言·前端·javascript
San30.6 小时前
深入 JavaScript 内存机制:从栈与堆到闭包的底层原理
开发语言·javascript·udp
Fantastic_sj6 小时前
Vue3相比Vue2的改进之处
前端·javascript·vue.js
ttod_qzstudio8 小时前
深入理解 TypeScript 数组的 find 与 filter 方法:精准查找的艺术
javascript·typescript·filter·find
冬男zdn8 小时前
优雅处理数组的几个实用方法
前端·javascript
克喵的水银蛇8 小时前
Flutter 通用标签选择组件:TagSelector 支持单选 / 多选
javascript·windows·flutter