[アップデート] Amazon SES のメール送信イベントの送信先に EventBridge を指定出来るようになりました

2024.06.15

いわさです。

先日のアップデートで Amazon SES のメール送信イベントを EventBridge に送信出来るようになりました。

今まで Amazon SES では EventBridge が長い間サポートされておらず、少し前に Vertual Deliverability Manager のレコメンドイベントがようやく EventBridge に発行されるようになった程度でした。

今回ついにイベント送信先として EventBridge が追加されるようになりました。
これまではメール送信イベントのアクティビティログを残したり後続の処理を自動化したい場合、次のように SNS 経由で Lambda でロジックで処理させたり、あるいは Firehose から S3 に転送するなど固定パターンで蓄積したりなどができていましたが、今回 EventBridge がサポートされたことでより簡単に幅広い活用が出来るようになりました。

今回簡単なところとして EventBridge 経由で CloudWatch Logs にメール送信アクティビティログを溜め込む設定をしてみましたので紹介します。

EventBridge 経由で取得出来るイベント

まず、EventBridge 経由で取得出来るイベントは次の公式ドキュメントに追記されています。

内容を抜粋しイベントの概要をまとめておきました。

イベントタイプ 概要
Email Bounced 受信者のメールサーバーが永久的にメールを拒否したハードバウンス(ソフトバウンスは、SESがメールを配信できなかった場合にのみ)
Email Clicked 受信者がメール内のリンクをクリック
Email Complaint Received メールサーバーに正常に配信されたが、受信者がスパムとしてマークした
Email Delivered 受信者のメールサーバーに正常に配信した。
Email Delivery Delayed 一時的な問題が発生したため、メールを受信者のメールサーバーに配信できなかった。受信者のメールボックスが一杯だったり、受信メールサーバーに一時的な問題があったりすると、配信遅延が発生する場合がある
Email Opened 受信者がメッセージを受信し、メールクライアントで開いた
Email Rejected SESがメールを受け付けたが、ウイルスが含まれていると判断し、受信者のメールサーバーに配信できなかった
Email Rendering Failed テンプレートデータが不足していたり、テンプレートパラメーターとデータが一致しなかったりしたため、メールを送信できなかった
Email Sent 送信リクエストが成功し、SESが受信者のメールサーバーにメッセージを配信しようとしている
Email Subscribed メールが正常に配信されたが、受信者がメールヘッダーのList-Unsubscribeをクリックするか、フッターのUnsubscribeリンクをクリックしてサブスクリプション設定を更新した

また、EventBridge のルール作成時にサンプルイベントを確認することが出来るのですがその中のひとつを紹介します。以下はバウンスイベントのデータとなります。

{
  "version": "0",
  "id": "12a18625-3328-fafd-2809-a5e16004f112",
  "detail-type": "Email Bounced",
  "source": "aws.ses",
  "account": "123456789012",
  "time": "2023-07-17T16:48:05Z",
  "region": "us-east-1",
  "resources": ["arn:aws:ses:us-east-1:123456789012:identity/example.com"],
  "detail": {
    "eventType": "Bounce",
    "bounce": {
      "bounceType": "Permanent",
      "bounceSubType": "General",
      "bouncedRecipients": [{
        "emailAddress": "recipient@example.com",
        "action": "failed",
        "status": "5.1.1",
        "diagnosticCode": "smtp; 550 5.1.1 user unknown"
      }],
      "timestamp": "2017-08-05T00:41:02.669Z",
      "feedbackId": "01000157c44f053b-61b59c11-9236-11e6-8f96-7be8aexample-000000",
      "reportingMTA": "dsn; mta.example.com"
    },
    "mail": {
      "timestamp": "2017-08-05T00:40:02.012Z",
      "source": "Sender Name <sender@example.com>",
      "sourceArn": "arn:aws:ses:us-east-1:123456789012:identity/sender@example.com",
      "sendingAccountId": "123456789012",
      "messageId": "EXAMPLE7c191be45-e9aedb9a-02f9-4d12-a87d-dd0099a07f8a-000000",
      "destination": ["recipient@example.com"],
      "headersTruncated": false,
      "headers": [{
        "name": "From",
        "value": "Sender Name <sender@example.com>"
      }, {
        "name": "To",
        "value": "recipient@example.com"
      }, {
        "name": "Subject",
        "value": "Message sent from Amazon SES"
      }, {
        "name": "MIME-Version",
        "value": "1.0"
      }, {
        "name": "Content-Type",
        "value": "multipart/alternative; boundary=\"----=_Part_7307378_1629847660.1516840721503\""
      }],
      "commonHeaders": {
        "from": ["Sender Name <sender@example.com>"],
        "to": ["recipient@example.com"],
        "messageId": "EXAMPLE7c191be45-e9aedb9a-02f9-4d12-a87d-dd0099a07f8a-000000",
        "subject": "Message sent from Amazon SES"
      },
      "tags": {
        "ses:configuration-set": ["ConfigSet"],
        "ses:source-ip": ["192.0.2.0"],
        "ses:from-domain": ["example.com"],
        "ses:caller-identity": ["ses_user"]
      }
    }
  }
}

メール本文はやはり取得できませんが、ヘッダー情報や件名、送信先、タイムスタンプなどの必要な情報は取得できますね。良さそうです。

ルールを設定してみる

では EventBridge で新規ルールを作成してみます。
イベントパターンとして新しい Amazon SES のルールが追加されています。

