如何使用 Lambda 在 DynamoDB 中存储与 Amazon SES 电子邮件有关的 Amazon SNS 通知?

4 分钟阅读
0

对于通过 Amazon Simple Email Service(Amazon SES)发送的电子邮件,我使用 Amazon Simple Notification Service(Amazon SNS)来接收相关通知。我想创建一个 AWS Lambda 函数,将这些通知存储在 Amazon DynamoDB 表中。

解决方法

**注意:**以下步骤中的代码示例仅适用于 Node.js 版本 16.x 及更早版本的 Lambda 运行时系统。

(先决条件)使用配置为接收来自 Amazon SES 的通知的 Amazon SNS 主题来设置 Amazon SES 电子邮件或域

有关详细信息,请参阅 使用 Amazon SNS 接收 Amazon SES 通知

创建 DynamoDB 表

1.    在 DynamoDB 中创建一个具有以下属性的表:
Table-name 中输入 SESNotifications
在主分区键中输入 SESMessageId
在主排序键中输入 SnsPublishTime

2.    若要允许 Lambda 查询表并创建 Amazon SES 报告,请设置以下二级索引

索引名称分区键排序键
SESMessageType-IndexSESMessageType(字符串)SnsPublishTime(字符串)
SESMessageComplaintType-IndexSESComplaintFeedbackType(字符串)SnsPublishTime(字符串)

**注意:**您可以根据需要添加更多二级索引。

有关在 DynamoDB 中创建表的信息,请参阅创建 DynamoDB 表

为 Lambda 函数的 IAM 角色添加权限,使其能够调用 DynamoDB 表

创建一个新的 AWS Identity and Access Management(IAM)角色。配置角色以允许您的 Lambda 函数调用 DynamoDB:PutItem API

**注意:**最佳做法是为不同的 Lambda 函数创建和使用新的 IAM 角色。避免在多个函数中重复使用角色。

1.    在 IAM 控制台的导航窗格中,选择角色

2.    选择创建角色

3.    为选择可信实体类型选择 AWS 服务

4.    为选择用例选择 Lambda。然后,选择下一步: 权限

5.    对于附加权限策略,勾选 AWSLambdaBasicExecutionRole 托管策略旁边的复选框。然后,选择下一步: 标签

6.    (可选)为您的用例向角色添加 IAM 标签。有关详细信息,请参阅标记 IAM 资源

7.    选择下一步: 审查

8.    为**角色名称\ *** 输入 lambda_ses_execution

9.    选择创建角色

10.    返回 IAM 角色视图,然后选择您创建的角色。

11.    在权限选项卡中,选择添加内联策略

12.    在视觉编辑器选项卡中,选择选择服务

13.    选择 DynamoDB

14.    在操作搜索字段中,输入 PutItem。在显示的下拉列表中,勾选 PutItem 旁边的复选框。

15.    为资源选择特定

16.    选择添加 ARN。然后,在显示的文本框中,输入您的 DynamoDB 表的 Amazon 资源名称(ARN)

17.    选择查看策略

18.    在名称中,输入策略的名称。

19.    选择创建策略

授予对 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 通知

使用以下示例函数代码创建名为 sesnotificationscodeLambda 函数。您可以将以下示例 Lambda 函数用作模板,向客户关系管理(CRM)系统或其他目标写入数据。

**重要事项:**确保为该函数分配 lambda_ses_execution 角色。

示例 Lambda 函数代码,用于检查 Amazon SNS 通知并将关联的 Amazon SES 通知置于 DynamoDB 表中

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,'')
      }
    });
  }
};

**注意:**将 TableName 参数 SESNotifications 替换为您的 DynamoDB 表的名称。

为您的 Lambda 函数订阅一个或多个 Amazon SNS 主题

使用 Amazon SNS 控制台

必须手动向函数资源策略添加权限,以允许 SNS 调用该函数。若要添加这些权限,请运行以下 AWS CLI 命令:

**注意:**如果您在运行 AWS CLI 命令时收到错误,请确保您使用的是最新版本的 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-functionsns-my-topicarn:aws:sns:us-east-1:123456789012:my-topic 的值替换为您的函数、主题和完整 ARN 的 ID。

在添加必要权限后完成以下步骤,以便为您的函数订阅 SNS 主题。

1.    在 Amazon SNS 控制台的导航窗格中,选择主题

2.    确定 Amazon SES 中用于退回通知的 SNS 主题。例如: 一个名为 ses_notifications_repo 的 SNS 主题。

3.    选择 SNS 主题的 ARN。随即将打开主题详细信息页面。

4.    选择创建订阅

5.    为协议选择 AWS Lambda

6.    在端点中输入您的 Lambda 函数的 ARN。

7.    选择创建订阅

8.    (可选)对希望函数订阅的其他每个通知主题重复步骤 1-7。

使用 Lambda 控制台

1.    在 Lambda 控制台中打开函数页面

2.    选择您创建的 Lambda 函数。

3.    在函数概述窗格上,选择 +添加触发器

4.    在触发器配置下拉列表中,选择 SNS。随即将出现一个配置面板。

5.    在 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 的事件数据示例

**重要事项:**您不能使用这些事件数据示例,因为它们是为在 Lambda 控制台中发送测试消息而编写的。若要在 Lambda 控制台中使用示例进行测试,必须将 eventType 消息键更改为 notificationType。如果您不更改消息键,则测试将会失败。

从 DynamoDB 下载报告以查看 Amazon SES 通知

要查询、排序 DynamoDB 表的内容并将其下载为.csv 文件,请完成以下步骤:

1.    打开 DynamoDB 控制台,然后选择 SESNotifications 通知表。

2.    选择项目选项卡。

3.    创建查询扫描搜索。有关详情信息,请参阅查询和扫描数据的最佳实践

**注意:**您可以使用 DynamoDB 表导出定期将文件下载到 Amazon Simple Storage Service(Amazon S3)存储桶。有关详细信息,请参阅 DynamoDB 数据导出到 Amazon S3:工作原理

相关信息

Lambda 函数的扇出

通过 Amazon SNS 调用 AWS Lambda 函数

使用 Amazon SNS 接收 Amazon SES 通知

AWS 官方
AWS 官方已更新 1 年前