Lambda を使用して、Amazon SES E メールの Amazon SNS 通知を DynamoDB に保存するにはどうすればよいですか?

所要時間5分
0

Amazon Simple Notification Service (Amazon SNS) を使用して、Amazon Simple Email Service (Amazon SES) から送信された E メールに関する通知を受け取っています。これらの通知を Amazon DynamoDB テーブルに保存するために AWS Lambda 関数を設定したいと考えています。

解決策

**注:**次のステップのコード例は、Node.js 18.x や 20.x などの V3 SDK を搭載した Lambda Node.js ランタイムに適用されます。

**前提条件:**Amazon SES からの通知を受信するように設定された Amazon SNS トピックを使用して Amazon SES E メールまたはドメインをセットアップする詳細については、「Amazon SNS を使用した Amazon SES 通知の受信」を参照してください。

DynamoDB テーブルを作成する

次の属性を持つテーブルをDynamoDB に作成します。

  • [テーブル名] には、「SESNotifications」と入力します。
  • [プライマリパーティションキー] には、「SESMessageId」と入力します。
  • [プライマリソートキー] には、「SnsPublishTime」と入力します。

Lambda がテーブルをクエリして Amazon SES レポートを作成できるようにするには、次のセカンダリインデックスを設定します。

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

注: 必要に応じて、セカンダリインデックスを追加できます。

詳細については、「DynamoDB テーブルを作成する」を参照してください。

Lambda 関数の IAM ロールに DynamoDB テーブルを呼び出す権限を追加します。

新しい AWS Identity and Access Management (IAM) ロールを作成します。Lambda 関数が DynamoDB:PutItem API を呼び出すことができるようにロールを設定します。

注: さまざまな Lambda 関数用に新しい IAM ロールを作成して使用するのがベストプラクティスです。複数の機能でロールを再利用しないでください。

Lambda 関数の IAM ロールにアクセス権限を追加するには、次の手順を実行します。

  1. IAM コンソールを開きます。
  2. ナビゲーションペインで、[ロール] を選択します。
  3. [ロールを作成] を選択します。
  4. [信頼されたエンティティの種類を選択] から、[AWS サービス] を選択します。
  5. [ユースケースの選択] で、[Lambda] を選択します。そして、[次へ: 権限] を選択します。
  6. [許可ポリシーをアタッチ] では、[AWSLambdaBasicExecutionRole] 管理ポリシーの横にあるチェックボックスを選択します。そして、[次へ: タグ] を選択します。
  7. (オプション) ロールに IAM タグを追加します。詳細については、「IAM リソースのタグ付け」を参照してください。
  8. [次へ: 確認] を選択します。
  9. [ロール名]* には「lambda_ses_execution」と入力します。
  10. [ロールの作成] を選択します。
  11. IAM ロールを返し、ロールを選択します。
  12. [権限] タブで [インラインポリシーを追加] を選択します。
  13. [ビジュアルエディタ] タブで、[サービスを選択] を選択します。
  14. [DynamoDB] を選択します。
  15. [アクション] 検索フィールドに「PutItem」と入力します。ドロップダウンリストで、PutItem の横にあるチェックボックスを選択します。
  16. [リソース][特定] を選択します。
  17. [ARN の追加] を選択します。次に、テキストボックスに DynamoDB テーブルの ARN を入力します。
  18. [ポリシーの確認] を選択します。
  19. [名前] にポリシーの名前を入力します。
  20. [ポリシーを作成] を選択します。

DynamoDB テーブルへのアクセスを許可するインライン IAM ポリシーの例

{
    "Version": "2012-10-17",
    "Statement": [
         {
            "Sid": "Stmt1428510662000",
            "Effect": "Allow",
            "Action": [
                "DynamoDB:PutItem"
            ],
            "Resource": [
                "arn:aws:DynamoDB:us-east-1:12345678912:table/SESNotifications"
            ]
        }
    ]
}

Amazon SES と Amazon SNS の通知を処理する Lambda 関数を作成する

次のサンプル関数コードを使用して、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 関数を 1 つ以上の Amazon SNS トピックにサブスクライブする

Amazon SNS コンソールまたは Lambda コンソールを使用して、Lambda 関数を 1 つ以上の Amazon SNS トピックにサブスクライブできます。

**アマゾン 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-functionsns-my-topic、および arn:aws:sns:us-east-1:123456789012:my-topic を、必ず関数、トピック、および完全な ARN の ID に置き換えてください。

関数を SNS トピックに登録するには、次の手順を実行します。

  1. Amazon SNS コンソールを開きます。
  2. ナビゲーションペインで、[トピック] を選択します。
  3. バウンス通知のために Amazon SES で使用される SNS トピックを特定します。例: ses_notifications_repo という名前の SNS トピック。
  4. SNS トピックの ARN を選択します。
  5. [サブスクリプションの作成] を選択します。
  6. [プロトコル] には、[AWS Lambda] を選択します。
  7. [エンドポイント] には、Lambda 関数の ARN を入力します。
  8. [サブスクリプションの作成] を選択します。
  9. (オプション) 関数にサブスクライブする通知トピックごとに、前の手順を繰り返します。

Lambda コンソール

Lambda コンソールを使用して Lambda 関数を 1 つ以上の SNS トピックにサブスクライブするには、次の手順を実行します。

  1. Lambda コンソールを開きます。
  2. ナビゲーションペインで、[関数] を選択します。
  3. Lambda 関数を選択します。
  4. [関数の概要] ペインで、[+トリガーの追加] を選択します。
  5. [トリガーの設定] ドロップダウンリストで、[SNS] を選択します。
  6. **SNS ** トピックドロップダウンリストで、SNS トピックを選択します。
  7. [追加] を選択します。
  8. (オプション) 関数にサブスクライブする通知トピックごとに、前の手順を繰り返します。

セットアップのテスト:

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 ファイルとしてクエリ、ソート、ダウンロードするには、次の手順を実行します。

  1. DynamoDB コンソールを開きます。
  2. SESNotifications テーブルを選択します。
  3. [項目] タブを選択します。
  4. [クエリ] または [スキャン] 検索を作成します。詳細については、「データのクエリとスキャンのベストプラクティス」を参照してください。
    **注:**DynamoDB テーブルエクスポートを使用すれば、Amazon シンプルストレージサービス (Amazon S3) バケットへのファイルのダウンロードを定期的にスケジュールすることができます。詳細については、「Amazon S3 への DynamoDB データエクスポート:仕組み」を参照してください。

関連情報

Lambda 関数へのファンアウト

Invoking AWS Lambda functions via Amazon SNS

Amazon SNSを使用したAmazon SES通知の受信

AWS公式
AWS公式更新しました 5ヶ月前
コメントはありません