Avoiding Common Pitfalls: The Best Approach to AWS SES Integration in Flask

Saurav Jaiswal

  1. Jan 07, 2025
  2. 4 min read

Email functionality is crucial for any web application. Whether it's for sending registration confirmations, password resets, or system alerts, ensuring emails are sent reliably is a top priority. AWS Simple Email Service (SES) provides a powerful, scalable, and cost-effective solution for sending emails in Flask applications. However, many developers run into common pitfalls when setting up AWS SES.

In this post, we'll explore the best approach to integrate AWS SES into Flask and highlight common mistakes to avoid. By the end of this post, you'll have a solid, clean implementation that ensures reliable and secure email delivery.

Why AWS SES?

AWS SES is a cloud-based email sending service that is both cost-effective and highly reliable. Here’s why you should consider using AWS SES for email functionality in Flask:

  • Cost-Effective: AWS SES is affordable, especially if you're sending a high volume of emails. It has a generous free tier, and additional email costs are low.
  • Scalable and Reliable: With AWS SES, you don't have to worry about email deliverability or server downtime.
  • Simple API: SES provides a simple, flexible API that is easy to integrate into Flask.

Setting Up AWS Configuration and Credentials

Before diving into the Flask implementation, you must configure your AWS credentials. These credentials are used by boto3 to authenticate with AWS services like SES.

  1. Credentials File (~/.aws/credentials):

[default]
aws_access_key_id=YOUR_ACCESS_KEY
aws_secret_access_key=YOUR_SECRET_KEY

2. Config File (~/.aws/config):


[default]
region=us-east-1

Common Pitfalls to Avoid When Using AWS SES

While integrating AWS SES into Flask is straightforward, many developers run into common issues:

  • Unverified Email Addresses: You can only send emails to verified email addresses in the SES sandbox environment.
  • Lack of Proper IAM Permissions: Incorrect IAM roles or policies may block your ability to send emails through SES.
  • Not Handling SES Errors Gracefully: If SES fails, not handling the error properly can cause your application to fail silently or crash.
  • Ignoring SES Sending Limits: AWS SES imposes sending limits that may affect how many emails you can send, especially in the sandbox environment.

By addressing these issues in advance, you can ensure that your email functionality is secure and reliable.

The Right Way to Set Up AWS SES in Flask

Let’s break down the correct approach to integrating AWS SES with Flask. We’ll walk through the setup process step by step, highlight the logic behind it, and ensure that we avoid common mistakes.

Step 1: Install Required Libraries

Before we start coding, let’s install the libraries needed for this project. Specifically, we’ll use boto3, the official AWS SDK for Python. Boto3 enables your Flask application to interact with AWS services, including SES, in a simple and Pythonic way.

What is boto3?

Boto3 is the AWS SDK for Python, allowing Python applications to interact with AWS services programmatically. With boto3, you can perform tasks such as:

  • Sending emails using AWS SES.
  • Uploading files to Amazon S3.
  • Interacting with DynamoDB, EC2, and other AWS services.

For this guide, we’ll use boto3 to handle email sending via AWS SES. Its simple API allows seamless integration of AWS services into your Python application.

Install boto3 and Flask

To begin, install the required libraries using pip:


pip install boto3 flask

Step 2: Initialize AWS SES in Flask

Next, initialize the SES client in Flask. This connects your Flask application to AWS SES using the credentials and configuration defined earlier.


from flask import Flask
import boto3

app = Flask(__name__)

ses_client = boto3.client('ses', region_name='us-east-1')

Step 3: Create a Function to Send Emails

Define a send_email function to handle email sending using AWS SES. This function will support both HTML and plain text email bodies.


def send_email(sender_email, recipient_email, subject, html_body, text_body=None):
    """
    Sends an email using AWS SES.

    :param sender_email: Verified email address in SES to send the email from.
    :param recipient_email: Email address to send the email to.
    :param subject: Subject of the email.
    :param html_body: HTML content of the email.
    :param text_body: Optional plain-text content of the email for fallback.

    """
    try:
        message = {
            "Source": sender_email,
            "Destination": {
                "ToAddresses": [recipient_email]
            },
            "Message": {
                "Subject": {"Data": subject},
                "Body": {
                    "Html": {"Data": html_body}
                }
            }
        }
        if text_body:
            message["Message"]["Body"]["Text"] = {"Data": text_body}

        response = ses_client.send_email(**message)

        if response is None:
            raise Exception("SES response is None")
        
        return {"success": True, "response": response}

    except (BotoCoreError, ClientError) as e:
        return {"success": False, "error": f"Error sending email: {str(e)}"}
    except Exception as e:
        return {"success": False, "error": str(e)}

