Skip to main content

A Django email backend for Amazon SES with bounce and complaint handling

Project description

django_aws_ses

A Django email backend for Amazon Simple Email Service (SES), featuring bounce and complaint handling, unsubscribe functionality, and robust integration with Django’s email system. Developed by ZeeksGeeks.

Features

  • Seamless integration with Django’s email framework using a custom SES backend.
  • Handles AWS SES bounce and complaint notifications via SNS.
  • Secure unsubscribe functionality.
  • Django Admin dashboard for SES statistics (superusers only).
  • Optional DKIM signing support (requires dkimpy).

Installation

Follow these steps to install and configure django_aws_ses in your Django project.

Prerequisites

  • Python 3.6 or higher
  • Django 3.2 or higher
  • An AWS account with SES access
  • Verified email address or domain in AWS SES

Step 1: Install the Package

Install django_aws_ses from PyPI:

pip install django-aws-ses

For development or testing, include development dependencies:

pip install django-aws-ses[dev]

For DKIM signing support (optional):

pip install django-aws-ses[dkim]

This installs core dependencies:

  • django>=3.2
  • boto3>=1.18.0
  • requests>=2.26.0
  • cryptography>=3.4.7
  • dnspython>=2.1.0

Step 2: Configure Django Settings

Add django_aws_ses and required Django apps to INSTALLED_APPS in your settings.py:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites',
]
Configure AWS SES credentials and the email backend:

Option 1: IAM Role (Recommended for AWS environments)

# No AWS credentials needed in settings
AWS_SES_REGION_NAME = 'us-east-1'
AWS_SES_REGION_ENDPOINT = 'https://email.us-east-1.amazonaws.com'
EMAIL_BACKEND = 'django_aws_ses.backends.SESBackend'
DEFAULT_FROM_EMAIL = 'no-reply@yourdomain.com'

Option 2: Access Keys

AWS_SES_ACCESS_KEY_ID = 'your-access-key-id'
AWS_SES_SECRET_ACCESS_KEY = 'your-secret-access-key'

Optional: Enable debugging logs for troubleshooting:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django_aws_ses': {
            'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}

Step 3: Set Up URLs

Include the django_aws_ses URLs in your project’s urls.py:

from django.urls import path, include

urlpatterns = [
    path('aws_ses/', include('django_aws_ses.urls', namespace='django_aws_ses')),
]

