Amazon SES configuration and monitoring
If you are running or developing any kind of web application, inevitably you will at some point want to send transactional emails or even newsletters. If your application is deployed, or if you plan to deploy your app on AWS, then you are in the right place. We will discuss how to properly configure and monitor your email using Amazon SES (Simple email service).
First of all, let’s get the basics out of the way.
SPAM is bad, mkay!? Glad we sorted that out. Most people don’t like to get bombarded with SPAM, and service providers will impose strict rules or different kinds of technical measures to prevent SPAM outbreaks from their infrastructure.
AWS is no exception. By default, your new account will have SMTP throttling imposed on your EC2 instances. You can go two ways from here on.
- You can either request this limit to be removed and then send your transactional email from EC2 directly. However, this is really not an option when you start playing with a larger infrastructure, autoscaling and large numbers of instances.
- You can start using Amazon SES for all outgoing email from your applications. You can use SES even if you don’t use EC2 to host your app.
If you opted for the second option, please do continue reading as we will discuss the benefits of using SES and how to configure it properly.
Benefits of using Amazon SES
You don’t have to worry about maintaining mail servers, their reputation and enough capacity to meet the demands of your application.
From our experience, most of the email traffic is burstable, during newsletter campaigns, or during some high traffic events (black Fridays, etc.). Amazon SES will quickly chew through your demand with no additional cost of maintaining mail server infrastructure, you only pay for what you have used, or rather by the number of emails sent.
While we are at it, let’s talk about pricing. If you are sending from AWS infrastructure (EC2 instances for example), you get 62 000 emails free of charge each month. After that, you pay $0.10 per 1000 emails sent.
Now let’s talk about configuration
First thing you should know is that SES is not available in every region, so you will probably have to choose one of the closest ones to your application.
I will not guide you through the entire process step by step, as this is very well covered in AWS documentation. However, I will give you some general guidelines and steps to have SES appropriately configured.
Validating domain for sending
After choosing the region, you will need to validate the sending domain. You will want to generate DKIM records, and configure them in your DNS. If you are using Route53, then this last part can be automatic. Otherwise, you will need to configure DKIM TXT records by hand in your DNS.
It will take some time to verify DNS records, and once this is done, the domain will be in a verified state.
Removing sandbox requirements
Just like with EC2, even SES is sandboxed by default to prevent accidental SPAM outbreaks. You can test SES out with your application in this mode; however, you will have to verify each recipient. To use SES in production, you will want to request sandbox limit removal using instructions in the link.
Creating sending credentials
You can use SES just like any other SMTP server; however, you will have to create a set of credentials for SMTP authentication. They are handled through IAM, and you can create SMTP credentials using instructions on this link.
Configure mail server or application
At this stage, you only need to point your application or mail server to use SES for mail delivery. There are various integration types covered in official AWS docs, either for sending email programmatically or sending via the mail server. It’s up to you to decide what works best for your case.
In either case, make sure you are sending your email from a domain that you verified in SES; otherwise, your email will be rejected by SES.
Verify everything is working
So at this point, you should be all good to send email from SES. Do and verify this works as intended for your case before declaring it production-ready.
Don’t get yourself banned
Even if everything is ok after testing, there are still some steps to do. Amazon SES has some limitations. You need to uphold your sender reputation to keep using SES. In that regard, you should monitor if your application is sending SPAM, either on purpose or by mistake.
Once your sender reputation drops, AWS will revoke your sending limits.
You can check your reputation using your AWS Console in SES > Reputation Dashboard. From there you can inspect your limits and detailed explanation of various statuses.
In a nutshell, you should keep your Bounce Rate below 5%, and if you ever reach 10%, your sending privileges might be revoked. Similarly, with complaint rate, you should keep it below 0.1%, and if you ever reach 0.5%, your sending privileges might be revoked.
What are those metrics?
Bounces should be self-explanatory; this metric covers all bounces to emails sent from SES. It is, however, worth noting that not all bounces are bad or accounted for in this metric. For example, out of office/vacation auto-responders, or bounces when the end user’s mailbox is full are considered transient bounces. Meaning they might get delivered at a later date.
Persistent bounces, on the other hand, are pure evil in SES’s eyes and are counted towards this limit. Those include bounces when recipients email server send a hard bounce but didn’t specify the reason, or when mail address is not present on the receiving server. Most commonly, users will mistype their email address.
Complaints are just that – some user has clicked the report spam button on your email, or SES received an abuse report for a specific email.
You should never try to send further emails to that address.
Enable the suppression list
Each account can enable its own account level suppression list for SES.
Suppression list gives you the ability to process bounces and complaints automatically, and add them to the account level deny list. Any further email that your application will send via SES will be still accepted and counted towards your monthly billing; however, no delivery attempts will be made, and those emails will not count towards your sender reputation.
By default, we recommend that you enable account level suppression list with BOUNCE and COMPLAINT reasons.
aws sesv2 put-account-suppression-attributes \ --suppressed-reasons BOUNCE COMPLAINT
In the link above you have few other examples on how to interact with account-level suppression lists, either by listing, adding or removing addresses to/from the list.
How do I know what’s happening with emails
If you are reading our blogs regularly, you should by now know that we advocate monitoring all the things.
In that regard, in this section, we will guide you on how you can configure early monitoring of SES delivery, bounce and complaint logs so that you can react to them and have insight on what’s happening.
We will configure Alerts as well so that we are notified ahead of time and have some buffer for our reaction time.
Alerting with Cloudwatch and SNS
We will be alerting with SNS when certain SES reputation thresholds are reached. To do so, you will need to create an SNS topic with a subscription. The easiest way to get notified is by email, so you can just follow this subscription process. You can also integrate SNS with any other notification methods such as Opsgenie, Pagerduty and so on… however, this is out of the scope of this guide.
To create actual alarms, you will use CloudWatch, so head over to CloudWatch console. You need to create at least two alarms, one for bounce rate, other for complaint rate. In each case, the process is the same, and you can follow the official documentation. I’ll just point out some sensible defaults for each metric.
For bounce rate:
Selected metric: SES > AccountMetrics > Reputation.BounceRate
Threshold: 2.5
For complaint rate:
Selected metrics: SES >AccountMetrics > Reputation.ComplaintRate
Threshold: 0.5
Note that in some cases when you just configure SES, those metrics will not be available until first bounce or complaint is received. You can still create an alarm by specifying the metric in source in the “Source” tab when clicking the “Select metric” button.
{ "metrics": [ [ "AWS/SES", "Reputation.BounceRate", { "stat": "Average" } ] ], "view": "timeSeries", "stacked": false, "period": 300, "region": "eu-west-1" }
You will need to replace the region to your region and reputation.BounceRate to Reputation.ComplaintRate if creating that alarm.
Setting up logging
At this point, you are safe. You have suppression lists in place, and you have alarms in place to warn well before your sender reputation gets ruined totally.
However, you will not be any wiser when the alarm goes off. What you really need are some logs. Default metrics that Amazon SES is collecting in CloudWatch are just numbers; you don’t have any insights into what’s really going out, from where etc..
Let’s go to SNS again and create another topic named SES-Lambda. At this time you don’t need any subscriptions on this topic.
Yes as the name suggests, you will be using AWS Lambda for this. No need to panic, this will be a straightforward function, promise!
Go to Lambda functions in AWS console and create a function called ses-log with Python3.8 runtime.
When the function is created, paste this code and save the function.
import json def lambda_handler(event, context): message = event['Records'][0]['Sns']['Message'] print("From SNS: " + message) return message
All you need to do is add a Lambda trigger by clicking on the “Add trigger” button in the function overview. Select SNS and then find the SES-Lambda topic and click Add.
The Lambda part is done. See, wasn’t that scary.
Let’s get back to AWS SES domain list and configure notifications. What you will want is to configure SNS topic notification for each domain in your SES, so it looks like this:
Let’s recap what we have done so far. Each delivery, bounce or complaint including its headers will be sent to SNS topic SES-Lambda this will in turn fire up our custom lambda function named ses-log the sole purpose of this function is to print out SNS payload. And this will end up in Lambda’s CloudWatch logs interface.
Inspecting the logs
After a few deliveries, you should have some logs generated in CloudWatch Logs as /aws/lambda/ses-log Log group; you can go there and see if that’s the case. What you will see is lot’s of gibberish from Lambda execution as well, and this can be quite hard to track. This is where CloudWatch Log Insights comes in.
Make sure you select /aws/lambda/ses-log Log group and desired timeframe.
And try some queries listed below.
Mail deliveries
fields @timestamp, notificationType, mail.source as Sender, mail.destination.0 as Recepient1, mail.destination.1 as Recepient2, mail.commonHeaders.subject as Subject | filter notificationType = "Delivery" | sort @timestamp desc
Mail complaints
fields @timestamp, notificationType, mail.source as Sender, mail.destination.0 as Recepient1, mail.destination.1 as Recepient2, mail.commonHeaders.subject as Subject | filter notificationType = "Complaint" | sort @timestamp desc
Mail bounces
fields @timestamp, notificationType, mail.source as Sender, mail.destination.0 as Recepient1, mail.destination.1 as Recepient2, mail.commonHeaders.subject as Subject | filter notificationType = "Bounce" | sort @timestamp desc
Search for specific address
fields @timestamp, notificationType, mail.source as Sender, mail.destination.0 as Recepient1, mail.destination.1 as Recepient2, mail.commonHeaders.subject as Subject # Replace the CUSTOMER placeholder to query the logs for one specific address # make sure you select the appropriate time range in the time picker above | filter concat(mail.destination.0, mail.destination.1) like /CUSTOMER/ | sort @timestamp desc
Possibilities are endless
Now hopefully you are all set and have at least basic tools when you face alarms, and or issues with mail delivery.
This was just a quick demonstration of what is possible with Amazon SES, and you can go even further. For example, creating additional subscriptions on Bounce SNS topics to let you know when your email was not received. Maybe a user just made a typo in its mail address, by entering a gmali.com instead of gmail.com. Your customer support can fix that, and you will get that customer back.
If you have some specific case you would like to address with your email deliverability setup, we are here to help.
Get in touch with our experts and we’ll be happy to help.