Step 4: Define the Flask Route to Handle Requests

We now create a Flask route that accepts a POST request to send the email. This route will receive a JSON payload containing the email details, call the send_email function, and return the result to the user.

Below is an example of the JSON structure you need to send in the API request:


{
  "sender_email": "verified_sender@example.com",
  "recipient_email": "recipient@example.com",
  "subject": "Welcome to Our Service!",
  "html_body": "<h1>Hello, John!</h1><p>Welcome to our service.</p>",
  "text_body": "Hello, John! Welcome to our service."
}

Here’s the route implementation in Flask:


@app.route('/send-email-api', methods=['POST'])
def send_email_api():
    """
    API endpoint to send an email using AWS SES.
    """
    try:
        data = flask.request.json
        required_fields = ["sender_email", "recipient_email", "subject", "html_body"]
        missing_fields = [field for field in required_fields if field not in data]
        if missing_fields:
            return flask.jsonify(success = False, error = f"Missing fields: {', '.join(missing_fields)}")

        sender_email = data["sender_email"]
        recipient_email = data["recipient_email"]
        subject = data["subject"]
        html_body = data["html_body"]
        text_body = data.get("text_body") 

        result = send_email(sender_email, recipient_email, subject, html_body, text_body)

        if result["success"]:
            return flask.jsonify(success= True, message= "Email sent successfully!", response = result["response"])
        else:
            return flask.jsonify(success = False, error = result["error"])

    except Exception as e:
        return flask.jsonify(success = False, error = str(e))


if __name__ == '__main__':
    app.run(debug=True)

Key Improvements and Refinements

  • Error Handling: We've implemented proper error handling using BotoCoreError and ClientError from the botocore package. This ensures that if AWS SES encounters any issues, your Flask application doesn't crash unexpectedly and provides a clear error message to the user.
  • Optional Plain-Text Content: If the email includes an HTML body, we optionally add a plain-text version of the body as a fallback. This ensures that recipients who cannot view HTML emails still receive the content in a readable format.
  • Input Validation: The route validates that all required fields are provided in the JSON payload. This avoids issues where missing fields could cause failures when calling AWS SES.

Why This Approach Works

  • Reliability: By handling errors and validating inputs, this implementation ensures that your email sending functionality is robust and scalable.
  • Maintainability: The clear separation between logic (sending emails) and Flask route (handling API requests) makes it easy to maintain and extend the application.
  • Flexibility: The ability to send both HTML and plain-text emails allows you to cater to a wide variety of email clients, ensuring maximum compatibility.

Conclusion

Integrating AWS SES into your Flask application is a straightforward and efficient way to handle email functionality. By following best practices, you can avoid common mistakes like failing to verify email addresses, mishandling SES errors, or sending emails without proper content formatting.

In this post, we’ve shown you the right approach to integrate AWS SES into Flask, highlighting how to send both HTML and plain-text emails, handle errors gracefully, and avoid the most common pitfalls that developers face when using SES. With this guide, you'll be well-equipped to implement email functionality in your Flask applications securely and efficiently.

About Author
Saurav Jaiswal

See What Our Clients Say

Mindgap

Incentius has been a fantastic partner for us. Their strong expertise in technology helped deliver some complex solutions for our customers within challenging timelines. Specific call out to Sujeet and his team who developed custom sales analytics dashboards in SFDC for a SoCal based healthcare diagnostics client of ours. Their professionalism, expertise, and flexibility to adjust to client needs were greatly appreciated. MindGap is excited to continue to work with Incentius and add value to our customers.

Samik Banerjee

Founder & CEO

World at Work

