Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

django-cloudflare-email

A Django email backend for Cloudflare Email Service (public beta, April 2026).

Send transactional email through Cloudflare's first-party email API with full support for HTML, attachments, cc/bcc, reply-to, and custom headers.

Installation

pip install django-cloudflare-email

Or with uv:

uv add django-cloudflare-email

Requirements: Python 3.11+, Django 4.2+

Configuration

Add the following to your Django settings:

# settings.py

EMAIL_BACKEND = "django_cloudflare_email.backend.CloudflareEmailBackend"

# Your Cloudflare account ID (found in the Cloudflare dashboard)
CLOUDFLARE_ACCOUNT_ID = "your-account-id"

# A Cloudflare API token with Email Send permissions
CLOUDFLARE_API_TOKEN = "your-api-token"

Getting your credentials

  1. Log in to the Cloudflare dashboard
  2. Find your Account ID in the right sidebar on any zone page
  3. Create an API Token at dash.cloudflare.com/profile/api-tokens with the Email Send permission

Basic usage

Once configured, use Django's standard email API:

from django.core.mail import send_mail, EmailMultiAlternatives

# Plain text
send_mail(
    subject="Hello from Cloudflare",
    message="Plain text body",
    from_email="noreply@example.com",
    recipient_list=["user@example.com"],
)

# HTML email with plain-text fallback
msg = EmailMultiAlternatives(
    subject="Welcome!",
    body="Welcome to our service.",  # plain-text fallback
    from_email="welcome@example.com",
    to=["newuser@example.com"],
)
msg.attach_alternative("<p>Welcome to our service.</p>", "text/html")
msg.send()

Display names

From/To addresses support RFC 5322 display names:

from django.core.mail import EmailMessage

msg = EmailMessage(
    subject="Hello",
    body="Body text",
    from_email="My App <noreply@example.com>",
    to=["Alice Smith <alice@example.com>"],
    reply_to=["Support Team <support@example.com>"],
)
msg.send()

Attachments

from django.core.mail import EmailMessage

msg = EmailMessage(
    subject="Report attached",
    body="Please find the report attached.",
    from_email="reports@example.com",
    to=["manager@example.com"],
)

# Attach bytes directly
with open("report.pdf", "rb") as f:
    msg.attach("report.pdf", f.read(), "application/pdf")

msg.send()

Custom headers

msg = EmailMessage(...)
msg.extra_headers = {
    "X-Campaign-Id": "summer-2026",
    "X-Mailer": "MyApp/1.0",
}
msg.send()

Error handling

All errors are subclasses of CloudflareEmailError:

from django_cloudflare_email.exceptions import (
    CloudflareEmailError,
    CloudflareEmailThrottledError,
    CloudflareEmailDisabledError,
    CloudflareEmailInvalidAddressError,
)

try:
    msg.send()
except CloudflareEmailThrottledError:
    # HTTP 429 or CF error code 10004 — back off and retry
    time.sleep(60)
    msg.send()
except CloudflareEmailDisabledError:
    # CF error code 10203 — sending is disabled for this account
    logger.error("Cloudflare Email sending is disabled")
except CloudflareEmailInvalidAddressError as e:
    # CF error code 10200 — invalid recipient or sender address
    logger.error("Invalid address: %s", e)
except CloudflareEmailError as e:
    # Catch-all for any other Cloudflare error
    logger.error("Email send failed (code %s): %s", e.error_code, e)

Exception hierarchy

Exception CF Code HTTP Meaning
CloudflareEmailSchemaError 10001 200 Request body failed schema validation
CloudflareEmailInternalError 10002 5xx Cloudflare internal error
CloudflareEmailThrottledError 10004 429 Rate limited
CloudflareEmailInvalidAddressError 10200 200 Invalid email address
CloudflareEmailContentLengthError 10201 200 Missing or invalid content length
CloudflareEmailTooLargeError 10202 200 Message too large
CloudflareEmailDisabledError 10203 200 Sending disabled for account

fail_silently

Django's fail_silently flag is respected. When True, errors are logged but not raised:

msg.send(fail_silently=True)

Or configure at the backend level via connection:

from django.core.mail import get_connection

connection = get_connection(fail_silently=True)
msg = EmailMessage(..., connection=connection)
msg.send()

Development

git clone https://github.com/yudame/django-cloudflare-email
cd django-cloudflare-email
uv sync --all-extras
pytest tests/ -v

License

MIT. See LICENSE.

Links

About

Django email backend for Cloudflare Email Service

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages