如何使用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;
    }
})();
相关推荐
柳杉32 分钟前
震惊!字符串还能这么玩!
前端·javascript
仍然.1 小时前
算法题目---模拟
java·javascript·算法
我命由我123453 小时前
React - 类组件 setState 的 2 种写法、LazyLoad、useState
前端·javascript·react.js·html·ecmascript·html5·js
聊聊MES那点事3 小时前
JavaScript图表控件AG Charts使用教程:使用AG Charts React实时更新柱状图
开发语言·javascript·react.js·图表控件
亚马逊云开发者3 小时前
在 IDEA 里装个 AI 助手:Amazon Q Developer 到底好不好用?
aws
斯班奇的好朋友阿法法4 小时前
离线ollama导入Qwen3.5-9B.Q8_0.gguf模型
开发语言·前端·javascript
莫物5 小时前
vue过滤表格数据导致的索引错乱问题
前端·javascript·vue.js
竹林8185 小时前
从监听失败到实时更新:我在NFT铸造项目中搞定合约事件监听的全过程
前端·javascript
光影少年5 小时前
手写防抖和节流
前端·javascript·前端框架
后藤十八里6 小时前
维普期刊逆向笔记
javascript·笔记·js逆向