Gửi Email Alert qua SNS: Tại Sao Tôi Không Nhận Được Email?
Bạn vừa tạo xong một SNS topic, gắn subscription email, deploy xong Lambda hoặc CloudWatch Alarm — rồi ngồi chờ. Không có gì. Đây là lỗi cực kỳ phổ biến khi mới làm việc với Amazon SNS email alert: subscription ở trạng thái PendingConfirmation và AWS đã gửi một email xác nhận đến inbox của bạn, nhưng bạn chưa click vào link đó.
TL;DR — Tóm Tắt Nhanh
| Vấn đề | Nguyên nhân | Hành động |
|---|---|---|
| Không nhận được email alert | Subscription chưa được xác nhận | Kiểm tra inbox, click link xác nhận |
| Email xác nhận không đến | Sai địa chỉ email hoặc bị spam filter | Kiểm tra spam/junk, tạo lại subscription |
| Subscription vẫn Pending sau 3 ngày | Token xác nhận đã hết hạn | Xóa subscription cũ, tạo mới |
| Đã confirm nhưng vẫn không nhận | Topic policy hoặc IAM chặn publish | Kiểm tra resource policy của topic |
Amazon SNS Email Subscription Hoạt Động Như Thế Nào
SNS không gửi email trực tiếp ngay khi bạn tạo subscription. Thay vào đó, nó thực hiện một quy trình xác nhận hai bước để đảm bảo địa chỉ email hợp lệ và chủ sở hữu đồng ý nhận thông báo. Đây là điểm mà hầu hết mọi người bị vấp.
Message publish sẽ bị bỏ qua Email->>SNS: Click link xác nhận SNS-->>U: SubscriptionArn: arn:aws:sns:... Note over SNS: Trạng thái: Confirmed U->>SNS: sns:Publish (message) SNS->>Email: Gửi email alert
- Subscribe: Bạn gọi
sns:Subscribevới protocolemailvà endpoint là địa chỉ email. - PendingConfirmation: SNS gửi email chứa một URL xác nhận duy nhất đến địa chỉ đó. Subscription ở trạng thái PendingConfirmation — mọi message publish lên topic trong giai đoạn này sẽ không được gửi đến email này.
- Confirm: Người dùng click vào link trong email. SNS chuyển subscription sang trạng thái Confirmed.
- Deliver: Từ đây, mọi message publish lên topic mới được SNS gửi đến email.
Token xác nhận có thời hạn hiệu lực. Nếu bạn không xác nhận trong thời gian đó, subscription sẽ tự động bị xóa và bạn cần tạo lại từ đầu.
Bước 1: Kiểm Tra Trạng Thái Subscription Hiện Tại
Trước khi làm bất cứ điều gì khác, hãy xác nhận chính xác subscription của bạn đang ở trạng thái nào. Đây là điểm khởi đầu duy nhất có ý nghĩa — mọi hướng xử lý tiếp theo đều phụ thuộc vào kết quả của bước này.
aws sns list-subscriptions-by-topic \
--topic-arn arn:aws:sns:us-east-1:123456789012:MyAlertTopic
Kết quả trả về sẽ có trường SubscriptionArn. Nếu giá trị là PendingConfirmation, subscription chưa được xác nhận. Nếu là một ARN đầy đủ (ví dụ arn:aws:sns:us-east-1:123456789012:MyAlertTopic:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx), subscription đã được xác nhận.
Bước 2: Xử Lý Subscription Đang Ở Trạng Thái PendingConfirmation
Nếu subscription đang PendingConfirmation, bước đầu tiên là kiểm tra inbox của địa chỉ email bạn đã đăng ký — bao gồm cả thư mục spam/junk. Email xác nhận có tiêu đề dạng 'AWS Notification - Subscription Confirmation', gửi từ no-reply@sns.amazonaws.com. Click vào link 'Confirm subscription' trong email đó.
Giống như đăng ký newsletter — dù bạn điền form xong, bạn vẫn phải click link trong email xác nhận thì mới thực sự được nhận bài. SNS hoạt động theo cùng cơ chế đó.
Nếu email xác nhận không đến hoặc token đã hết hạn, bạn cần xóa subscription cũ và tạo lại. Lưu ý quan trọng: lệnh aws sns unsubscribe chỉ hoạt động với các subscription đã ở trạng thái Confirmed (có ARN đầy đủ). Subscription đang ở trạng thái PendingConfirmation phải được xóa thông qua AWS Management Console (SNS → Topics → chọn topic → Subscriptions → chọn subscription pending → Delete).
Sau khi xóa subscription cũ, tạo lại subscription mới:
aws sns subscribe \
--topic-arn arn:aws:sns:us-east-1:123456789012:MyAlertTopic \
--protocol email \
--notification-endpoint your-email@example.com
Kiểm tra inbox ngay lập tức và click link xác nhận trước khi token hết hạn.
Bước 3: Xác Minh Topic Tồn Tại và Có Đúng ARN
Subscription đã confirmed nhưng vẫn không nhận được email? Lúc này cần kiểm tra xem alarm hoặc service của bạn có đang publish đúng topic ARN không. Một lỗi hay gặp là copy nhầm ARN từ region khác hoặc từ một topic test cũ.
aws sns get-topic-attributes \
--topic-arn arn:aws:sns:us-east-1:123456789012:MyAlertTopic
Lệnh này trả về các thuộc tính của topic, bao gồm TopicArn để bạn đối chiếu với ARN đang được cấu hình trong CloudWatch Alarm hoặc Lambda.
Bước 4: Kiểm Tra Topic Policy Có Cho Phép Publish Không
Đây là lớp hay bị bỏ qua nhất. Nếu CloudWatch Alarm hoặc một AWS service khác publish lên topic nhưng bị chặn bởi resource policy của topic, message sẽ bị drop hoàn toàn — không có error log rõ ràng ở phía người nhận.
aws sns get-topic-attributes \
--topic-arn arn:aws:sns:us-east-1:123456789012:MyAlertTopic \
--query 'Attributes.Policy' \
--output text
Kiểm tra trường Policy trong output. Nếu bạn muốn CloudWatch publish lên topic này, policy cần có statement tương tự:
🔽 Xem ví dụ Topic Policy cho CloudWatch Alarms
{
"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"
}
]
}
Nếu topic được tạo mà không chỉnh sửa policy, mặc định chỉ có account owner mới có quyền publish. Các AWS service như CloudWatch cần được cấp quyền tường minh trong resource policy.
Bước 5: Kiểm Tra IAM Permission Của Người Thực Hiện
Nếu bạn đang tạo subscription hoặc publish message bằng CLI/SDK với một IAM role hoặc user cụ thể, role đó cần có đủ quyền. Thiếu quyền ở bước này thường biểu hiện bằng lỗi AuthorizationError trong CLI — nhưng nếu bạn dùng console và không để ý, lỗi có thể bị bỏ qua.
🔽 Xem ví dụ IAM Policy tối thiểu cho SNS email alert
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SNSTopicActions",
"Effect": "Allow",
"Action": [
"sns:Subscribe",
"sns:Publish",
"sns:GetTopicAttributes",
"sns:Unsubscribe"
],
"Resource": "arn:aws:sns:us-east-1:123456789012:MyAlertTopic"
},
{
"Sid": "SNSListSubscriptions",
"Effect": "Allow",
"Action": [
"sns:ListSubscriptionsByTopic"
],
"Resource": "*"
}
]
}
Action sns:ListSubscriptionsByTopic được tách ra một Statement riêng với "Resource": "*" vì theo AWS Service Authorization Reference, action này không hỗ trợ resource-level restriction — nếu đặt chung với ARN cụ thể, policy sẽ không hoạt động đúng.
Luồng Chẩn Đoán Toàn Bộ
list-subscriptions-by-topic"] B --> C{"SubscriptionArn?"} C -->|"PendingConfirmation"| D["Kiểm tra inbox + spam"] D --> E{"Tìm thấy email xác nhận?"} E -->|"Có"| F["Click link xác nhận"] E -->|"Không / Token hết hạn"| G["Xóa qua AWS Console
Tạo lại subscription"] G --> F F --> H["Subscription Confirmed"] C -->|"ARN đầy đủ (Confirmed)"| I["Kiểm tra topic ARN
có khớp với publisher?"] I -->|"Sai ARN"| J["Sửa ARN trong CloudWatch
hoặc Lambda config"] I -->|"ARN đúng"| K["Kiểm tra Topic Resource Policy
get-topic-attributes"] K -->|"Policy chặn publish"| L["Cập nhật policy
cho phép service publish"] K -->|"Policy OK"| M["Kiểm tra IAM permission
của principal"] H --> N["Publish test message
sns:Publish"] J --> N L --> N M --> N N --> O["Nhận email thành công ✓"]
- Kiểm tra trạng thái subscription bằng
list-subscriptions-by-topic. - Nếu PendingConfirmation: kiểm tra inbox, click link xác nhận. Nếu token hết hạn, xóa qua Console và tạo lại subscription.
- Nếu đã Confirmed nhưng không nhận email: kiểm tra topic ARN đang được publish có khớp không.
- Kiểm tra topic resource policy có cho phép service publish không.
- Kiểm tra IAM permission của principal thực hiện publish/subscribe.
Kinh Nghiệm Thực Tế: Sai Lầm Hay Gặp Nhất
Tình huống điển hình: CloudWatch Alarm được cấu hình đúng, SNS topic tồn tại, subscription hiển thị Confirmed trong console — nhưng không có email nào đến khi alarm trigger. Kiểm tra CloudWatch Alarm history thấy trạng thái chuyển sang ALARM bình thường. Không có lỗi nào được log.
Nguyên nhân thực tế: topic được tạo bởi một account member, nhưng CloudWatch Alarm lại ở một account khác trong AWS Organizations. Topic policy không có statement cho phép cloudwatch.amazonaws.com từ account đó publish. Message bị drop hoàn toàn ở lớp resource policy — không có notification, không có CloudWatch metric nào cho thấy publish thất bại từ phía người nhận.
Bài học: khi cross-account hoặc cross-service publish, resource policy của topic là lớp đầu tiên cần kiểm tra, không phải IAM của publisher.
Gửi Test Message Để Xác Nhận End-to-End
Sau khi đã xác nhận subscription và kiểm tra policy, publish một message test để xác minh toàn bộ luồng hoạt động trước khi dựa vào đây cho production alert.
aws sns publish \
--topic-arn arn:aws:sns:us-east-1:123456789012:MyAlertTopic \
--subject "Test Alert" \
--message "Day la email test tu SNS topic MyAlertTopic"
Nếu email đến trong vòng vài giây, toàn bộ luồng từ publish đến delivery đang hoạt động đúng.
Tổng Kết và Bước Tiếp Theo với SNS Email Alert
Phần lớn các trường hợp không nhận được SNS email alert đều quy về một trong ba nguyên nhân: subscription chưa được xác nhận, topic resource policy chặn publisher, hoặc sai ARN. Quy trình chẩn đoán theo thứ tự — trạng thái subscription → topic policy → IAM — sẽ xác định được nguyên nhân trong hầu hết các tình huống.
Để đi sâu hơn, tham khảo tài liệu chính thức:
Glossary — Các Thuật Ngữ Chính
| Thuật ngữ | Giải thích |
|---|---|
| SNS Topic | Kênh truyền thông điệp trung tâm trong Amazon SNS. Publisher gửi message vào topic, SNS phân phối đến tất cả subscriber. |
| Subscription | Liên kết giữa một topic và một endpoint (email, SQS, Lambda, v.v.). Phải ở trạng thái Confirmed mới nhận được message. |
| PendingConfirmation | Trạng thái của subscription email sau khi tạo, trước khi người dùng click link xác nhận. Message sẽ không được gửi đến endpoint này. |
| Topic Resource Policy | JSON policy gắn trực tiếp vào SNS topic, kiểm soát principal nào được phép thực hiện action (publish, subscribe) lên topic đó. |
| Confirmation Token | Mã duy nhất trong link xác nhận email. Có thời hạn hiệu lực; sau khi hết hạn, subscription phải được tạo lại. |
Nhận xét
Đăng nhận xét