Work project
Hyper-Personalized Email at Scale
Emails that send themselves, with each subscriber's name and segment
Nightly results for two lottery brands plus welcome and birthday emails, each one carrying the name and segment of the person who receives it.

What it is about
These automations build and send the emails of the lottery brands the agency serves, the results email every night through Amazon SES and the ones a subscriber event triggers, such as a welcome or a birthday.
The results email is built from the official API and waits for the draws published late. Recipients come from Zoho Analytics, each email carries the person's name and segment, and the delivery events come back to PostgreSQL. The results are also exposed by a Spring Boot API with Thymeleaf templates.
What it does
- A Python script queries the results API, fills a Jinja2 template that holds only variables and writes the HTML ready for the Amazon SES template.
- Emails that a subscriber event triggers, such as the welcome and the birthday greeting.
- Recipients come from a Zoho Analytics view through its bulk export API; each email carries the person's name and segment, and a column of the file can assign another template.
- When a draw is not published yet, the script exits with its own code and the pipeline retries every 10 minutes, up to 9 times, before sending what was published.
- Sending spreads the emails across several workers with a per-second limit and, when Amazon SES asks to slow down, waits a random time that grows with each attempt.
- It notices when the history's pagination returns repeated rows and asks for the day again with other page sizes until it is complete.
- The email weighs 55 to 75 KB, under the size at which Gmail clips it, and the subject carries the date so Gmail does not thread every day's send together.
- A FastAPI receiver with asyncpg stores in PostgreSQL the delivery events Amazon SNS reports for each email.
- A Spring Boot API with Thymeleaf exposes the same results as JSON and as an HTML template.
How it works
From the API to the inbox
The nightly pipeline reads the API, takes the recipients from Zoho Analytics and sends; the delivery events come back to PostgreSQL.
Source
- Official results API
- Paginated history of previous days
- Recipients from Zoho Analytics
Nightly pipeline
- Cron on the server
- Jinja2 template that holds only variables
- Retries every 10 minutes
Delivery and measurement
- Amazon SES
- Delivery events through Amazon SNS
- PostgreSQL
Decisions and their costs
Wait for late draws, with a limit
The API publishes some draws more than an hour late.
Templates that hold only variables
A design change must never alter a figure, and an IDE formatter broke a template once.
A subject with the date
With a fixed subject, Gmail threads every day's send into one conversation.
One template a day, each person's data at send time
Each email carries the recipient's name.
Stack
Pick a technology to see the projects that use it.



