Sarath が SES の SNS 通知を
DynamoDB に保存する方法を
ご案内します

lambda-sns-ses-dynamodb-sarath

Amazon Simple Email Service (Amazon SES) で送信されてくる E メールのバウンス、苦情、配信に関する通知を受け取るために、Amazon Simple Notification Service (Amazon SNS) を使っています。これらの通知を AWS Lambda を使って Amazon DynamoDB データベースに保存したいと思います。そのための方法を教えてください。

Amazon SNS を通じた Amazon SES 通知を設定したら、AWS Lambda 関数を使用してこれらの通知を DynamoDB データベースに書き込むことができます。そして、これらの通知は DynamoDB データベースから CSV ファイルにダウンロード可能です。

注意: 今回のサンプルで作成された Lambda 関数は、メーリングリストをホストする場所に基づいて CRM などの書き込み先にデータを書き込む際のテンプレートとして使用できます。

Lambda 関数を使用して SES で送られた SNS 通知の内容を DynamoDB データベースに保存するには、以下の一連のステップを完了させます。

  1. DynamoDB テーブルを作成します。
  2. Lambda の IAM ロールの権限を追加して、作成した DynamoDB テーブルに書き込めるようにします。
  3. SES バウンス通知を処理する Lambda 関数を作成します。
  4. Lambda 関数を 1 つ、または複数のトピックにサブスクライブします。
  5. 関数の権限を更新して、関数の起動を SNS に許可します。
  6. Lambda 関数を起動するために SES メッセージを送信して設定をテストします。
  7. DynamoDB からレポートをダウンロードして、SES 通知を表示します。

前提条件

  • DynamoDB データベースに読み取りと書き込み権限を許可します。
  • SES 通知を受け取るように設定された SNS トピックの存在が検証された SES アカウント (E メールまたはドメイン) を設定します。SNS を使用した SES 通知の受け取りの詳細に関しては、Amazon SNS を通じた Amazon SES 通知を参照してください。

1. DynamoDB テーブルを作成する

SESMessageId という名前のプライマリパーティションキーおよび SnsPublishTime という名前のプライマリソートキーを使用して、DynamoDB に SESNotifications という名前のテーブルを作成します。

テーブルのクエリを行い、SES レポートを生成するには、下表に記載された通知タイプおよび苦情タイプのセカンダリインデックスを設定します。インデックスは必要に応じて追加することができます。

インデックス名 パーティションキー ソートキー
SESMessageType-Index SESMessageType (文字列) SnsPublishTime (文字列)
SESMessageComplaintType-Index SESComplaintFeedbackType (文字列) SnsPublishTime (文字列)

DynamoDB におけるテーブル作成の詳細に関しては、DynamoDB の使用開始を参照してください。

2. Lambda の IAM ロールの権限を追加して、DynamoDB テーブルに書き込めるようにする

Lambda 関数が使用するための新しい AWS Identity and Access Management (IAM) ロールを作成します。このロールは、DynamoDB:PutItem API の呼び出しを Lambda 関数に許可する必要があります。

注意: 異なる Lambda 関数には、新しい IAM ロールを作成して使用するのがベストプラクティスです。複数の関数にわたって、ロールを使いまわすのは避けるようにします。

  1. IAM コンソールのナビゲーションペインで、[ロール]、[ロールの作成] の順に選択します。
  2. 信頼されたエンティティの種類に AWS サービスを選択して、[Lambda]、次に [次のステップ: アクセス権限] を選択します。
  3. 管理ポリシー AWSLambdaBasicExecutionRole を選択してから、[次へ] を選択します。
  4. lambda_ses_execution のロールに名前を付与して、ロールの作成を完了させます。
  5. IAM ロールの画面に戻って、ユーザーが作成したロールを選択します。
  6. [インラインポリシーの追加] を選択します。
  7. ビジュアルエディタで、[サービス] として [DynamoDB] を、次に、アクションとして [書き込み] カテゴリの [PutItem] を選択します。リソースで [ARN の追加] を選択し、次に、先に作成した DynamoDB テーブルの ARN を付与します。
  8. [確認] を選択してポリシーの名前を付与し、次に [ポリシーの作成] を選択します。

以下の例では、ステップ 1 で作成した DynamoDB データベースの us-east-1:12345678912:table/SESNotifications へのアクセスを許可するために、lambda_ses_execution ロールに追加されたインラインポリシーのステートメントを示しています。

------------------------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-----------------------------

3. SES バウンス通知を処理する Lambda 関数を作成する

