Emails Setup in Django Using AWS

Steve YonkeuSteve Yonkeu
5 min read

In the early days, communication relied on letters that took days or weeks to deliver. The internet revolutionized this with the advent of emails, providing instantaneous and reliable messaging. From there businesses quickly adopted this tool for customer communication, transactional updates, and marketing, valuing the speed and direct connection it offered. For developers, integrating email functionality into applications has become essential. AWS (Amazon Web Services) provides not only a robust but also a cheap solution for setting up email services, allowing developers to automate and streamline communication within their Django applications.

Let's dive into a quick implementation of this using AWS and Django. We will be using a couple of ideas from the AWS Official Blog.

  • What is Django?
    Django is a free, open-source Python web framework designed to simplify the creation of complex, database-driven websites. It emphasizes reusability, rapid development, and clean design. Django handles many common web development tasks, allowing developers to focus on unique features for their applications. Personally, I consider it quickest way to kickstart a web application.

  • What is AWS?
    Amazon Web Services (AWS) is a comprehensive cloud computing platform offering over 200 services. It provides on-demand resources like computing power, storage, databases, and machine learning tools for individuals, businesses, and governments. AWS operates on a pay-as-you-go model, allowing users to scale resources based on their needs.

Why AWS?

Price:
1-- After a few comparison I came to the conclusion that this will be our most cost effective option.

Email ServiceFree TierPrice per 10,000 EmailsAdditional Features
AWS SES62,000 emails per month (when sent from Amazon EC2)$1 (after 62,000 free tier)Flexible, scalable, and cost-effective
SendGrid100 emails/day (3,000 emails/month)$9.95 for 10,000 emailsAdvanced analytics, templates, API
Mailgun5,000 emails/month for 3 months$35 for 10,000 emailsEmail validation, detailed logs, analytics
Mailchimp10,000 emails/month for 3 months$30 for 10,000 emailsMarketing automation, templates, analytics
PostmarkNo free tier$10 for 10,000 emailsFast delivery, detailed stats, responsive support
Sendinblue300 emails/day (9,000 emails/month)$25 for 10,000 emailsMarketing automation, SMS, chat, CRM
SparkPost15,000 emails/month$20 for 10,000 emailsAdvanced analytics, templates, API
Mandrill (Mailchimp)No free tier$20 for 10,000 emailsTransactional email service, API

2 --Scalability:
AWS SES is highly scalable, allowing you to send millions of emails per day. Its robust infrastructure ensures that you can handle increased email volumes seamlessly as your business grows. Base on your needs you can easily step up.

3--Reliability:
AWS SES boasts high deliverability rates and strong security measures, ensuring that your emails reach their intended recipients reliably and safely. This reliability is critical for maintaining effective communication with your customers.

Setting Amazon SES(Simple Email Service)

  1. Let's get started

    AWS SES Home

  2. Enter Email, domain/subdomain and proceed

    Click the button

  3. Verify your email and domain

    Verification 1

    Verification 2

    Verification 3

  4. By default the account is in Sandbox mode and needs to be in production to send emails to emails not under the verified domain. It usually takes a couple of hours, maximum 24 hours to verify but it's worth it.

    Sandbox Account

Setting the Django project

This project being one tagged as beginner-friendly we need a few prerequisites for this. Already we need to have a Python environment properly setup. Also, a valid domain and email ready for use on this project. I got a random domain name and an email for this tutorial. Let's have a walk now...

  1. Creating Folder and Activating the virtual environment
mkdir DjangoSES && cd DjangoSES

python -m venv venv

# For Unix and Linux
source venv/bin/activate
  1. Installing the necessary packages or dependencies
pip install django boto3 python-dotenv
  1. Creating the Django Project and the Django app
# Creating the Django project
django-admin startproject aws_ses .

# We create an application for the project
python manage.py startapp emailer

At this moment, the current project structure is using the command below:

tree -I "venv|__pycache__" .

The Output below:

    .
    ├── aws_ses
    │   ├── __init__.py
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    ├── emailer
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
+   │   ├── forms.py
    │   ├── migrations
    │   │   └── __init__.py
    │   ├── models.py
    │   ├── tests.py
+   │   ├── urls.py
+   │   ├── utils.py
    │   └── views.py
    ├── manage.py
    └── requirements.txt
    ├── static
    └── templates
+   └── .env

At this point you should have this display on your browser when you run the command:

python manage.py runserver

Django Init Display

Writing some utils functions for the project

  1. A function to send emails
# .env
AWS_ACCESS_KEY_ID=your_access_key_id
AWS_SECRET_ACCESS_KEY=your_secret_access_key
AWS_REGION_NAME=your_aws_region
# aws_ses/settings.py
import os
from dotenv import load_dotenv

load_dotenv()

AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY')
AWS_REGION_NAME = os.getenv('AWS_REGION_NAME')
DEFAULT_FROM_EMAIL = os.getenv('DEFAULT_FROM_EMAIL')
# emailer/utils.py
import boto3
from botocore.exceptions import ClientError
from django.conf import settings

def send_ses_email(recipient, subject, body_text, body_html=None):
    client = boto3.client('ses', region_name=settings.AWS_REGION_NAME)

    try:
        response = client.send_email(
            Destination={
                'ToAddresses': [recipient],
            },
            Message={
                'Body': {
                    'Text': {
                        'Charset': 'UTF-8',
                        'Data': body_text,
                    },
                    'Html': {
                        'Charset': 'UTF-8',
                        'Data': body_html,
                    } if body_html else {},
                },
                'Subject': {
                    'Charset': 'UTF-8',
                    'Data': subject,
                },
            },
            Source=settings.DEFAULT_FROM_EMAIL,
        )
    except ClientError as e:
        print(f"An error occurred: {e.response['Error']['Message']}")
        return False
    else:
        print(f"Email sent! Message ID: {response['MessageId']}")
        return True

This project will be fully available on GitHub here

Conclusion

I thoroughly enjoyed working with AWS services to enhance the capabilities of Django applications. The versatility and robustness of AWS tools have made this project not only successful but also a great learning experience. As we continue to explore and integrate AWS services into our future projects, I am excited about the potential to innovate and optimize our applications further. For more insights and updates on upcoming projects utilizing AWS, please visit my website and follow my social media channels. Let's stay connected and push the boundaries of what we can achieve with AWS and Django. Stay tuned for more!

10
Subscribe to my newsletter

Read articles from Steve Yonkeu directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Steve Yonkeu
Steve Yonkeu

Code with Django, Deploy with Ease.