如何使用 Lambda 将 Amazon SES 电子邮件的 Amazon SNS 通知存储于 DynamoDB 中?
上次更新日期:2022 年 11 月 10 日
我使用 Amazon Simple Email Service (Amazon SES) 接收有关通过 Amazon Simple Notification Service (Amazon SNS) 发送的电子邮件的通知。如何设置 AWS Lambda 函数,以便将这些通知存储于 Amazon DynamoDB 表中?
解决方法
注意:以下示例 Lambda 函数可用作向客户关系管理 (CRM) 系统或其他目标写入数据的模板。
(先决条件)设置 Amazon SES 电子邮件或域,使其具有配置为接收来自 Amazon SES 的通知的 Amazon SNS 主题。
有关更多信息,请参阅使用 Amazon SNS 接收 Amazon SES 通知。
创建 DynamoDB 表
1. 在 DynamoDB 中创建一个表,使其具有以下属性:
对于 Table-name,输入 SESNotifications。
对于主分区键,输入 SESMessageId。
对于主排序键,输入 SnsPublishTime。
2. 要允许 Lambda 查询表和创建 Amazon SES 报告,请设置以下二级索引:
索引名称 | 分区键 | 排序键 |
---|---|---|
SESMessageType-Index | SESMessageType (String) | SnsPublishTime (String) |
SESMessageComplaintType-Index | SESComplaintFeedbackType (String) | SnsPublishTime (String) |
注意:您可以根据需要添加更多二级索引。
有关在 DynamoDB 中创建表的信息,请参阅 Amazon DynamoDB 入门。
向 Lambda 函数的 IAM 角色添加权限,使其能够调用 DynamoDB 表
创建新的 AWS Identity and Access Management (IAM) 角色。通过执行以下操作配置角色,以允许 Lambda 函数调用 DynamoDB:PutItem API:
注意:最佳实践是为不同的 Lambda 函数创建和使用新的 IAM 角色。避免在多个函数中重用角色。
1. 在 IAM 控制台的左侧导航窗格中,选择 Roles(角色)。
2. 选择 Create Role(创建角色)。
3. 对于 Select type of trusted entity (选择受信任实体的类型),选择 AWS 服务。
4. 对于 Choose a use case(选择使用案例),请选择 Lambda。选择 Next: Permissions(下一步:权限)。
5. 对于 Attach permissions policies(附加权限策略),请选择 AWSLambdaBasicExecutionRole 托管策略旁边的复选框。然后,选择 Next: Tags(下一步:标签)。
6. (可选)为您的使用案例向角色添加 IAM 标签。有关更多信息,请参阅标记 IAM 资源。
7. 选择下一步: 检查。
8. 对于 Role name*(角色名称*),输入 lambda_ses_execution。
9. 选择 Create Role(创建角色)。
10. 返回 IAM Roles(IAM 角色)并选择您创建的角色。
11. 从Permissions(权限)选项卡中,选择 Add inline policy(添加内联策略)。
12. 在 Visual editor(可视化编辑器)选项卡中,选择 Choose a service(选择服务)。
13. 选择 DynamoDB。
14. 在 Actions(操作)搜索字段中,输入 PutItem。在出现的下拉列表中,选中 PutItem 旁边的复选框。
15. 对于 Resources(资源),选择 Specific(特定)。
16. 选择 Add ARN(添加 ARN)。然后,在出现的文本框中,输入 DynamoDB 表的 Amazon Resource Name (ARN)。
17. 选择 Review policy(查看策略)。
18. 在 Name(名称)中,为策略输入名称。
19. 选择 Create policy(创建策略)。
授予对 DynamoDB 表的访问权限的内联 IAM 策略示例
------------------------IAM Policy Begins---------------------------
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1428510662000",
"Effect": "Allow",
"Action": [
"DynamoDB:PutItem"
],
"Resource": [
"arn:aws:DynamoDB:us-east-1:12345678912:table/SESNotifications"
]
}
]
}
------------------------IAM Policy Ends-----------------------------
创建一个 Lambda 函数以处理 Amazon SES 和 Amazon SNS 通知
使用以下示例函数代码创建 Lambda 函数,然后将其命名为 sesnotificationscode。
重要提示:请确保为函数分配创建的 lambda_ses_execution 角色。
示例 Lambda 函数代码,用于检查 Amazon SNS 通知并将关联的 Amazon SES 通知置于 DynamoDB 表中
重要提示:将 TableName 参数 SESNotifications 替换为您的 DynamoDB 表名称。
--------------------------Lambda Code Begins------------------------
console.log("Loading event");
var aws = require("aws-sdk");
var ddb = new aws.DynamoDB({ params: { TableName: "SESNotifications" } });
exports.handler = function (event, context, callback) {
console.log("Received event:", JSON.stringify(event, null, 2));
var SnsPublishTime = event.Records[0].Sns.Timestamp;
var SnsTopicArn = event.Records[0].Sns.TopicArn;
var SESMessage = event.Records[0].Sns.Message;
SESMessage = JSON.parse(SESMessage);
var SESMessageType = SESMessage.notificationType;
var SESMessageId = SESMessage.mail.messageId;
var SESDestinationAddress = SESMessage.mail.destination.toString();
var LambdaReceiveTime = new Date().toString();
if (SESMessageType == "Bounce") {
var SESreportingMTA = SESMessage.bounce.reportingMTA;
var SESbounceSummary = JSON.stringify(SESMessage.bounce.bouncedRecipients);
var itemParams = {
Item: {
SESMessageId: { S: SESMessageId },
SnsPublishTime: { S: SnsPublishTime },
SESreportingMTA: { S: SESreportingMTA },
SESDestinationAddress: { S: SESDestinationAddress },
SESbounceSummary: { S: SESbounceSummary },
SESMessageType: { S: SESMessageType },
},
};
ddb.putItem(itemParams, function (err, data) {
if (err) {
callback(err)
} else {
console.log(data);
callback(null,'')
}
});
} else if (SESMessageType == "Delivery") {
var SESsmtpResponse1 = SESMessage.delivery.smtpResponse;
var SESreportingMTA1 = SESMessage.delivery.reportingMTA;
var itemParamsdel = {
Item: {
SESMessageId: { S: SESMessageId },
SnsPublishTime: { S: SnsPublishTime },
SESsmtpResponse: { S: SESsmtpResponse1 },
SESreportingMTA: { S: SESreportingMTA1 },
SESDestinationAddress: { S: SESDestinationAddress },
SESMessageType: { S: SESMessageType },
},
};
ddb.putItem(itemParamsdel, function (err, data) {
if (err) {
callback(err)
} else {
console.log(data);
callback(null,'')
}
});
} else if (SESMessageType == "Complaint") {
var SESComplaintFeedbackType = SESMessage.complaint.complaintFeedbackType;
var SESFeedbackId = SESMessage.complaint.feedbackId;
var itemParamscomp = {
Item: {
SESMessageId: { S: SESMessageId },
SnsPublishTime: { S: SnsPublishTime },
SESComplaintFeedbackType: { S: SESComplaintFeedbackType },
SESFeedbackId: { S: SESFeedbackId },
SESDestinationAddress: { S: SESDestinationAddress },
SESMessageType: { S: SESMessageType },
},
};
ddb.putItem(itemParamscomp, function (err, data) {
if (err) {
callback(err)
} else {
console.log(data);
callback(null,'')
}
});
}
};
------------------------Lambda Code Ends----------------------------
为一个或多个 Amazon SNS 主题订阅 Lambda 函数
要使用 Amazon SNS 控制台为 Amazon SNS 主题订阅函数
必须手动向函数资源策略添加权限,以允许 SNS 调用该函数。您可以使用以下 AWS CLI 命令添加这些权限:
aws lambda add-permission --function-name my-function --action lambda:InvokeFunction --statement-id sns-my-topic \<br>--principal sns.amazonaws.com --source-arn arn:aws:sns:us-east-1:123456789012:my-topic
注意:一定要将数值 my-function、sns-my-topic 和 arn:aws:sns:us-east-1:123456789012:my-topic 替换为您的函数、主题和完整 ARN 的 ID。
添加必要权限后,请按照以下步骤将您的函数订阅到 SNS 主题。
1. 在 Amazon SNS 控制台的左侧导航窗格中,选择 Topics(主题)。
2. 确定 Amazon SES 中用于退回通知的 SNS 主题。例如,名为 ses_notifications_repo 的 SNS 主题。
3. 选择 SNS 主题的 ARN。此时将打开 Topic Details(主题详细信息)页面。
4. 选择 Create Subscription(创建订阅)。
5. 在 Protocol(协议)中,选择 AWS Lambda。
6. 对于 Endpoint(端点),请输入 Lambda 函数的 ARN。
7. 选择 Create Subscription(创建订阅)。
8. (可选)对每个想要订阅函数的其他通知主题,请重复执行步骤 1-7。
要使用 Lambda 控制台为 Amazon SNS 主题订阅函数
1. 打开 Lambda 控制台中的函数页面。
2. 选择您之前创建的 Lambda 函数。
3. 在 Function overview(函数概览)窗格中,选择 +Add trigger(+添加触发器)按钮。
4. 在 Trigger configuration(触发器配置)下拉列表中,选择 SNS。此时将显示配置面板。
5. 在 SNS topic(SNS 主题)下拉列表中,选择要订阅函数的 SNS 主题。
6. 选择添加。
7. (可选)对每个想要订阅函数的其他通知主题,请重复执行步骤 1-6。
通过发送 Amazon SES 邮件来调用 Lambda 函数以测试设置
要发送测试 Amazon SES 消息,请使用可用邮箱模拟器地址之一。
注意:发送测试消息时使用邮箱模拟器地址之一可以避免对 SES 送达率指标产生负面影响。
发送测试消息时,Amazon SES 会向 SNS 主题发布通知。然后,Amazon SNS 会将此通知作为 SNS 事件对象中的 JSON 转义 SES 事件通知对象,传送给 Lambda。
要使用 Lambda 控制台创建用于本地测试的示例事件,请参阅 Amazon SES 发布到 Amazon SNS 的事件数据示例。
重要提示:您无法使用 Amazon SES 向 Amazon SNS 发布的事件数据示例,因为它们是专为在 Lambda 控制台中发送测试消息而编写的。要在测试台中使用示例进行测试,您必须将 eventType 消息密钥更改为 notificationType。如果不更改消息密钥,则测试将会失败。
从 DynamoDB 下载报告来查看 Amazon SES 通知
要对 DynamoDB 表的内容进行查询、排序以及下载为 CSV 文件,请执行以下操作:
1. 在 DynamoDB 控制台中,选择 SESNotifications 表。
2. 选择 Items(项目)选项卡。
3. 创建 Query(查询)或 Scan(扫描)搜索。有关更多信息,请参阅查询和扫描数据的最佳实践。
注意:您可以使用 DynamoDB 表导出来安排定期将文件下载到 Amazon Simple Storage Service (Amazon S3) 存储桶。有关更多信息,请参阅 DynamoDB 数据导出到 Amazon S3:工作原理。