Случилась у нас бяда – AWS отключил нам отправку писем через AWS SES из-за bounce-рейта.
Проверить это можно в AWS SES > Reputation Dashboard, аккаунт сейчас в статусе Under review:
После обращения в тех. поддержку отправку почты нам временно включили, но решить проблему надо, а заодно – следить, что бы подобное не случалось в будущем.
Содержание
Bounce и Complaint rate
Запретить отправку почты AWS может по двум причинам – завышенный Bounce rate и завышенный Complaint rate. В случае высокого рейтинга – почтовые сервера могут помечать сервер отправки как “спамера”, и блокировать приходящие с него письма вообще, что, разумеется, негативно сказывается на AWS SES, а потому они достаточно активно следят за этими показателями и могут (и отключают) отправку с этого SES-аккаунта.
Кратко рассмотрим, что такое Bounce и Compliant рейтинги, а потом настроим мониторинг с CloudWatch и Prometheus, что бы в Slack получать уведомления о превышении пороговых значений – 5% bounce, и свыше 1% compliant rates.
Общие советы по уменьшению Bounce rate можно найти в What can I do to minimize bounces?
Bounce rate
Bounce rate определяет, какая часть получателей не получила отправленного письма, см. Bounce Rate.
Считается как (кол-во bounced / кол-во отправленных всего) * 100, например:
[simterm]
>>> (10.0/10000)*100 0.1
[/simterm]
Тут получаем 0.1% – отличный результат, если бы был реальным 🙂
Hard and Soft Bounce
При этом различают два типа bounce – hard и soft.
- Hard bounce: при “жёстком” отказе – сервер получателя отказывается принимать письмо вообще. Обычно это возникает из-за ошибок типа отсутствия ящика получателя на сервере, домена, в который отправляется письмо, или если сервер вообще отказывается получать какие-либо письма
- Soft bounce: сюда входят письма, которые сервер получателя принял и передал в пользовательский почтовый ящик, но не смог его доставить туда из-за, например, превышения ящиком дисковой квоты или размера письма
Complaint rate
Complaint rate считается, когда пользователь явно уведомляет, что он не хочет получать письма, например через кнопку “Report spam” в своём почтовом клиенте, или отправив жалобу напрямую AWS SES.
AWS SES CloudWatch metrics
Для алертинга используем метрики CloudWatch для AWS SES:
- Sends: общее количество отправленных писем
- Deliveries: общее количество доставленных писем
- Bounces: сервер получателя отказался доставлять письмо в ящик (считаются hard bounces)
- Complaints: письмо было доставлено получателю, но он отметил его как спам
Плюс дополнительно уже посчитаны значения для Bounce и Complaint – Reputation.BounceRate и Reputation.ComplaintRate.
Сейчас наше значение для Reputation.BounceRate == 0.1432, т.е. 14%:
(в конце этого поста рейтинг будет уже 18% – за сутки набрали ещё 4%)
Можно создать алерты используя сам AWS CloudWatch Alerts и SNS, см. Creating reputation monitoring alarms using CloudWatch, либо собирать метрики во внешнюю систему мониторинга, и слать алерты через неё.
В нашем случае, будем собирать в Prometheus, который через свой Alertmanager будет слать алерты в Opsgenie, а из него уже – нам в Slack.
Настройка Prometheus CloudWatch Exporter
Вообещ, мы используем yet-another-cloudwatch-exporter, но в случае с метриками для AWS SES он выводил полную ерунду, в Guthub Issues на вопросы отвечают редко, да и вообще он производит впечатление заброшенного проекта, хотя апдейты периодически выкатывают.
Поэтому для SES отдельно используем стандартный експортер, см. Prometheus: CloudWatch exporter — сбор метрик из AWS и графики в Grafana.
Его конфиг:
region: us-east-1 set_timestamp: false delay_seconds: 60 metrics: - aws_namespace: AWS/SES aws_metric_name: Send - aws_namespace: AWS/SES aws_metric_name: Delivery - aws_namespace: AWS/SES aws_metric_name: Bounce - aws_namespace: AWS/SES aws_metric_name: Complaint - aws_namespace: AWS/SES aws_metric_name: Reputation.BounceRate - aws_namespace: AWS/SES aws_metric_name: Reputation.ComplaintRate
Для проверки метрик можно запустить скрипт из поста AWS: SES — Simple Email Service и WorkMail: настройка аккаунта и отправка почты, который раз в 10 секунд отправляет письмо:
[simterm]
$ watch -n 10 ./ses_email.py
[/simterm]
Добавим графики в Grafana:
Сравним их с метриками в самом CloudWatch, что бы убедиться, что всё считается верно:
И осталось добавить алерт.
Prometheus alert
Но тут возникает проблема.
Из графика видно, что Bounce Rate выводится неравномерно:
Примерно раз в 20 минут запускается наша рассылка (5-6 отправок в минуту на графике – это тестовые, создаваемые запущенным выше скриптом), и сразу же появляются значения для метрики aws_ses_reputation_bounce_rate_sum
.
Если использовать самый простой алерт типа:
- alert: AWSSESReputationBounceRate expr: aws_ses_reputation_bounce_rate_sum{job="aws_ses"} * 100 > 5 for: 1s labels: severity: warning annotations: summary: 'AWS SES Bounce rate too high' description: 'Latest observed value: {{ $value | humanize }} %' tags: aws
То он будет активироваться и закрываться раз в те же 20 минут.
Что можно сделать?
Как вариант – использовать avg_over_time()
, и делать выборку по данным за последние, например, 10 минут – тогда получим ровный график:
Обновляем алерт (тут задал 1 час):
- alert: AWSSESReputationBounceRate expr: avg_over_time(aws_ses_reputation_bounce_rate_sum{job="aws_ses"}[1h]) * 100 > 5 for: 1s labels: severity: warning annotations: summary: 'AWS SES Bounce rate too high' description: 'Latest observed value: {{ $value | humanize }} %' tags: aws
И получаем алерт в Slack:
Готово.