SNSメール通知が届かない原因と対処法:サブスクリプション確認を忘れていませんか?
SNSトピックを作成してメールアドレスを登録したのに、アラートが一切届かない——本番環境の監視を設定した直後にこの状況に陥ると、「SNSが壊れているのか、IAMが間違っているのか」と疑い始めてしまう。ほとんどの場合、原因はずっとシンプルだ。サブスクリプション確認メールのリンクをクリックしていない、それだけである。
TL;DR:SNSメール通知が届かない場合の確認ポイント
| 確認順序 | 確認内容 | 期待される状態 |
|---|---|---|
| 1 | サブスクリプションのステータス | confirmed(PendingConfirmationは未確認) |
| 2 | 確認メールの受信(迷惑メールフォルダ含む) | 件名「AWS Notification - Subscription Confirmation」 |
| 3 | SNSトピックのアクセスポリシー | パブリッシュ権限が正しく設定されている |
| 4 | 送信元サービスのIAMロール | SNSトピックへのsns:Publish権限を保持 |
| 5 | CloudWatchアラームのアクション設定 | 正しいSNSトピックARNが指定されている |
SNSメール通知の仕組み:なぜ確認が必要なのか
Amazon SNSのEmailサブスクリプションは、スパム防止のためにダブルオプトイン方式を採用している。エンドポイント(メールアドレス)を登録した時点では、サブスクリプションはPendingConfirmation状態になる。この状態では、トピックにメッセージがパブリッシュされても、そのエンドポイントには配信されない。確認リンクをクリックして初めてconfirmed状態に遷移し、通知が届くようになる。
- Subscribe呼び出し:メールアドレスをエンドポイントとしてSNSトピックに登録する
- PendingConfirmation:SNSが確認メールを送信し、サブスクリプションは保留状態になる
- 確認リンクのクリック:メール内のリンクをクリックすることでSNSに確認を通知する
- Confirmed:サブスクリプションが有効化され、以降のパブリッシュが配信される
- Publish → 配信:CloudWatchアラームなどからのメッセージが実際にメールとして届く
確認リンクには有効期限がある。SNSの確認トークンは3日間有効で、期限切れ後は再サブスクライブが必要になる。「確認メールが来ていたけど後で見ようと思っていた」というケースで期限切れになっていることが多い。
SNSサブスクリプション確認:ステップバイステップの診断と修正
ステップ1:サブスクリプションのステータスを確認する
まず現在のサブスクリプション状態を確認する。PendingConfirmationが表示されていれば、確認リンクのクリックが完了していないことが確定する。IAMやトピックポリシーを疑う前に、ここを見るだけで原因が判明することがほとんどだ。
aws sns list-subscriptions-by-topic \
--topic-arn arn:aws:sns:us-east-1:123456789012:MyAlertTopic \
--region us-east-1
出力のSubscriptionArnフィールドがPendingConfirmationになっていれば、確認が未完了である。confirmed状態の場合は、別の原因(ステップ3以降)を調査する。
ステップ2:サブスクリプションを再作成して確認メールを再送する
確認メールが見つからない、または有効期限が切れている場合は、既存のサブスクリプションを削除して再作成する。再作成することで新しい確認メールが送信される。今度は迷惑メールフォルダも含めて即座に確認すること。
# 既存のPendingConfirmationサブスクリプションを削除(ARNがPendingConfirmationの場合は削除不要なケースもあるため確認)
aws sns unsubscribe \
--subscription-arn arn:aws:sns:us-east-1:123456789012:MyAlertTopic:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \
--region us-east-1
# メールアドレスを再登録
aws sns subscribe \
--topic-arn arn:aws:sns:us-east-1:123456789012:MyAlertTopic \
--protocol email \
--notification-endpoint your-email@example.com \
--region us-east-1
受信した確認メールの件名は「AWS Notification - Subscription Confirmation」となる。メール本文内の「Confirm subscription」リンクをクリックすることで確認が完了する。
ステップ3:SNSトピックのアクセスポリシーを確認する
サブスクリプションがconfirmed状態なのに通知が届かない場合、トピックポリシーがパブリッシュを拒否している可能性がある。特にCloudWatchやEventBridgeなど他のAWSサービスからSNSにパブリッシュする場合、サービスプリンシパルへの許可が必要になる。
aws sns get-topic-attributes \
--topic-arn arn:aws:sns:us-east-1:123456789012:MyAlertTopic \
--region us-east-1 \
--query 'Attributes.Policy'
CloudWatchアラームからパブリッシュする場合、トピックポリシーに以下のステートメントが含まれている必要がある。
🔽 CloudWatch用SNSトピックポリシー例(クリックして展開)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCloudWatchPublish",
"Effect": "Allow",
"Principal": {
"Service": "cloudwatch.amazonaws.com"
},
"Action": "sns:Publish",
"Resource": "arn:aws:sns:us-east-1:123456789012:MyAlertTopic",
"Condition": {
"ArnLike": {
"aws:SourceArn": "arn:aws:cloudwatch:us-east-1:123456789012:alarm:*"
}
}
}
]
}
ステップ4:CloudWatchアラームのアクション設定を確認する
サブスクリプションもポリシーも問題ないのに通知が来ない場合、CloudWatchアラームが正しいSNSトピックARNを参照しているか確認する。アラームのアクションにSNSトピックが設定されていない、またはARNが誤っているケースが意外と多い。
aws cloudwatch describe-alarms \
--alarm-names "MyAlarmName" \
--region us-east-1 \
--query 'MetricAlarms[*].{AlarmName:AlarmName,AlarmActions:AlarmActions,StateValue:StateValue}'
AlarmActions配列に対象のSNSトピックARNが含まれていることを確認する。空配列または別のARNが設定されている場合は、アラームを更新する必要がある。
aws cloudwatch put-metric-alarm \
--alarm-name "MyAlarmName" \
--alarm-actions arn:aws:sns:us-east-1:123456789012:MyAlertTopic \
--region us-east-1 \
--metric-name CPUUtilization \
--namespace AWS/EC2 \
--statistic Average \
--period 300 \
--threshold 80 \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 2 \
--dimensions Name=InstanceId,Value=i-1234567890abcdef0
ステップ5:テストメッセージを手動パブリッシュして疎通確認する
CloudWatchアラームの状態遷移を待たずに、SNSトピックへ直接メッセージをパブリッシュして配信経路を検証する。これにより、SNS→メール配信の経路自体が機能しているかをアラームとは独立して確認できる。
aws sns publish \
--topic-arn arn:aws:sns:us-east-1:123456789012:MyAlertTopic \
--subject "SNS疎通テスト" \
--message "このメッセージが届けば、SNSからメールへの配信は正常に機能しています。" \
--region us-east-1
このコマンドでメールが届けば、SNSとサブスクリプションは正常だ。届かなければ、サブスクリプションのステータスに戻って再確認する。届いた場合にCloudWatchからの通知だけが来ないなら、アラームのアクション設定またはトピックポリシーの問題に絞り込める。
実際の現場で起きた誤診パターン
「SNSのパブリッシュが失敗しているはずだ」と思い込んで、IAMロールのポリシーを1時間かけて見直したことがある。CloudTrailでSNS:Publishのイベントを検索しても見つからない。「権限エラーだ」と確信してsns:Publishを追加しようとしたところ、すでに付与されていた。
実際の原因はサブスクリプションがPendingConfirmationのままだったことだ。SNSはパブリッシュ自体は成功させる——ただしconfirmedでないエンドポイントには配信しないだけだ。CloudTrailにはPublish成功のログが残るが、メールは届かない。この非対称な動作が誤診を引き起こす。
SNSのパブリッシュ成功とエンドポイントへの配信成功は別の概念である。
必要なIAM権限
SNSトピックの管理とサブスクリプション操作を行うユーザーまたはロールには、以下の権限が必要になる。
🔽 SNS管理用IAMポリシー例(クリックして展開)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SNSTopicManagement",
"Effect": "Allow",
"Action": [
"sns:ListSubscriptionsByTopic",
"sns:GetTopicAttributes",
"sns:Subscribe",
"sns:Unsubscribe",
"sns:Publish"
],
"Resource": "arn:aws:sns:us-east-1:123456789012:MyAlertTopic"
},
{
"Sid": "CloudWatchAlarmManagement",
"Effect": "Allow",
"Action": [
"cloudwatch:DescribeAlarms",
"cloudwatch:PutMetricAlarm"
],
"Resource": "*"
}
]
}
cloudwatch:DescribeAlarmsおよびcloudwatch:PutMetricAlarmはリソースレベルの制限をサポートしていないアクションが含まれるため、Resource: "*"が必要になる場合がある。AWS Service Authorization Referenceで最新の対応状況を確認すること。
まとめとネクストステップ:SNSメール通知の確実な運用
SNSのメール通知が届かない問題の大半は、サブスクリプションのPendingConfirmation状態、つまり確認リンクの未クリックが原因だ。診断の順序は明確で、まずサブスクリプションのステータスを確認し、confirmedであれば次にトピックポリシー、アラームのアクション設定へと進む。
本番環境では、SNSトピックの作成とサブスクリプション登録をIaC(CloudFormationやTerraform)で自動化することを検討する。ただし、Emailサブスクリプションの確認は自動化できないため、デプロイ後に必ず手動で確認ステータスを検証するプロセスを組み込むこと。
- Amazon SNS Email通知 — AWS公式ドキュメント
- SNSアクセスポリシーのユースケース — AWS公式ドキュメント
- CloudWatchアラームでSNS通知を送信する — AWS公式ドキュメント
用語集
| 用語 | 説明 |
|---|---|
| SNSトピック | メッセージの送受信を仲介するAmazon SNSのチャネル。パブリッシャーがメッセージを送り、サブスクライバーが受け取る |
| サブスクリプション | SNSトピックとエンドポイント(メールアドレスなど)の紐付け。確認完了後に有効化される |
| PendingConfirmation | サブスクリプション登録後、確認リンクのクリック前の保留状態。この状態ではメッセージが配信されない |
| トピックポリシー | SNSトピックへのアクセスを制御するリソースベースのポリシー。他のAWSサービスからのパブリッシュ許可もここで設定する |
| sns:Publish | SNSトピックにメッセージを送信するIAMアクション。CloudWatchアラームなどのサービスがこの権限を必要とする |
コメント
コメントを投稿