Having worked so closely for half a year on our website project, I wanted to thank Incentius for all your fantastic work and efforts that helped us deliver a truly valuable experience to our WorldatWork members. I am in awe of the skills, passion, patience, and above all, the ownership that you brought to this project every day! I do not say this lightly, but we would not have been able to deliver a flawless product, but for you. I am sure you'll help many organizations and projects as your skills and professionalism are truly amazing.

Shantanu Bayaskar

Senior Project Manager

Gogla

It was a pleasure working with Incentius to build a data collection platform for the off-grid solar sector in India. It is rare to find a team with a combination of good understanding of business as well as great technological know-how. Incentius team has this perfect combination, especially their technical expertise is much appreciated. We had a fantastic time working with their expert team, especially with Amit.

Viraj gada

Gogla

Humblx

Choosing Incentius to work with is one of the decisions we are extremely happy with. It's been a pleasure working with their team. They have been tremendously helpful and efficient through the intense development cycle that we went through recently. The team at Incentius is truly agile and open to a discussion in regards to making tweaks and adding features that may add value to the overall solution. We found them willing to go the extra mile for us and it felt like working with someone who rooted for us to win.

Samir Dayal Singh

CEO Humblx

Transportation & Logistics Consulting Organization

Incentius is very flexible and accommodating to our specific needs as an organization. In a world where approaches and strategies are constantly changing, it is invaluable to have an outsourcer who is able to adjust quickly to shifts in the business environment.

Transportation & Logistics Consulting Organization

Consultant

Mudraksh & McShaw

Incentius was instrumental in bringing the visualization aspect into our investment and trading business. They helped us organize our trading algorithms processing framework, review our backtests and analyze results in an efficient, visual manner.

Priyank Dutt Dwivedi

Mudraksh & McShaw Advisory

Leading Healthcare Consulting Organization

The Incentius resource was highly motivated and developed a complex forecasting model with minimal supervision. He was thorough with quality checks and kept on top of multiple changes.

Leading Healthcare Consulting Organization

Sr. Principal

US Fortune 100 Telecommunications Company

The Incentius resource was highly motivated and developed a complex forecasting model with minimal supervision. He was thorough with quality checks and kept on top of multiple changes.

Incentive Compensation

Sr. Director

Most Read
Building a Simple E-Invoicing Solution with AWS Lambda and Flask

In today’s fast-moving distribution industry, efficiency is everything. Distributors need quick, reliable tools to handle tasks like generating invoices and e-way bills. That’s why we created a serverless e-invoicing solution using AWS Lambda and Flask—keeping things simple, cost-effective, and secure. Here’s how we did it and the benefits it brought to distributors.

Yash Pukale

  1. Nov 13, 2024
  2. 4 min read
Scaling Data Analytics with ClickHouse

In the modern data-driven world, businesses are generating vast amounts of data every second, ranging from web traffic, IoT device telemetry, to transaction logs. Handling this data efficiently and extracting meaningful insights from it is crucial. Traditional databases, often designed for transactional workloads, struggle to manage this sheer volume and complexity of analytical queries.

Kartik Puri

  1. Nov 07, 2024
  2. 4 min read
From Pandas to ClickHouse: The Evolution of Our Data Analytics Journey

At Incentius, data has always been at the heart of what we do. We’ve built our business around providing insightful, data-driven solutions to our clients. Over the years, as we scaled our operations, our reliance on tools like Pandas helped us manage and analyze data effectively—until it didn’t.

The turning point came when our data grew faster than our infrastructure could handle. What was once a seamless process started showing cracks. It became clear that the tool we had relied on so heavily for data manipulation—Pandas—was struggling to keep pace. And that’s when the idea of shifting to ClickHouse began to take root.

But this wasn’t just about switching from one tool to another; it was the story of a fundamental transformation in how we approached data analytics at scale.

Chetan Patel

  1. Oct 28, 2024
  2. 4 min read
Designing Beyond Aesthetics: How UI Shapes the User Experience in Enterprise Solutions

UI design in enterprise solutions goes beyond aesthetics, focusing on enhancing usability and user satisfaction. By emphasizing clarity, visual hierarchy, feedback, and consistency, UI improves efficiency and productivity, allowing users to navigate complex tasks seamlessly.

Mandeep Kaur

  1. Oct 23, 2024
  2. 4 min read