Amazon SESで発生したバウンスや苦情を任意のメールアドレスへ通知する仕組みを構築する

## はじめに

AWSでシステムを構築している場合、メールの送信を行う場合は [Amazon Simple Email Service](https://aws.amazon.com/jp/ses) (以降 `Amazon SES` と記載)を使用するケースが多いかと思います。
* 構成例：
![ses構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/b877d72d-1432-789f-b90d-3454c922d42c.png)
※Hoge Service はEC2やAmazon Lambdaなど、様々なサービスが設定可能

Amazon SESでは、メールアドレス誤り等による不達（バウンス）や、届いたメールのスパム報告（苦情）が一定数以上となると、メール送信機能が停止される恐れがある為、バウンス率は5％未満、苦情率は0.1％未満を維持することが勧められています。

参考：[評価ダッシュボードを使用して、Amazon SES 返送率が高いタイミングを知るにはどうすればよいですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/ses-reputation-dashboard-bounce-rate/)

なお、現在のバウンス率、苦情率はマネジメントコンソール上の `Amazon SES > 評判メトリクス` から確認が出来ます。
![スクリーンショット 2023-01-25 160608.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/d08afc64-d0e6-f467-86af-b02660e04813.png)
送信元メールアドレスにバウンスや苦情の発生を通知する機能はAmazon SESにあります（Eメールのフィードバック転送）が、あくまで送信元に限定されてしまう為、 `noreply@～` などといった送信専用のメールアドレスでは機能しないことが多いかと思われます。
そこで、 [Amazon Simple Notification Service](https://aws.amazon.com/jp/sns/) (以降 `Amazon SNS` と記載)を使用して任意のメールアドレスにバウンスや苦情をメールで通知する仕組みを構築します。

### 前提条件

本記事は以下の前提の下で動作を確認しています。
* アカウントがサンドボックス外にあり、任意のメールアドレス宛にメールが送信出来る状態
* 対象のメールアドレスの検証が完了しており、以下のようにマネジメントコンソールの `Amazon SES > 検証済みID` で表示される一覧のID（メールアドレス）のステータスが "確認済み" となっている状態
![Simple-Notification-Service (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/65ac8cb2-aef6-c1ba-6947-f943e1f41ee7.png)

### 構成図（概略）

最終的に以下のような構成を構築します。
Amazon SESから右に伸びている赤い矢印が、今回構築する通知に関する機能となります。
![ses-sns.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/9c929aad-f57a-d4fe-86a5-c11bba852ed2.png)

## Amazon SNSの設定

### トピックの作成

トピックは配信対象（サブスクリプション）を取りまとめるグループです。
今回はメール通知のみですが、メール通知＋Slackへの通知、などといった複数の通知先を設定することも出来ます。

マネジメントコンソールで `Amazon SNS > トピック` から `トピックの作成ボタン` を押下し、作成画面に遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/b701a863-257c-ade0-28bc-29f93dc7d374.png)
作成画面は以下となります。
![Simple-Notification-Service.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/8e8c61a0-f45c-ef45-0d4c-982d5392ac6f.png)
トピックには以下を設定します。
* タイプ：スタンダード
* 名前：任意の名前（今回は `Alert_to_admin` としています）

設定後、`トピックの作成ボタン` を押下し保存します。
これで、まずはトピックの作成が完了しました。

### サブスクリプションの作成

次に、トピックにメッセージが発行された時の通知先となるサブスクリプションを作成します。
今回は表題の通り、メールで通知を行う、といったサブスクリプションです。

先ほど作成したトピックの詳細画面の `サブスクリプションタブ` にある `サブスクリプションの作成` を押下し、作成画面に遷移します。
![Simple-Notification-Service (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/e2438d3c-c1f4-f0f5-134e-de6688e8e4fe.png)
作成画面は以下となります。
![Simple-Notification-Service (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/594b9b15-e2ac-73e9-3d66-d59598222fb5.png)
サブスクリプションには以下を設定します。
* トピックARN：先ほど作成したトピック
* プロトコル：Eメール
* エンドポイント：通知先のメールアドレス

`サブスクリプションの作成ボタン` 押下後、エンドポイントに入力したメールアドレスに以下のようなメールが届きます。
![スクリーンショット 2023-01-30 164005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/7d691e0a-839d-eb86-1cb3-46869ed35af8.png)
このメールはサブスクリプションへの登録確認のメールとなります。
メールに記載の `Confirm subscription` のURLにアクセスし、登録を完了させます。
![HTTPS-~1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/0b3964dc-6782-e65a-eb21-046aef750283.png)
上記画面が出たらAmazon SNSに来た通知を配信する設定までは完成となります。
ここまでの構成は以下のようなイメージです。
![ses-sns_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/c333fcdf-493f-8017-b2ec-9938dc752da5.png)
次に、作成したAmazon SNSのトピックとAmazon SESの関連付けを行い、Amazon SESでバウンスメールや苦情が発生した際に通知されるようにします。

## Amazon SESの設定

マネジメントコンソールで `Amazon SES > 検証済みID > 設定したいメールアドレス > 通知タブ` の順に遷移します。
![AWS-Simple-Email-Service-詳細ページ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/71685092-e24d-698f-bb38-e038651c33a0.png)
まだ設定を行っていない為、フィードバック通知のSNSトピック列が "SNSトピックなし" となっていますが、ここにAmazon SNSのトピックとの関連付けを行います。

フィードバック通知の `編集ボタン` を押下し、編集画面に遷移します。
![AWS-Simple-Email-Service-フィードバック通知の編集.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/25805063-3d19-7381-3cae-d3c585367bb3.png)
以下を設定します。
* バウンスフィードバック：先ほど作成したトピック（`Alert_to_admin`）
* 苦情のフィードバック：先ほど作成したトピック（`Alert_to_admin`）

`変更を保存ボタン` を押下し詳細画面に遷移すると、先ほど "SNSトピックなし" となっていたSNSトピック列に設定したトピックが表示されます。

![AWS-Simple-Email-Service-詳細ページ (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/0ff14f03-c3b8-5080-1739-22954c2bd944.png)

これでAmazon SESとトピックが関連付けられ、構築したかった構成が完成しました。
![ses-sns.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/9c929aad-f57a-d4fe-86a5-c11bba852ed2.png)
想定通りに動くかテストをしてみます。

## 設定の検証

Amazon SESではマネジメントコンソールから各種メールのテストが行えるようになっています。
マネジメントコンソールで `Amazon SES > 検証済みID` から、先ほどトピックを設定したメールアドレスのチェックボックスをオンにし、 `テストEメールの送信ボタン`を押下します。
![AWS-Simple-Email-Service-検証済み-ID.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/40d0b786-86c2-528a-2615-ea564513ade9.png)
以下のような画面が表示されます。
![AWS-Simple-Email-Service-テスト-E-メールの送信.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/9d9052b9-615a-7855-00ae-53a351a5fcc7.png)
ここでバウンスメールや苦情メールの送信テストが出来るので、バウンスや苦情が発生した時に通知メールが送られるかを確認していきます。
なお、ここで送ったバウンスメールや苦情メールはバウンス率や苦情率にカウントされないので安心してテストが行えます。

参考：[シミュレーターを使用した Amazon SES でのテストメール送信](https://docs.aws.amazon.com/ja_jp/ses/latest/dg/send-an-email-from-console.html)
>メールボックスシミュレーターに送信される E メールは送信クォータに加算されず、バウンス率や苦情率の計算にも含まれません。

テストに必要な以下の項目を入力します。
* Eメール形式：フォーマット済み
* From-address：（初期値）
* シナリオ：テストをしたいメールの種類（バウンス or 苦情）
* 件名：任意
* 本文：任意

入力後に `テストEメールの送信ボタン` を押下し、しばらく待つとサブスクリプションのエンドポイントに設定したメールアドレス宛に以下のようなメールが送られてきます。
![スクリーンショット 2023-01-30 165840.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/14a878e7-57f2-f6c6-d0f0-c6a46f574c26.png)
上記はシナリオを "バウンス" とした場合のメールとなりますが、このメールが実際にバウンスが発生した際の通知メールとなります。
本文がJSON形式となっており、 `notificationType` が `Bounce` となっていたり、 `destination` にシナリオに表示されていたメールアドレスが設定されているなど、どのメールに対して何が発生したか、の情報が記載されています。
なお、苦情の場合は `notificationType` が `Complaint` となります。

これで、設定についても問題がないことが確認出来ました。

もししばらく待ってもメールが届かない場合、CloudWatchを使ってAmazon SNSに通知が届いているか確認をしてみます。
マネジメントコンソールから `CloudWatch > すべてのメトリクス > SNS > トピックメトリクス` で該当するトピック名の `NumberOfNotificationsDelivered` がカウントされていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2698523/842dfd6d-a1ba-0aa2-1bdf-5ca8f3c02011.png)
メール不達には様々な要因があるので断言は出来ませんが、 `NumberOfNotificationsDelivered` でカウントされている場合はAmazon SESからAmazon SNSのトピックまでの疎通は出来ていることになるので、Amazon SNSのサブスクリプションの設定に誤りがないかを確認します。
カウントされていない場合はAmazon SNSのトピックにメッセージが届いていないことが予想される為、Amazon SESとトピックの関連付けを改めて確認してみるのが良いかもしれません。

## さいごに

ユーザがメールアドレスを入力出来る仕組みのあるシステムなどの場合、バウンスの通知とアクセスログなどと突き合わせることで、適当なメールアドレスを入力するブルートフォースアタックの兆候を検知するなど、様々な利用方法があるかと思います。
メールは運用でコントロールをしていくことが難しいですが、少しでも早くバウンスを検知をし対策が打てるような仕組みを作ることが大切かもしれません。
Amazon SESの通知の仕組み作りにこの記事がお役に立てれば幸いです。