This enables endpoints for bounce/complaint handling (https://yourdomain.com/aws_ses/bounce/), user-based unsubscribe (https://yourdomain.com/aws_ses/unsubscribe/<uuid>/<token>/), and email-only unsubscribe (https://yourdomain.com/aws_ses/unsubscribe/email/<encoded_email>/<token>/).

Step 4: Apply Migrations

Run migrations to create the django_aws_ses models (e.g., BounceRecord, ComplaintRecord, SendRecord, AwsSesUserAddon):

python manage.py migrate

Step 5: Configure AWS SES

Follow these detailed steps to set up Amazon SES in your AWS account for use with django_aws_ses:

  1. Sign Up for AWS SES:

  2. Verify Sender Email or Domain:

    • In the SES console, go to "Verified identities."
    • Click "Create identity":
      • Email Address: Enter the sender email (e.g., no-reply@yourdomain.com). AWS sends a verification email; click the link to verify.
      • Domain: Enter your domain (e.g., yourdomain.com). Add provided DNS records (TXT, CNAME, MX) to your DNS provider to verify ownership.
    • Docs: https://docs.aws.amazon.com/ses/latest/dg/creating-identities.html
  3. Create IAM Credentials:

  4. Set Up SNS Notifications:

  5. (Optional) Configure DKIM Signing:

  6. Test SES Configuration:

  7. Exit Sandbox Mode (Production):

Usage

django_aws_ses integrates with Django’s email API and provides additional features for SES-specific functionality. The following examples are shown in a Python console (e.g., Django shell or within a view).

Sending a Basic Email

Use Django’s send_mail for simple emails:

from django.core.mail import send_mail

send_mail(
    subject='Test Email',
    message='This is a test email from django_aws_ses.',
    from_email='no-reply@yourdomain.com',  # Must be SES-verified
    recipient_list=['recipient@example.com'],
    fail_silently=False,
)
  • Set fail_silently=False to raise exceptions for debugging (e.g., unverified email errors).

Sending HTML Emails

Send emails with HTML content and plain text fallback:

from django.core.mail import EmailMultiAlternatives

subject = 'Welcome to Our Platform'
from_email = 'no-reply@yourdomain.com'
to = 'recipient@example.com'
text_content = 'Thank you for joining our platform!'
html_content = '<p>Thank you for joining! <a href="https://yourdomain.com">Visit us</a></p>'

email = EmailMultiAlternatives(subject, text_content, from_email, [to])
email.attach_alternative(html_content, 'text/html')
email.send()

Sending Email Attachments

Send emails with attachments using EmailMultiAlternatives:

from django.core.mail import EmailMultiAlternatives

subject = 'Document from Our Platform'
from_email = 'no-reply@yourdomain.com'
to = 'recipient@example.com'
text_content = 'Please find the attached document.'

email = EmailMultiAlternatives(subject, text_content, from_email, [to])
email.attach('document.pdf', open('path/to/document.pdf', 'rb').read(), 'application/pdf')
email.send()
  • Note: Amazon SES limits the total email size, including attachments, to 10MB. Ensure attachments are within this limit to avoid delivery failures.

Handling Bounce and Complaint Notifications

  • Bounce and complaint notifications are processed via the SNS endpoint (/aws_ses/bounce/).
  • Records are stored in the BounceRecord and ComplaintRecord models.
  • View bounce/complaint data in the Django Admin or SES dashboard (/aws_ses/status/).
  • Configure additional SNS notifications for deliveries in SES console.
  • Docs: https://docs.aws.amazon.com/ses/latest/dg/monitor-sending-activity.html

Generating Unsubscribe Links

Add secure unsubscribe links to emails:

from django_aws_ses.models import AwsSesUserAddon

user = User.objects.get(email='recipient@example.com')
addon = AwsSesUserAddon.objects.get_or_create(user=user)[0]
unsubscribe_url = addon.unsubscribe_url_generator()
# Include in email template, e.g., <a href="{{ unsubscribe_url }}">Unsubscribe</a>
  • Users clicking the link are redirected to /aws_ses/unsubscribe/<uuid>/<token>/, which marks them as unsubscribed.
  • Customize the unsubscribe view or template in django_aws_ses/templates/django_aws_ses/unsubscribe.html.

Generating Unsubscribe Links for Non-User Emails

For mailing lists or launch notifications where recipients may not have accounts, use EmailUnsubscribe:

from django_aws_ses.models import EmailUnsubscribe

emails = ['recipient@example.com', 'other@example.com']

# Bulk get-or-create unsubscribe records
existing = {u.email: u for u in EmailUnsubscribe.objects.filter(email__in=emails)}
to_create = [EmailUnsubscribe(email=e) for e in emails if e not in existing]
if to_create:
    EmailUnsubscribe.objects.bulk_create(to_create, ignore_conflicts=True)
    all_unsubs = {u.email: u for u in EmailUnsubscribe.objects.filter(email__in=emails)}
else:
    all_unsubs = existing

for email in emails:
    unsub = all_unsubs.get(email)
    if unsub and unsub.unsubscribed:
        continue
    unsubscribe_url = unsub.unsubscribe_url_generator()
    # append unsubscribe_url to the email body before sending
  • Links point to /aws_ses/unsubscribe/email/<encoded_email>/<token>/ and are self-authenticating — no session or login required.
  • Run python manage.py migrate django_aws_ses after upgrading to create the EmailUnsubscribe table.

Viewing SES Statistics

Debugging and Error Handling

  • Enable debug logging (see Step 2) to troubleshoot SES errors.
  • Common issues:
    • Unverified email/domain: Verify in SES console.
    • IAM permissions: Ensure AmazonSESFullAccess and AmazonSNSFullAccess.
    • SNS endpoint errors: Confirm HTTPS endpoint is publicly accessible.
  • Check BounceRecord and ComplaintRecord in Django Admin for failed deliveries.

Rate Limiting and Throttling

Changelog

For a detailed list of changes, improvements, and fixes across versions, see CHANGELOG.md.

Contributors

Developed by the ZeeksGeeks team. See CONTRIBUTORS.md for individual contributors and their roles.

Contributing

We welcome contributions! Please follow these steps:

  1. Fork the repository: https://github.com/zeeksgeeks/django_aws_ses
  2. Create a branch: git checkout -b feature/your-feature
  3. Commit changes: git commit -m 'Add your feature'
  4. Push: git push origin feature/your-feature
  5. Open a Pull Request.

See CONTRIBUTORS.md for current contributors.

License

This project is licensed under the MIT License. See LICENSE for details.

PyPI Distribution

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_aws_ses-0.1.6.tar.gz (94.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_aws_ses-0.1.6-py3-none-any.whl (93.0 kB view details)

Uploaded Python 3

File details

Details for the file django_aws_ses-0.1.6.tar.gz.

File metadata

  • Download URL: django_aws_ses-0.1.6.tar.gz
  • Upload date:
  • Size: 94.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for django_aws_ses-0.1.6.tar.gz
Algorithm Hash digest
SHA256 bfccf3b851fee081338222710b5753f1b5b7e0015965aedac904dfc4f8811066
MD5 5849c6ba23b9ba813eda43f29f051a93
BLAKE2b-256 80ffcf91412dc257ea6f1e3ee3108ac207be1c872f2cf37967224b0ce70cfd52

See more details on using hashes here.

File details

Details for the file django_aws_ses-0.1.6-py3-none-any.whl.

File metadata

  • Download URL: django_aws_ses-0.1.6-py3-none-any.whl
  • Upload date:
  • Size: 93.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for django_aws_ses-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 2967d1440c27ae471bb9c48535effa0918b9b701f619d7bc0d2aa56bb5859372
MD5 1dba0ad4d8bea1553df65f0c1804a5cf
BLAKE2b-256 984a6f3a638e8200e87d72c1451cdf566b3487f7830b239e9d4bd6ff1d546bd1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page