Lambda コンソール を使用して、sesnotificationscode という名前の Lambda 関数を作成します。

関数を作成する際に、ロールとして先に作成した lambda_ses_execution を選択します。

以下のサンプルコードを使用して、新しい関数を設定します。このサンプルコードは、Amazon SES の Amazon SNS 通知の例に記載されている 3 種類の SNS 通知をチェックするとともに、その SES 通知を DynamoDB テーブルに入力します。

注意: 以下のサンプルコードのパラメータ TableName の値 SESNotifications をユーザーのテーブルの名前に置き換えてください。

--------------------------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)
{
  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) { context.fail(err)}
  else {
           console.log(data);
           context.succeed();
      }
  });
}
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) { context.fail(err)}
  else {
          console.log(data);
          context.succeed();
      }
  });
}
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) { context.fail(err)}
  else {
          console.log(data);
          context.succeed();
>      }
  });
}
};
------------------------Lambda Code Ends----------------------------

4. Lambda 関数を 1 つ、または複数のトピックにサブスクライブする

ユーザーが SNS トピックを少なくとも 1 つ作成して、なおかつその SNS トピックを フィードバック通知に使用できるように SES の E メールドメインが設定済みであることを前提として、以下のステップに従います。

  1. SNS コンソールのナビゲーションペインで、[トピック] を選択します。たとえば ses_notifications_repo という名前の SNS トピックのように、バウンス用の SES で使用される SNS トピックを特定します。
  2. SNS トピックの ARN を選択して、トピックの詳細ページを開きます。
  3. [サブスクリプションの作成] を選択します。
  4.     [プロトコル]で、[AWS Lambda] を選択します。
  5. [エンドポイント] で Lambda 関数の ARN を入力し、次に [サブスクリプションの作成] を選択します。これで、Lambda をプロトコルとし、また Lambda 関数の ARN をエンドポイントとしたサブスクリプションが作成されます。

5. 関数の権限を更新して、関数の起動を SNS に許可する

前のステップでトピックに Lambda のサブスクリプションを作成する際に SNS コンソールを使用しなかった場合は、Lambda コンソールを使用してトリガーを手動で作成することができます。

  1. その関数については Lambda コンソールで、Designer のトリガーリストから SNS トリガーを追加します。設定パネルは Designer の下に表示されます。
  2. 設定パネルのドロップダウンリストからトピックを選択します。

この手順を繰り返して、この Lambda 関数をサブスクライブしたい別の通知トピックを追加します。

6. Lambda 関数を起動するために SES メッセージを送信して設定をテストする

これで Lambda 関数が SNS トピックにサブスクライブされました。次に SES メッセージを発行して、Lambda コンソールにおいて Lambda 関数の起動を観察します。SES コンソールを使用して、テストメッセージを送信することができます。

テストメッセージを送信するには、メールボックスシミュレーターで使用可能なアドレスの 1 つを使用して、ユーザーの配信性能メトリクスに対する悪影響を回避することができます。詳細に関しては、Amazon SES での E メール送信のテストを参照してください。

SES メッセージが送信されたら、SES は SNS トピックに対する通知を発行します。SNS はこの通知を Lambda に対し、SNS イベントオブジェクトにおける JSON エスケープした SES イベント通知オブジェクトとして配信します。

Lambda コンソールを使用してローカルのテストのためのサンプルイベントを作成するには、Amazon SES E メール受信のイベント例を参照してください。

SES バウンス、苦情、配信通知の例に関しては、Amazon SES の Amazon SNS 通知の例を参照してください。

7. DynamoDB からレポートをダウンロードして、SES 通知を表示する

DynamoDB コンソールを使用して、テーブルのコンテンツのクエリ、ソート、CSV ファイルとしてダウンロードを行うことができます。

  1. DynamoDB コンソールで、SESNotifications テーブルを選択します。
  2. [項目] タブに移動します。
  3. [クエリ] または [スキャン] 検索を作成します。

詳細に関しては、Amazon DynamoDB とはを参照してください。また、AWS Data Pipeline を使用し、コンプライアンスおよび記録管理を目的として、Amazon Simple Storage Service (Amazon S3) バケットへのファイルのダウンロードを定期的にスケジュールすることもできます。詳細に関しては、Export DynamoDB Table to S3 および第 2 部: DynamoDB からのデータのエクスポートを参照してください。


このページは役に立ちましたか? はい | いいえ

AWS サポート ナレッジ センターに戻る

サポートが必要ですか? AWS サポートセンターをご覧ください。

公開日: 2018 年 6 月 13 日

更新: 2018 年 7 月 9 日