はじめに
本記事はSESを初めて使用した際に陥った備忘録として投稿します。
AWS SESとは
公式サイトには以下のように説明されています。
ユーザー自身の E メールアドレスとドメインを使用して E メールを送受信するための、簡単で費用効率の高い方法を提供する E メールプラットフォーム
要するに、開発したサービスの中で簡単にメール送信を行えるというものです。
送信クォータとは
しかしSESは無制限に使えるわけではなく制限が設けられており、
以下のような送信クォータというものが設定されています。
・24時間ごとに200件まで(変更申請可能)
・1秒ごとに1件まで(変更申請可能)
・メールの容量は1件あたり40MBまで etc...
(詳しくは公式をご参考ください。)
発生したエラーと解決策
今回は以下のようなエラーが発生しました
554 Transaction faild:
Recipient count exceeds 50. The email was not sent.
SESでは1回の送信処理における最大宛先件数に50件という制限があり、
200件の宛先がある場合は最低でも4回に分ける必要があるということです。
何も知らず100件の宛先に一斉送信した私は当然これにひっかかりました。
解決策は主に2つです。
① 最大宛先件数の上限を上げる申請をする。
② 任意の件数ごとのアドレスリストを作成する。
①は簡単に思えますが、送信クォータには1秒ごとの送信件数制限もあるので
こちらにひっかかる可能性があります。
なので今回は②の方法で解決することにしました。
解決方法
以下の変数が設定されているとします。
List<String> allAddressList // 全ての送信先アドレスのリスト
では実際に解決できたコードを作成してみましょう。
int sendUnit = 50; // 1回の送信先件数
int allAddressSize = allAddressList.size(); // 全ての送信先件数
fot (int i = 0; i < allAddressSize; i+= sendUnit {
List<String> subList = new ArrayList<>
(allAddressList.subList(i, Math.min(i + sendUnit, allAddressSize));
// 送信処理のコード省略 //
}
今回はsubListメソッドを使用して、新しい送信先リストを作成しました。
subListは第一引数に開始位置、第二引数に終了位置を渡すことで、
その範囲にある値のリストを新しく作成できるメソッドです。
しかし注意すべき点がひとつ、
それはsubListはシャローコピーであるということです。
シャローコピーとは参照元と同じデータを参照しているという意味です。
要するにsubListに変更があると参照元のデータも変わってしまいます。
これを防ぐためにnewで初期化し、参照元に影響が出ないようにしています。
また、今回はsubListの第二引数でMath.min()を使用しました。
これは引数のうち小さい方を取得するというメソッドです。
例えばアドレスが80件の場合、Math.min()を使用しないどうなるでしょう。
int sendUnit = 50;
int allAddressSize = allAddressList.size();
fot (int i = 0; i < allAddressSize; i+= sendUnit {
List<String> subList = new ArrayList<>
(allAddressList.subList(i, i + sendUnit);
// 1週目は50件まで作成できるが、
// 2週目で81件目以降が存在せず例外が発生する。
}
81件目以降は存在しないのに取得しようとするため、例外が発生します。
Math.mint()を使って、
1回の送信先件数と未送信アドレス件数で小さい方をsubListに渡し、
例外が発生しないようにします。
まとめ
今回はsubListを使うことで送信クォータの制限を解決しました。
AmazonSESは簡単に使えて手軽なため初めてでも扱いやすい反面、
様々な制限がありAWSの知識も必要になります。
同じ場面に出くわした方に少しでも役立つことを願います。