AWS SES Sandbox Mode: Tại Sao Không Gửi Email Cho Khách Hàng Và Cách Yêu Cầu Production Access
Bạn vừa tích hợp xong Amazon SES, gửi thử email cho chính mình thì nhận được ngay — nhưng khi deploy lên production, toàn bộ email gửi cho khách hàng đều bị từ chối với lỗi MessageRejected. Đây là triệu chứng điển hình của SES Sandbox Mode, và nếu bạn không biết mình đang ở trong đó, bạn sẽ mất hàng giờ debug ở tầng application trong khi vấn đề nằm ở tầng account.
TL;DR — SES Sandbox Mode Là Gì Và Cần Làm Gì
| Vấn đề | Nguyên nhân | Giải pháp |
|---|---|---|
| Chỉ gửi được cho email đã verify | Account đang ở Sandbox Mode | Request production access qua SES console |
| Bị giới hạn 200 email/ngày | Sandbox sending quota | Yêu cầu tăng sending limit trong cùng request |
Lỗi MessageRejected | Địa chỉ đích chưa được verify | Verify địa chỉ đích hoặc thoát Sandbox |
| Không thấy nút request production access | Sai region trong console | Kiểm tra đúng region đang dùng SES |
SES Sandbox Mode Hoạt Động Như Thế Nào
Mọi AWS account khi bắt đầu sử dụng SES đều ở Sandbox Mode theo mặc định. AWS áp dụng điều này để ngăn chặn spam và bảo vệ reputation của shared sending infrastructure. Đây không phải lỗi cấu hình — đây là trạng thái mặc định có chủ ý.
Trong Sandbox, SES áp đặt ba ràng buộc chính:
- Chỉ có thể gửi email đến địa chỉ hoặc domain đã được verify trong cùng AWS account.
- Chỉ có thể gửi từ địa chỉ hoặc domain đã được verify.
- Sending quota bị giới hạn — kiểm tra giá trị cụ thể trong SES console vì quota có thể thay đổi theo thời gian.
Khi bạn gửi email cho chính mình và nhận được, đó là vì cả địa chỉ gửi lẫn địa chỉ nhận đều đã được verify trong account của bạn. Khách hàng của bạn thì không.
- Sandbox Mode: SES kiểm tra xem địa chỉ đích có nằm trong danh sách verified identities của account không. Nếu không — reject ngay.
- Production Mode: SES bỏ qua bước kiểm tra đó và gửi đến bất kỳ địa chỉ hợp lệ nào, với sending quota cao hơn nhiều.
- Trạng thái Sandbox/Production là per-region. Nếu bạn dùng SES ở
us-east-1vàeu-west-1, bạn phải request production access riêng cho từng region.
Xác Nhận Account Đang Ở Sandbox Mode
Trước khi submit bất kỳ request nào, hãy xác nhận trạng thái thực tế. Nhiều người submit request rồi mới phát hiện mình đã ở production mode ở một region khác.
aws sesv2 get-account \
--region us-east-1
Tìm field ProductionAccessEnabled trong output. Nếu giá trị là false, account đang ở Sandbox Mode cho region đó.
{
"DedicatedIpAutoWarmupEnabled": true,
"EnforcementStatus": "HEALTHY",
"ProductionAccessEnabled": false,
"SendQuota": {
"Max24HourSend": 200.0,
"MaxSendRate": 1.0,
"SentLast24Hours": 0.0
},
"SendingEnabled": true
}
ProductionAccessEnabled: false — đây là xác nhận rõ ràng nhất. SendingEnabled: true chỉ có nghĩa là account không bị suspend, không có nghĩa là đã thoát Sandbox.
Verify Sending Identity Trước Khi Request Production Access
AWS sẽ đánh giá request của bạn dựa một phần vào việc bạn đã setup sending infrastructure đúng cách chưa. Verify domain với DKIM trước khi submit sẽ tạo ấn tượng tốt hơn và giúp email deliverability sau này.
Verify Domain (Khuyến nghị)
aws sesv2 create-email-identity \
--email-identity example.com \
--dkim-signing-attributes SigningAttributesOrigin=AWS_SES \
--region us-east-1
Lệnh này tạo DKIM keys và trả về các DNS records cần thêm vào Route 53 hoặc DNS provider của bạn. Sau khi thêm DNS records, kiểm tra trạng thái verify:
aws sesv2 get-email-identity \
--email-identity example.com \
--region us-east-1
Chờ đến khi VerifiedForSendingStatus trả về true trước khi tiếp tục.
Verify Email Address Đơn Lẻ (Cho Testing)
aws sesv2 create-email-identity \
--email-identity you@example.com \
--region us-east-1
AWS sẽ gửi một email xác nhận đến địa chỉ đó. Click vào link trong email để hoàn tất verify.
Cách Request Production Access — Thoát SES Sandbox Mode
Đây là bước quan trọng nhất. Request được submit qua SES console hoặc AWS CLI, và AWS sẽ review thủ công. Thời gian xử lý thường trong vòng 24 giờ, nhưng không có SLA cố định.
Qua AWS Console
- Mở Amazon SES console → chọn đúng region.
- Trong navigation pane, chọn Account dashboard.
- Tìm section Sending limits → click Request production access.
- Điền form với thông tin use case của bạn.
Qua AWS CLI (SES v2)
aws sesv2 put-account-details \
--mail-type TRANSACTIONAL \
--website-url https://www.example.com \
--use-case-description "We send transactional emails including order confirmations, password resets, and account notifications to registered users who have opted in through our sign-up flow. We maintain a suppression list and process unsubscribe requests within 10 business days." \
--additional-contact-email-addresses admin@example.com \
--production-access-enabled \
--region us-east-1
Lưu ý: --mail-type chấp nhận TRANSACTIONAL hoặc MARKETING. Chọn đúng loại — AWS dùng thông tin này để đánh giá request.
Nội Dung Use Case Description Cần Có
Đây là phần quyết định request của bạn được approve hay bị yêu cầu bổ sung thông tin. Từ kinh nghiệm thực tế, một description tốt cần trả lời được bốn câu hỏi sau:
- Bạn gửi loại email gì? — Transactional (order confirmation, password reset) hay marketing (newsletter, promotion).
- Người nhận opt-in như thế nào? — Double opt-in, single opt-in, hay existing customers.
- Bạn xử lý bounce và complaint như thế nào? — Có suppression list không, có xử lý SNS notifications từ SES không.
- Volume dự kiến là bao nhiêu? — Số email/ngày và tốc độ tăng trưởng.
Nghĩ về request này như một cuộc phỏng vấn ngắn với AWS Trust & Safety team. Họ cần biết bạn hiểu email deliverability và sẽ không làm ảnh hưởng đến reputation của shared IP pool. Một description hai câu chung chung gần như chắc chắn sẽ bị bounce lại.
- Sau khi submit, AWS sẽ review request và gửi email thông báo kết quả về địa chỉ liên kết với AWS account.
- Nếu được approve,
ProductionAccessEnabledsẽ chuyển thànhtrue— verify lại bằng lệnhget-accountở trên. - Nếu bị reject hoặc yêu cầu thêm thông tin, AWS sẽ mở một Support case — trả lời trực tiếp trong case đó.
Setup Bounce và Complaint Handling — Không Phải Tùy Chọn
AWS yêu cầu bạn xử lý bounce và complaint notifications để duy trì sending reputation. Nếu bounce rate hoặc complaint rate vượt ngưỡng, SES có thể tạm dừng sending của account. Đây là điều bạn cần setup trước khi gửi email production, không phải sau.
Tạo SNS Topic Cho Notifications
aws sns create-topic \
--name ses-bounce-complaints \
--region us-east-1
Cấu Hình SES Gửi Notifications Đến SNS
aws sesv2 put-configuration-set-event-destination \
--configuration-set-name default \
--event-destination-name bounce-complaint-handler \
--event-destination '{"Enabled": true, "MatchingEventTypes": ["BOUNCE", "COMPLAINT"], "SnsDestination": {"TopicArn": "arn:aws:sns:us-east-1:123456789012:ses-bounce-complaints"}}' \
--region us-east-1
Nếu chưa có configuration set, tạo trước:
aws sesv2 create-configuration-set \
--configuration-set-name default \
--region us-east-1
IAM Policy Cho Lambda Xử Lý SNS Notifications
Nếu bạn dùng Lambda để xử lý bounce/complaint notifications từ SNS:
🔽 Click để xem IAM policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ses:PutSuppressedDestination"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/*"
}
]
}
Khi nhận được bounce notification, thêm địa chỉ đó vào SES account-level suppression list để tránh gửi lại:
aws sesv2 put-suppressed-destination \
--email-address bounced@customer.com \
--reason BOUNCE \
--region us-east-1
Bẫy Thực Tế: Misdiagnosis Mất 3 Giờ
Đây là pattern xảy ra thường xuyên hơn bạn nghĩ. Team nhận được lỗi MessageRejected: Email address is not verified và bắt đầu debug ở tầng application — kiểm tra lại SDK configuration, IAM permissions, thậm chí network connectivity. Tất cả đều ổn.
Sau đó họ verify thêm vài địa chỉ email test và thấy gửi được — kết luận vội vàng là 'vấn đề đã fix'. Deploy lại production, lỗi quay lại ngay lập tức.
Nguyên nhân thực sự: account vẫn ở Sandbox Mode. Địa chỉ test gửi được vì đã được verify. Địa chỉ khách hàng thì không. Lỗi Email address is not verified trong Sandbox Mode không có nghĩa là địa chỉ gửi của bạn có vấn đề — nó có nghĩa là địa chỉ nhận chưa được verify trong account của bạn.
Fix đúng: chạy aws sesv2 get-account, xác nhận ProductionAccessEnabled: false, submit production access request. Không có shortcut nào khác.
Kiểm Tra Trạng Thái Sau Khi Được Approve
aws sesv2 get-account \
--region us-east-1
Output sau khi được approve:
{
"ProductionAccessEnabled": true,
"SendQuota": {
"Max24HourSend": 50000.0,
"MaxSendRate": 14.0,
"SentLast24Hours": 0.0
},
"SendingEnabled": true
}
Sending quota sau khi thoát Sandbox phụ thuộc vào những gì bạn request và đánh giá của AWS. Nếu cần tăng thêm, submit thêm một request tăng quota riêng.
Wrap-Up: SES Sandbox Mode Và Các Bước Tiếp Theo
SES Sandbox Mode không phải lỗi — đó là cơ chế bảo vệ mặc định của AWS cho mọi account mới. Vấn đề chỉ xảy ra khi bạn không biết mình đang ở trong đó và bắt đầu debug sai tầng.
Checklist trước khi go-live với SES production:
- ☑ Verify sending domain với DKIM
- ☑ Setup configuration set với bounce/complaint notifications đến SNS
- ☑ Implement suppression list handling
- ☑ Submit production access request với use case description đầy đủ
- ☑ Xác nhận
ProductionAccessEnabled: truebằng CLI sau khi approve - ☑ Nhớ repeat cho mỗi region bạn dùng SES
Tham khảo thêm: AWS SES — Moving out of the Amazon SES sandbox và Monitoring SES sending activity.
Glossary — Thuật Ngữ Chính
| Thuật ngữ | Giải thích |
|---|---|
| Sandbox Mode | Trạng thái mặc định của SES account mới — chỉ gửi được đến verified addresses |
| Verified Identity | Email address hoặc domain đã được xác nhận ownership trong SES |
| Sending Quota | Giới hạn số email tối đa có thể gửi trong 24 giờ và tốc độ gửi tối đa |
| Bounce Rate | Tỷ lệ email bị từ chối bởi mail server đích — ảnh hưởng trực tiếp đến sending reputation |
| Suppression List | Danh sách địa chỉ SES sẽ tự động bỏ qua để tránh gửi lại sau bounce hoặc complaint |
| Configuration Set | Tập hợp các rule áp dụng cho một nhóm email — dùng để routing events đến SNS, CloudWatch, v.v. |
Nhận xét
Đăng nhận xét