詳細タイプを指定しないことも出来るのですが、前述のアドバイザーレコメンドも配信されるのでそちらのオプションを有効化している場合は意識したほうが良いです。イベントデータがごちゃごちゃになってしまうかもしれない。

配信先に CloudWatch Logs ロググループを直接指定します。
ちなみにマネジメントコンソールから指定した場合はロググループのリソースベースポリシーなど勝手に設定されます。CLI や SDK 経由で設定した場合はリソースベースポリシーの明示的な指定が必要になるのでご注意ください。

受信できなかった

さぁテストメールを送信して受信出来るか確認してみます。
Amazon SES コンソールからテストメール送信機能を使います。

しかし、イベントを受信することができずここで少し悩みました。

イベント送信先の設定必要

今回のアップデートにあわせて API も更新されていまして、どうやら勝手にイベントが送信されるわけではないようです。何かしら API を操作する必要があるっぽい。

で、確認したところ設定セットに対してイベント送信先の設定が必要だということがわかりました。次のコマンドの送信先に新たに EventBridge を指定出来るようになっています。なるほど。

マネジメントコンソールでも同様に設定することができまして、作成済みの設定セットに対してイベント送信先を追加設定することができます。
検証用の適当な設定セットが存在していたのでそいつに設定してみます。設定セットの新規作成時にはイベント送信先の作成はまだできません。一度設定セットを作成しておく必要があります。

設定セットのイベント送信先タブから送信先の追加が可能です。

送信するイベントタイプ指定後に、送信先を指定しましょう。
Amazon EventBridge が追加されています。
なお、本日時点でイベントバスは default のみがサポートされていますのでご注意ください。

設定できました...!

先ほどと同様に再びテストメールを送信してみると...イベントデータが CloudWatch ロググループへ配信されています。良さそうだ。

ログデータの内容は次のようになっていました。
繰り返しになりますが、本文はデータに含まれていませんのでご注意ください
よくある送信アクティビティログとしては使えるのではないでしょうか。

{
    "version": "0",
    "id": "5d9b54e9-a611-4464-37b9-307151fca9ea",
    "detail-type": "Email Delivered",
    "source": "aws.ses",
    "account": "123456789012",
    "time": "2024-06-15T00:21:24Z",
    "region": "ap-northeast-1",
    "resources": [
        "arn:aws:ses:ap-northeast-1:123456789012:configuration-set/hoge-config"
    ],
    "detail": {
        "eventType": "Delivery",
        "mail": {
            "timestamp": "2024-06-15T00:21:23.684Z",
            "source": "sender@mail1.tak1wa.com",
            "sourceArn": "arn:aws:ses:ap-northeast-1:123456789012:identity/mail1.tak1wa.com",
            "sendingAccountId": "123456789012",
            "messageId": "0106019019453264-e4e24702-0de5-4550-b8df-2d2e7592625d-000000",
            "destination": [
                "success@simulator.amazonses.com"
            ],
            "headersTruncated": false,
            "headers": [
                {
                    "name": "From",
                    "value": "sender@mail1.tak1wa.com"
                },
                {
                    "name": "To",
                    "value": "success@simulator.amazonses.com"
                },
                {
                    "name": "Subject",
                    "value": "hoge"
                },
                {
                    "name": "MIME-Version",
                    "value": "1.0"
                },
                {
                    "name": "Content-Type",
                    "value": "multipart/alternative;  boundary=\"----=_Part_1759514_144765430.1718410883684\""
                }
            ],
            "commonHeaders": {
                "from": [
                    "sender@mail1.tak1wa.com"
                ],
                "to": [
                    "success@simulator.amazonses.com"
                ],
                "messageId": "0106019019453264-e4e24702-0de5-4550-b8df-2d2e7592625d-000000",
                "subject": "hoge"
            },
            "tags": {
                "ses:source-tls-version": [
                    "TLSv1.3"
                ],
                "ses:operation": [
                    "SendEmail"
                ],
                "ses:configuration-set": [
                    "hoge-config"
                ],
                "ses:recipient-isp": [
                    "AmazonSES"
                ],
                "ses:source-ip": [
                    "104.28.196.10"
                ],
                "ses:from-domain": [
                    "mail1.tak1wa.com"
                ],
                "ses:sender-identity": [
                    "mail1.tak1wa.com"
                ],
                "ses:caller-identity": [
                    "cm-iwasa.takahito"
                ],
                "ses:outgoing-ip": [
                    "23.251.234.1"
                ]
            }
        },
        "delivery": {
            "timestamp": "2024-06-15T00:21:24.443Z",
            "processingTimeMillis": 758,
            "recipients": [
                "success@simulator.amazonses.com"
            ],
            "smtpResponse": "250 2.6.0 Message received",
            "reportingMTA": "e234-1.smtp-out.ap-northeast-1.amazonses.com"
        }
    }
}

あるいはこのイベントをフックして送信先リストをメンテナンスすることも出来そうです。

さいごに

本日は Amazon SES のメール送信イベントの送信先に EventBridge を指定出来るようになったので、CloudWatch ロググループにメールアクティビティログとして出力出来るようにしてみました。

設定セットのイベント追加が必要ですが、非常に簡単に設定できますね。
今までは SNS -> Lambda で処理することが鉄板だった気がしますが、今後は EventBridge 経由で柔軟な構成を行うことが出来そうです。