
AWS SESのバウンスメール情報をアプリケーション側で受け取ってみる
はじめに
開発の要件として、アプリケーションからのメール送信時に、
宛先が到達不可能なメールアドレスだった場合に、
そのメールアドレス宛に再度アプリケーションからメールが送られないようにする必要がありました。
今回は、現在使用しているAWSサービスのSimpleEmailService(以下、SESと記載)のバウンスメール情報を、
アプリケーション側で受け取る方法を説明します。
環境
PHP:8.3.7
Laravel:12.3.0
アプリケーション側の設定
アプリケーション側でバウンスメール情報を受け取る準備をします。
今回はPHP+Laravelで実装を行いましたが、
指定したアドレス宛にPOSTでパラメータを受け取れれば何を使ってもOKです。
まず実際の処理を行うControllerを作成します。
後述するSES設定で使用するサブスクライブ用のURLは、
今回ログに出力するようにしています。
App\Http\Controllers\SesBounceController.php
<?php
namespace App\Http\Controllers;
use App\Models\UndeliverableMailAddress;
use Carbon\Carbon;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class SesBounceController extends Controller
{
public function handleBounce(Request $request): \Illuminate\Http\JsonResponse
{
// JSON通知データを取得
$message = json_decode($request->getContent(), true);
// サブスクライブ用のURLをログに表示する
Log::channel('daily')->info($message['SubscribeURL'] ?? "", [
"file" => __FILE__,
"line" => __LINE__
]);
// "Message"フィールドをデコード
$notification = json_decode($message['Message'] ?? '', true);
if (
isset($notification['notificationType']) &&
$notification['notificationType'] === 'Bounce'
) {
// バウンスイベントである場合
$bouncedRecipients = $notification['bounce']['bouncedRecipients'];
foreach ($bouncedRecipients as $recipient) {
$emailAddress = $recipient['emailAddress'];
// メールアドレスを使ってDBに登録するなど。今回はログにメールアドレスを出力します。
Log::channel('daily')->info($emailAddress, [
"file" => __FILE__,
"line" => __LINE__
]);
}
}
return response()->json(['message' => 'Bounce processed']);
}
}次にルートの設定をします。
先ほど作成したControllerで処理を受け取れるようにします。
routes\api.php
<?php
use Illuminate\Support\Facades\Route;
// sesのバウンスを受け取る
Route::post('ses/bounce', [App\Http\Controllers\SesBounceController::class, 'handleBounce']);これでアプリケーション側の設定はOKです。
SNSの設定
アプリケーション側へのバウンス通知は、
AWSサービスのSimpleNotificationService(以下、SNSと記載)を使用します。
まずは赤枠のボタンからトピックを作成します。
タイプはスタンダードを選択し、
名前と表示名はお好みで問題ありません。
入力できたら、画面下部にあるトピックの作成ボタンを押下します。
トピックが作成できたら、
次はサブスクリプションの作成を行います。
トピックARNはそのままで、
プロトコルはHTTPSを選択します。
エンドポイントにはroutes\api.phpで設定したURLを入力します。
入力できたら、画面下部のサブスクリプションの作成ボタンを押下します。
サブスクリプションが作成できたら、
トピックの詳細画面に戻りましょう。
サブスクリプションが追加され、ステータスが「保留中の確認」になっていることが確認できます。
ここまでできたら、
アプリケーション側のログを確認してみましょう。
先ほどControllerでサブスクライブ用のURLをログに出力するようにしているので、
ログにサブスクライブ用のURLが出力されているはずです。
そのURLにアクセスするとサブスクライブが完了します。
※ログに出てこない場合は、リクエストの確認ボタンを押してみてください。
再度エンドポイントに対してリクエストが送られます。
それでも出てこない場合は、リクエストが届いていない可能性が高いです。
IP制限などの設定を確認してください。
サブスクライブが完了すると、
サブスクリプションのステータスが「確認済み」になります。
これでSNSの設定はOKです。
SESの設定
最後にSESの設定になりますが、
既にID設定が完了していることを前提に進めます。
まずメール送信に使用しているメールアドレスもしくはドメインの詳細ページに移動します。
詳細ページの下部で、通知タブを押下します。
フィードバック通知という項目が出てくるので、
編集ボタンを押下します。
編集画面で、バウンスフィードバックに先ほど作成したトピックを設定します。
設定出来たら変更の保存ボタンを押下します。
これですべての設定が完了となります。
あとは実際にバウンスになるメールを送ってみるなり、
SESの機能の「テストEメールの送信」をやってみるなりして、
動作を確認しましょう。
まとめ
以上がSESのバウンスメール情報をアプリケーション側で受け取る方法でした。
今回この対応を実施する中で、バウンスメールに関しての気づきがありました。
SESのバウンスメールは、すぐ返ってくる場合もあれば、数時間~数日かかる場合もあるらしく、
送信先のメールサーバーによっては、バウンスが発生しない場合もあるらしいです。
何とも曖昧な基準なのだと感じました。。。







