見出し画像

Amazon SES の送信履歴をDynamoDBに保存する

概要

最近は、メール送信は PostfixやSendmailを使って直接メール配送するよりもスケーラビリティの高いAmazon SESを使うのが一般的かと思います。
phpのフレームワークの LaravelもAmazonSESを標準的にサポートしており、単純なメール送信なら簡単に実装可能です。

そんな Amazon SESですが送信先への到達性を確認するためには工夫が必要です。(API用意されてると嬉しいなぁ。嬉しいなぁ。)
AWS公式サイトにナレッジに沿って進めれば、送信状況を保存して、取得することができるのですが、期待するデーター構造ではなかったのでナレッジのスクリプトを少し改造した話です。

AWSの公式サイトのナレッジ

AWS Lambda 関数を作成して Amazon SES に関する Amazon SNS 通知内容を Amazon DynamoDB データベースに保存する方法を教えてください。

ナレッジに沿って
AmazonSES -> SNS -> Lambda -> DynamoDB 構成を作って行きます。

* Amazon SES の Amazon SNS 通知の設定 をして
* DynamoDBを作成して
* Lambda を作って
な感じで設定して行きます。複数サービスの組み合わせなので、なかなか敷居高いですがググれば色々出てきます!\(^o^)/

期待するものと違った!

公式ナレッジに沿って実装すると、
送信先アドレスが入っているSESDestinationAddressカラムに
複数のメールアドレスが入っているではありませんか!!!

私の所属している会社のサービスでは、1メール送信で to,cc に複数のメールアドレスを指定して同時送っているためナレッジのLambdaコードだと、DynamoDBに格納されるデータ構造では非常に取り扱いづらいものとなってしまいます。(to,cc などで同時に送ったメールの Message-IDは同一になるため。)

// DynamoDB SESDestinationAddress カラム
jane@example.com,mary@example.com,richard@example.com
// Lambda 実装
var SESDestinationAddress = SESMessage.mail.destination.toString();
// SNS通知 JSON destination が 配列ということが確認できる。
   {
      "notificationType":"Bounce",
      "bounce":{
        [中略]
      },
      "mail":{
         "timestamp":"2016-01-27T14:59:38.237Z",
         "source":"john@example.com",
         [中略]
         "messageId":"00000138111222aa-33322211-cccc-cccc-cccc-ddddaaaa0680-000000",
         "destination":[  // ここです!
           "jane@example.com",
           "mary@example.com",
           "richard@example.com"],
         "headersTruncated":false,
[以下略]

なお、SNSで通知されるJSONは全部で5パターンあり以下で確認できます。Bounce (2パターン)/ Complain(2パターン) / Delivery(1パターン)
Amazon SNS 通知の例 
Amazon SNS 通知の内容

理想とする形式でDynamoDBに格納する

そこで、ナレッジのLambdaコードに手を加えて、
1レコード1送信先になるよう以下のようなデータ構造でDynamoDBに格納するようにします。

- MessageId
   - 1メール送信毎に発行される
   - ID to,ccなど同時に送る場合は同一IDとなる。
- SrcAddress
   - 単一の送信先アドレス
   - ex)from@example.com
- DestAddress
   - ex) to@example.com
- MessageType
   - Delivery / Bounce / Complaint のいずれか
-Summary
   - 送信状況の具体的な内容

DynamoDBの プライマリパーティションキーとプライマリソートキーは以下のように作成します。(ナレッジ通り作成した場合は、再作成が必要)

* プライマリパーティションキー: MessageId (文字列)
* プライマリソートキー:DestAddress (文字列)

コード例

* 以下のコードだと、 MessageIDとDestAddress(送信先)の2要素で特定の送信先への配信状況がわかるので取り扱いやすくなります!
* Bounce / Complain / Deliveryで送信先アドレスの取得方法が違うので分岐があります。
* javascript 書き慣れていないのでコードはあれです。
* 実際にビジネスで動いているコードとは違います。



この記事が気に入ったらサポートをしてみませんか?