如何使用 Lambda 在 DynamoDB 中存储与 Amazon SES 电子邮件有关的 Amazon SNS 通知?
对于通过 Amazon Simple Email Service(Amazon SES)发送的电子邮件,我使用 Amazon Simple Notification Service(Amazon SNS)来接收相关通知。我想创建一个 AWS Lambda 函数,将这些通知存储在 Amazon DynamoDB 表中。
解决方案
**注意:**以下步骤中的代码示例适用于使用 V3 SDK 的 Lambda Node.js 运行时,例如 Node.js 18.x 和 20.x。
**先决条件:**使用配置为接收 Amazon SES 通知的 Amazon SNS 主题来设置 Amazon SES 电子邮件或域。有关详细信息,请参阅 Receiving Amazon SES notifications using Amazon SNS。
创建 DynamoDB 表
在 DynamoDB 中创建表,使其具备以下属性:
- 在 Table-name 中输入 SESNotifications。
- 在主分区键中输入 SESMessageId。
- 在主排序键中输入 SnsPublishTime。
若要允许 Lambda 查询表并创建 Amazon SES 报告,请设置以下二级索引:
索引名称 | 分区键 | 排序键 |
---|---|---|
SESMessageType-Index | SESMessageType(字符串) | SnsPublishTime(字符串) |
SESMessageComplaintType-Index | SESComplaintFeedbackType(字符串) | SnsPublishTime(字符串) |
**注意:**可以根据需要添加更多二级索引。
有关信息,请参阅 Create a DynamoDB table。
为 Lambda 函数的 IAM 角色添加权限,使其能够调用 DynamoDB 表
创建一个新的 AWS Identity and Access Management(IAM)角色。配置角色,允许 Lambda 函数调用 DynamoDB:PutItem API。
**注意:**最佳做法是为不同的 Lambda 函数创建和使用新的 IAM 角色。请勿在多个函数中重复使用角色。
要向 Lambda 函数的 IAM 角色添加权限,请完成以下步骤:
- 打开 IAM 控制台。
- 在导航窗格中,选择角色。
- 选择创建角色。
- 为选择可信实体类型,选择 AWS 服务。
- 为选择用例选择 Lambda。然后,选择下一步: 权限。
- 对于附加权限策略,勾选 AWSLambdaBasicExecutionRole 托管策略旁边的复选框。然后,选择下一步: 标签。
- (可选)向角色添加 IAM 标签。有关详细信息,请参阅 Tagging IAM resources。
- 选择下一步: 审核。
- 为角色名称* 输入 lambda_ses_execution。
- 选择创建角色。
- 返回 IAM 角色,然后选择角色。
- 在权限选项卡上,选择添加内联策略。
- 在可视化编辑器选项卡上,选择**“选择服务”**。
- 选择 DynamoDB。
- 在操作搜索字段中,输入 PutItem。在下拉列表中,选中 PutItem 旁边的复选框。
- 为资源选择特定。
- 选择添加 ARN。然后,在文本框中输入 DynamoDB 表的 ARN。
- 选择查看策略。
- 在名称中输入策略的名称。
- 选择创建策略。
授予对 DynamoDB 表的访问权限的内联 IAM 策略示例:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1428510662000", "Effect": "Allow", "Action": [ "DynamoDB:PutItem" ], "Resource": [ "arn:aws:DynamoDB:us-east-1:12345678912:table/SESNotifications" ] } ] }
创建 Lambda 函数来处理 Amazon SES 和 Amazon SNS 通知
使用以下示例函数代码创建名为 sesnotificationscode 的 Lambda 函数。可以将以下示例 Lambda 函数用作模板,将数据写入客户关系管理(CRM)系统或其他目标。
**重要事项:**为该函数分配 lambda_ses_execution 角色。
console.log("Loading event"); import { DynamoDBClient, PutItemCommand } from "@aws-sdk/client-dynamodb"; const client = new DynamoDBClient({}); export const handler = async (event) => { 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 = { TableName: "SESNotifications", Item: { SESMessageId: { S: SESMessageId }, SnsPublishTime: { S: SnsPublishTime }, SESreportingMTA: { S: SESreportingMTA }, SESDestinationAddress: { S: SESDestinationAddress }, SESbounceSummary: { S: SESbounceSummary }, SESMessageType: { S: SESMessageType }, }, }; const command = new PutItemCommand(itemParams); try { const response = await client.send(command); console.log("Put Item Response Bounce: ", response); } catch (err) { console.log("Error", err); } } else if (SESMessageType == "Delivery") { var SESsmtpResponse1 = SESMessage.delivery.smtpResponse; var SESreportingMTA1 = SESMessage.delivery.reportingMTA; var itemParamsdel = { TableName: "SESNotifications", Item: { SESMessageId: { S: SESMessageId }, SnsPublishTime: { S: SnsPublishTime }, SESsmtpResponse: { S: SESsmtpResponse1 }, SESreportingMTA: { S: SESreportingMTA1 }, SESDestinationAddress: { S: SESDestinationAddress }, SESMessageType: { S: SESMessageType }, }, }; const commanddel = new PutItemCommand(itemParamsdel); try { const responsedel = await client.send(commanddel); console.log("Put Item Response Delivery: ", responsedel); } catch (err) { console.log("Error", err); } } else if (SESMessageType == "Complaint") { var SESComplaintFeedbackType = SESMessage.complaint.complaintFeedbackType; var SESFeedbackId = SESMessage.complaint.feedbackId; var itemParamscomp = { TableName: "SESNotifications", Item: { SESMessageId: { S: SESMessageId }, SnsPublishTime: { S: SnsPublishTime }, SESComplaintFeedbackType: { S: SESComplaintFeedbackType }, SESFeedbackId: { S: SESFeedbackId }, SESDestinationAddress: { S: SESDestinationAddress }, SESMessageType: { S: SESMessageType }, }, }; const commandcomp = new PutItemCommand(itemParamscomp); try { const responsecomp = await client.send(commandcomp); console.log("Put Item Response complaint: ", responsecomp); } catch (err) { console.log("Error", err); } } };
**注意:**将 TableName 参数 SESNotifications 替换为 DynamoDB 表的名称。
为 Lambda 函数订阅一个或多个 Amazon SNS 主题
可以使用 Amazon SNS 控制台或 Lambda 控制台为 Lambda 函数订阅一个或多个 Amazon SNS 主题。
Amazon SNS 控制台
**注意:**如果在运行 AWS 命令行界面 (AWS CLI) 命令时遇到错误,请参阅排查 AWS CLI 错误。此外,确保您使用的是最新版本的 AWS CLI。
必须手动向函数资源策略添加权限,允许 SNS 调用该函数。运行 add-permission AWS CLI 命令:
aws lambda add-permission --function-name my-function --action lambda:InvokeFunction --statement-id sns-my-topic \\ \--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 主题,请完成以下步骤:
- 打开 Amazon SNS 控制台。
- 在导航窗格中,选择主题。
- 确定 Amazon SES 中用于退回通知的 SNS 主题。例如: 一个名为 ses_notifications_repo 的 SNS 主题。
- 选择 SNS 主题的 ARN。
- 选择创建订阅。
- 为协议选择 AWS Lambda。
- 在端点中输入 Lambda 函数的 ARN。
- 选择创建订阅。
- (可选)对要订阅函数的每个通知主题重复前面的步骤。
Lambda 控制台
要使用 Lambda 控制台为 Lambda 函数订阅一个或多个 SNS 主题,请完成以下步骤:
- 打开 Lambda 控制台。
- 在导航窗格中,选择函数。
- 选择您的 Lambda 函数。
- 在函数概述窗格上,选择 +添加触发器。
- 在触发器配置下拉列表中,选择 SNS。
- 在 SNS 主题下拉列表中,选择 SNS 主题。
- 选择添加。
- (可选)对要订阅函数的每个通知主题重复前面的步骤。
测试设置
若要发送测试 Amazon SES 消息,请使用一个可用的邮箱模拟器地址。
**注意:**发送测试消息时,使用其中一个邮箱模拟器地址可以防止对您的 SES 送达率指标产生负面影响。
发送测试消息时,Amazon SES 会向 SNS 主题发布通知。然后,Amazon SNS 会在 SNS 事件对象中将通知作为 JSON 转义的 SES 事件通知对象传送到 Lambda。
要使用 Lambda 控制台为本地测试创建示例事件,请参阅 Amazon SES 发布到 Amazon SNS 的事件数据示例。
**重要事项:**不能使用这些事件数据示例,因为这些示例是为在 Lambda 控制台中发送测试消息而编写的。必须将 eventType 消息密钥更改为 notificationType。如果不更改消息键,则测试将会失败。
从 DynamoDB 下载报告以查看 Amazon SES 通知
要查询、排序 DynamoDB 表的内容并将其下载为 .csv 文件,请完成以下步骤:
- 打开 DynamoDB 控制台。
- 选择 SESNotifications 表。
- 选择项目选项卡。
- 创建查询或扫描搜索。有关详情信息,请参阅 Best practices for querying and scanning data。
**注意:**可以使用 DynamoDB 表导出功能,定期将文件下载到 Amazon Simple Storage Service(Amazon S3)存储桶。有关详细信息,请参阅 DynamoDB 数据导出到 Amazon S3:工作原理。
相关信息
相关内容
- AWS 官方已更新 2 年前
- AWS 官方已更新 4 年前
- AWS 官方已更新 2 年前
- AWS 官方已更新 1 年前