Cloud Native Email Automation with AWS SES, Python, Flask, and Jinja2
Email automation is a crucial component of modern enterprise applications, and Amazon Simple Email Service (AWS SES) provides a robust platform for handling scalable email communications. In this comprehensive guide, we'll explore how to create a custom email automation system using AWS SES, Python Flask, and Jinja2 - perfect for businesses seeking secure, cloud-native email solutions.
Overview
We'll build a cloud-native email system that can:
- Generate dynamic email templates
- Create reports using email templates
- Send formatted HTML emails through AWS SES
Setting Up the Email Template System
1. Creating Custom HTML Email Templates
First, let's create a professional HTML email template using Jinja2 for business process automation:
html<!DOCTYPE html> <html> <head> <style> .body { font-family: Arial, sans-serif; } table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid black; padding: 8px; text-align: left; } </style> </head> <body> <div> <p>Dear {{ full_name }},</p> <p>Here is your report for {{ today_ordinal_format }}:</p> <table> <tr> <th>Metric</th> <th>Amount</th> </tr> <tr> <td>Funds In</td> <td>£{{ fund_in }}</td> </tr> <tr> <td>Funds Out</td> <td>£{{ fund_out }}</td> </tr> </table> <p>Best regards,<br> {{ sender_name }}<br> {{ designation }}<br> {{ phone_number }}</p> </div> </body> </html>
<br>
2. Implementing the Email Microservice API
Let's create a Flask-based microservice API to generate our email templates:
pythonfrom flask import Flask, Response from jinja2 import Environment, FileSystemLoader import boto3 @email_api.route("/template", methods=["GET"]) @user_required() def get_email_template(access_token): # Get required parameters client_id = request.args.get("clientId") fund_in = request.args.get("fundIn") fund_out = request.args.get("fundOut") # Get user details from Cognito name, designation, phone_number = get_email_signature_details(access_token) # Generate template template = email_service.fetch_email_template( client_id, fund_in, fund_out, name, designation, phone_number ) return Response(template, content_type="text/html")
<br>
2.1 User Details and Email Signature Management
A key part of our system is retrieving user details from AWS Cognito for email signatures. Here's how we implement this:
pythondef get_email_signature_details(access_token): """ Retrieve user details from AWS Cognito for email signature. Args: access_token: AWS Cognito access token Returns: tuple: (name, designation, phone_number) """ client = boto3.client("cognito-idp") user = client.get_user(AccessToken=access_token) name = "" designation = "" phone_number = "" for item in user["UserAttributes"]: if item["Name"] == "name": name = item["Value"] elif item["Name"] == "custom:designation": designation = item["Value"] elif item["Name"] == "phone_number": phone_number = item["Value"] return name, designation, phone_number
2.2 Custom Template Generation
Our scalable template generation process combines authenticated user details with dynamic content:
pythondef fetch_email_template( self, client_id, fund_in, fund_out, name, designation, phone_number, ): """ Generate email template with dynamic content. Args: client_id: Client identifier fund_in: Incoming funds amount fund_out: Outgoing funds amount name: Sender's full name designation: Sender's designation phone_number: Sender's contact number Returns: str: Rendered HTML template """ try: # Initialize Jinja2 environment env = Environment(loader=FileSystemLoader("templates")) template = env.get_template("report_email_template.html") # Get client information client_basic_info = self._get_client_info(client_id) full_name = client_basic_info["full_name"] # Format dates today = datetime.date.today() today_ordinal_format = format_ordinal_date(today) # e.g., "1st January 2024" day_month_year_format_today = today.strftime("%d/%m/%Y") # Extract first name for personalized signing sender_first_name = self._extract_first_name(name) # Render template with all required variables email_content = template.render( full_name=full_name, today_ordinal_format=today_ordinal_format, day_month_year_format_today=day_month_year_format_today, fund_in=fund_in, fund_out=fund_out, sender_name=name, designation=designation, phone_number=phone_number, sender_first_name=sender_first_name, ) return email_content except Exception as e: return None, str(e)
3. Email: Composition and Sending
The core email sending functionality leverages AWS SES for reliable enterprise communication:
pythonfrom email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText def compose_email(client_id, email_content, sender, is_monthly, to_date): # Create MIME message msg = MIMEMultipart("mixed") msg["From"] = sender msg["To"] = recipients msg["Subject"] = f"{client_name} - Report {to_date}" # Attach HTML content msg_body = MIMEMultipart("alternative") htmlpart = MIMEText(email_content.encode("utf-8"), "html", "utf-8") msg_body.attach(htmlpart) msg.attach(msg_body) return msg.as_string() def send_email(email_content): try: response = ses_client.send_raw_email( RawMessage={"Data": email_content} ) return {"status": "success", "message_id": response["MessageId"]} except ClientError as e: raise ServiceException(e.response["Error"]["Message"])
Enterprise-Grade Features and Best Practices
Cloud-Native Template ManagemenT:
- Implement separate template storage using Jinja2's
FileSystemLoader - Enable DevOps-friendly template versioning
- Support regulatory compliance requireme
Secure Error Handling:
- Implement comprehensive error handling for template generation
- Maintain detailed logging for compliance
- Monitor email delivery status
Enterprise MIME Handling:
- Professional formatting for multipart emails
- Support for rich HTML content
- Maintain consistent branding across templates
Dynamic Content Integration:
- Real-time data injection into templates
- Support for personalized content
- Business process automation integration
Secure Authentication:
- AWS Cognito integration for enterprise security
- Role-based access control
- Audit trail implementation
<br>
Security Considerations
- Always validate email recipients
- Use proper authentication for API endpoints
- Sanitize input data before injecting into templates
- Keep AWS credentials secure and use IAM roles
- Implement rate limiting for email sending
<br>
Conclusion
AWS SES combined with Flask and Jinja2 provides a powerful foundation for building an email automation system. By following these patterns, you can create a robust, scalable email service that handles both simple and complex use cases.
Remember to:
- Test templates thoroughly before sending
- Monitor AWS SES sending quotas
- Keep templates maintainable and modular
- Handle edge cases and errors gracefully
This system can be extended to handle more complex scenarios like A/B testing, analytics tracking, and dynamic content based on user preferences.




