Registry / communication / django-anymail

django-anymail

JSON →
library15.1pypypi✓ verified 25d ago

Django Anymail provides a unified interface for sending transactional emails and receiving webhooks across many Email Service Providers (ESPs) like SendGrid, Mailgun, Postmark, and more. It integrates seamlessly with Django's `EmailBackend` and `send_mail` functions, adding advanced features like ESP-specific options, transactional tracking, and inbound email signals. The library is actively maintained with frequent releases, currently at version 14.0, and supports various Django and Python versions.

pip install django-anymail
INSTALL
IMPORT
SIG · DJANGO-ANYMAIL
D
django-anymail
communicationpythonv15.1
Install
4.1s avg
Import
Disk
70MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v15.1 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.910 runs
installs and imports cleanly · install 0.0s · import 0.000s · 70.6MB
glibc
py 3.103.910 runs
installs and imports cleanly · install 4.1s · import 0.000s · 71MB
70MB installed
● package 70MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

VERSION
from anymail import VERSION
from anymail.webhooks.views import AnymailWebhooksView

This quickstart demonstrates how to configure and use django-anymail to send emails via an ESP (Mailgun is used as an example). It shows both the standard `send_mail` function and the extended `AnymailMessage` for ESP-specific features like tags. Remember to replace placeholder API keys and recipient emails. For a real Django project, the `settings.configure` block is not needed, as settings would be in your project's `settings.py`.

import os from django.conf import settings from django.core.mail import send_mail from anymail.message import AnymailMessage # --- Minimal Django settings configuration for standalone execution --- # In a real Django project, these settings would be in your settings.py file. # This block ensures the script can run without a full Django project setup. if not settings.configured: settings.configure( ANYMAIL={ "MAILGUN_API_KEY": os.environ.get("ANYMAIL_MAILGUN_API_KEY", "your-mailgun-api-key"), "MAILGUN_SENDER_DOMAIN": os.environ.get("ANYMAIL_MAILGUN_SENDER_DOMAIN", "mg.example.com"), # For other ESPs, replace MAILGUN_API_KEY/SENDER_DOMAIN with appropriate keys/settings }, EMAIL_BACKEND="anymail.backends.mailgun.EmailBackend", # Or your chosen ESP backend DEFAULT_FROM_EMAIL="sender@example.com", DEBUG=True, # Minimal required setting for settings.configure ) print("Attempting to send an email using Django's send_mail...") try: # Example 1: Basic email using Django's send_mail send_mail( subject="Hello from django-anymail!", message="This is a test email sent via Mailgun through django-anymail.", from_email=settings.DEFAULT_FROM_EMAIL, recipient_list=["recipient@example.com"], # Replace with a valid recipient email fail_silently=False, ) print("Basic email send attempt successful.") # Example 2: Using AnymailMessage for ESP-specific features (e.g., tags) message = AnymailMessage( subject="AnymailMessage with Tags", body="This email demonstrates using AnymailMessage with custom tags.", from_email=settings.DEFAULT_FROM_EMAIL, to=["recipient2@example.com"], # Replace with another valid recipient email ) message.tags = ["transactional", "test-tag"] # You can also add merge_data, metadata, etc. message.send(fail_silently=False) print("AnymailMessage with tags send attempt successful.") except Exception as e: print(f"\nFailed to send email: {e}") print("Please ensure your environment variables (e.g., ANYMAIL_MAILGUN_API_KEY, ANYMAIL_MAILGUN_SENDER_DOMAIN) ") print("are correctly set and your ESP configuration in settings.py is valid.") print("Note: In a real Django project, you'd only need the settings in settings.py ") print("and directly call send_mail or AnymailMessage.send().")
Debug
Known issues
breakingVersion 14.0 introduced improved Unicode handling that might surface new `AnymailUnicodeError` exceptions for previously silently-handled problematic non-ASCII characters. This helps identify and fix issues at the source.
fix
Review your email content and templates for non-ASCII characters. Consult the Anymail documentation's 'International email' section (https://anymail.dev/en/stable/tips/international_email/) for guidance on handling specific character sets and ESP limitations.
affects: >=14.0
breakingVersion 11.0 introduced breaking changes for Amazon SES and SparkPost. For Amazon SES, `anymail.message.AnymailMessage.esp_extra` now strictly requires a dictionary. For SparkPost, using `template_id` requires explicitly setting `use_org_defaults=True`.
fix
Update your `esp_extra` usage for Amazon SES to pass a dictionary (instead of a string). For SparkPost, ensure `use_org_defaults=True` is included in your template parameters when `template_id` is set.
affects: >=11.0
gotchaAnymail webhook views, designed to receive POST requests from external ESPs, are incompatible with Django's default CSRF protection. If not properly exempted, these webhook requests will be blocked.
fix
When configuring webhook URLs in `urls.py`, wrap `AnymailWebhooksView.as_view()` with `django.views.decorators.csrf.csrf_exempt`. Example: `path('anymail/webhooks/', csrf_exempt(AnymailWebhooksView.as_view()), name='anymail-webhooks')`.
affects: All versions
gotchaThe most common issue is incorrectly configuring the `ANYMAIL` dictionary in `settings.py` or omitting the specific ESP API key (e.g., `MAILGUN_API_KEY`, `SENDGRID_API_KEY`, `POSTMARK_API_TOKEN`). This will prevent Anymail from authenticating with your chosen ESP.
fix
Ensure `ANYMAIL = { 'YOUR_ESP_API_KEY': '...' }` is correctly defined in `settings.py`, and the key name matches the exact environment variable/setting name required by your chosen ESP as per Anymail documentation.
affects: All versions
Upgrade
Version history
15.1latest on PyPI · released Jul 30, 2026
Audit
Dependencies
DjangorequiredCore framework integration; requires Django >= 3.2
requestsrequiredUsed internally for HTTP requests to most ESP APIs
Agent activity
22 hits · last 30 days
node
20
OpenAI (training)
1
Resources
django-anymail — pip install django-anymail · libregistry