Email learning series
What happens after my application sends an email through AWS SES?
By Pedro Paiva
Our application needs to send a welcome email to reader@example.net. We have the recipient’s address, a subject, and the message body. We use Amazon Simple Email Service (SES) (An AWS service that sends email on behalf of applications and reports sending outcomes.) to send it.
The API call (A request from one program to another service using a defined interface.) succeeds and returns a message ID. It’s tempting to mark the email as delivered and move on. But that response only tells us about the first part of the process. Let’s follow the welcome email through the rest.
Sending the message to SES
For our example, we call the SES v2 SendEmail API through an AWS SDK (An AWS software development kit: libraries that help code call AWS services and authenticate requests.), the AWS library for our programming language. We provide a verified sender address or domain, reader@example.net as the recipient, and our welcome message. The SDK makes an authenticated HTTPS (HTTP protected by TLS, encrypting the connection between the application and the service.) request, so the connection to SES is encrypted.
An application that uses an SMTP mail client (Software that submits outgoing email using the Simple Mail Transfer Protocol.) can instead connect to a regional SES endpoint with SES SMTP credentials and TLS encryption (Transport Layer Security protects data while it travels across a connection. It does not encrypt stored email or guarantee encryption on every later hop.). Either path hands the message to SES. We’ll use the API here.
SES accepts our request for processing and returns a MessageId. We can save that ID alongside our own record of the welcome email. At this point, our application knows the submission succeeded. It doesn’t know whether the recipient’s mail server has accepted anything yet.
Finding the next server
SES now has our message. But where should it send it?
The address gives us a starting point: example.net is the recipient’s domain. SES needs to find the mail servers responsible for that domain. The domain may use another company to host its mail, so we can’t guess the server from the address.
That information comes from DNS (The Domain Name System publishes records that help software find services for a domain, including its receiving mail servers.), which publishes records about domains. For email delivery, the relevant records are called MX records (Mail exchanger DNS records name the servers that receive email for a domain and give their preference order.), short for mail exchanger records. The domain might publish something like this:
example.net. MX 10 mx1.example.net.
example.net. MX 20 mx2.example.net.
These are made-up records for our example. The numbers set the preference: lower numbers come first, so mx1.example.net is preferred. DNS also resolves the server’s name to an IP address (A network address used to connect to a server. A server name can resolve to one or more IP addresses.) that SES can connect to.
DNS tells SES where to connect, but doesn’t check whether reader is a valid mailbox. The receiving mail system decides that. SES handles this lookup and onward delivery for us.
Handing over the welcome email
SES connects to the receiving server and uses SMTP (The Simple Mail Transfer Protocol is the set of commands and replies used to submit and transfer email between mail systems.) to transfer the message. SMTP lets the servers exchange the sender, recipient, and email content, with replies that report whether each part worked. We’ll save the command-by-command conversation for the next article.
For now, the important result is the receiving server’s final reply after the message data. If it accepts the message, it takes responsibility for delivering it or passing it to another server. Accepting the recipient address earlier in the conversation isn’t enough to establish that the whole message was accepted.
Our application doesn’t see this exchange in the original API response. It happens after we’ve handed the welcome email to SES. We need later feedback to know how it went.
What happens inside the receiving system
Even after the receiving server accepts our welcome email, there’s another step: getting it into the recipient’s mailbox.
The mail system applies its own filters and rules. The message might land in the inbox or the spam folder. Sender authentication, reputation, and content can influence that decision. Acceptance by the server doesn’t tell us which folder it chose, or whether the recipient read the email.
There can also be a failure after acceptance. The server might accept the message and only later discover that it can’t deliver it. A failure reported at that point is called an asynchronous bounce (A delivery failure reported after a mail server has already accepted the message.).
So our example has three separate outcomes to keep track of:
Application → SES: submission accepted; message ID returned
SES → receiving server: accepted after message data
Receiving mail system: inbox, spam folder, or a later failure
Keeping our application informed
That leaves our application with a gap. Its send request is finished, but the welcome email can still be delivered, fail, or generate a complaint. SES notifications or event publishing give us updates after the initial call.
If the receiving server accepts the welcome email, SES can publish a delivery event (An SES update saying the receiving mail server accepted the message; it does not confirm inbox placement or that the recipient read it.). We can record that the recipient’s server accepted it. This event doesn’t report inbox placement.
If reader@example.net doesn’t exist, the receiving server may reject the message and SES can report a bounce (A report that delivery failed permanently or that SES stopped retrying a temporary failure.). Temporary problems, such as a busy server, can lead to retries. SES reports a bounce when delivery fails permanently or it stops retrying a temporary failure.
If the recipient gets our welcome email and marks it as spam, SES may receive that feedback and publish a complaint event (An SES update based on feedback that a recipient marked the message as spam, when the mail provider shares that feedback.). Not every provider shares complaint feedback with SES. A missing complaint event isn’t proof that nobody complained.
We need to configure these updates and have our application handle them. Matching their SES message ID to our welcome-email record lets us track what happened after the send request ended.
Saved only in this browser until you clear it. Reading progress isn’t sent to us.