Django email backend implementation compatible with SendGrid API v5+ for seamless email delivery integration
—
Django settings integration for configuring SendGrid API access, tracking options, sandbox mode, debugging features, and other SendGrid-specific behaviors. All configuration is handled through Django's settings system.
Essential configuration settings that must be provided for the backend to function.
# Required in settings.py
SENDGRID_API_KEY = str # SendGrid API key for authentication
EMAIL_BACKEND = "sendgrid_backend.SendgridBackend" # Django email backend# settings.py
import os
EMAIL_BACKEND = "sendgrid_backend.SendgridBackend"
SENDGRID_API_KEY = os.environ.get("SENDGRID_API_KEY")
# Validate API key presence
if not SENDGRID_API_KEY:
raise ImproperlyConfigured("SENDGRID_API_KEY environment variable is required")Settings for SendGrid API endpoint and connection parameters.
SENDGRID_API_KEY = str # SendGrid API key (required)
SENDGRID_HOST_URL = str # API endpoint URL (optional)Standard US endpoint (default):
# settings.py
SENDGRID_API_KEY = "SG.your-api-key-here"
# SENDGRID_HOST_URL defaults to https://api.sendgrid.comEU endpoint configuration:
# settings.py
SENDGRID_API_KEY = "SG.your-eu-api-key-here"
SENDGRID_HOST_URL = "https://api.eu.sendgrid.com"Multiple environment configuration:
# settings.py
import os
# Different API keys per environment
if os.environ.get("ENVIRONMENT") == "production":
SENDGRID_API_KEY = os.environ["SENDGRID_PROD_API_KEY"]
elif os.environ.get("ENVIRONMENT") == "staging":
SENDGRID_API_KEY = os.environ["SENDGRID_STAGING_API_KEY"]
else:
SENDGRID_API_KEY = os.environ["SENDGRID_DEV_API_KEY"]Control email delivery behavior in development and testing environments.
SENDGRID_SANDBOX_MODE_IN_DEBUG = bool # Enable sandbox in DEBUG mode (default: True)
SENDGRID_ECHO_TO_STDOUT = bool # Echo emails to stdout (default: False)Development environment setup:
# settings.py
DEBUG = True
# Prevent accidental email sending in development
SENDGRID_SANDBOX_MODE_IN_DEBUG = True # Emails won't be delivered
# Enable debug output
SENDGRID_ECHO_TO_STDOUT = True # Print emails to consoleProduction environment setup:
# settings.py
DEBUG = False
# Ensure emails are delivered in production
SENDGRID_SANDBOX_MODE_IN_DEBUG = False # Not used when DEBUG=False anyway
# Disable debug output
SENDGRID_ECHO_TO_STDOUT = FalseTesting environment setup:
# test_settings.py
DEBUG = True
# Force sandbox mode for tests
SENDGRID_SANDBOX_MODE_IN_DEBUG = True
# Capture email output for testing
SENDGRID_ECHO_TO_STDOUT = TrueConfigure email open and click tracking behavior for all emails sent through the backend.
SENDGRID_TRACK_EMAIL_OPENS = bool # Track email opens (default: True)
SENDGRID_TRACK_CLICKS_HTML = bool # Track clicks in HTML content (default: True)
SENDGRID_TRACK_CLICKS_PLAIN = bool # Track clicks in plain text (default: True)Full tracking enabled (default):
# settings.py
SENDGRID_TRACK_EMAIL_OPENS = True
SENDGRID_TRACK_CLICKS_HTML = True
SENDGRID_TRACK_CLICKS_PLAIN = TruePrivacy-focused configuration:
# settings.py - Minimal tracking for privacy compliance
SENDGRID_TRACK_EMAIL_OPENS = False
SENDGRID_TRACK_CLICKS_HTML = False
SENDGRID_TRACK_CLICKS_PLAIN = FalseSelective tracking configuration:
# settings.py - Track opens but not clicks
SENDGRID_TRACK_EMAIL_OPENS = True
SENDGRID_TRACK_CLICKS_HTML = False
SENDGRID_TRACK_CLICKS_PLAIN = FalseSettings for webhook signature verification and event processing.
SENDGRID_WEBHOOK_VERIFICATION_KEY = str # Webhook signature verification key# settings.py
SENDGRID_WEBHOOK_VERIFICATION_KEY = os.environ.get("SENDGRID_WEBHOOK_KEY")
# Webhook endpoint configuration
WEBHOOK_ENDPOINTS = {
'sendgrid_events': '/webhooks/sendgrid/events/',
'sendgrid_inbound': '/webhooks/sendgrid/inbound/',
}Backend initialization parameters that can override Django settings at runtime.
# SendgridBackend.__init__() parameters
api_key = str # Override SENDGRID_API_KEY
host = str # Override SENDGRID_HOST_URL
stream = io.TextIOBase # Custom output stream for echoing
fail_silently = bool # Error handling behaviorCustom backend instance:
from sendgrid_backend import SendgridBackend
import sys
# Override settings for specific use case
custom_backend = SendgridBackend(
api_key="different-api-key",
host="https://api.eu.sendgrid.com",
stream=sys.stderr, # Custom output stream
fail_silently=True
)
# Use custom backend
messages = [EmailMessage(...)]
sent_count = custom_backend.send_messages(messages)The backend performs automatic validation of configuration settings.
# Validation errors raised
ImproperlyConfigured # Missing or invalid required settings
ValueError # Invalid parameter values (e.g., ip_pool_name length)API key validation:
# Will raise ImproperlyConfigured if no API key provided
try:
backend = SendgridBackend()
except ImproperlyConfigured as e:
print("SendGrid configuration error:", e)
# Handle missing API keyParameter validation:
from django.core.mail import EmailMessage
msg = EmailMessage(from_email="test@example.com", to=["recipient@example.com"])
# Invalid IP pool name (too short)
msg.ip_pool_name = "x" # Must be 2-64 characters
try:
msg.send()
except ValueError as e:
print("Invalid IP pool name:", e)Best practices for managing configuration across different environments.
# base_settings.py
EMAIL_BACKEND = "sendgrid_backend.SendgridBackend"
# Default tracking settings
SENDGRID_TRACK_EMAIL_OPENS = True
SENDGRID_TRACK_CLICKS_HTML = True
SENDGRID_TRACK_CLICKS_PLAIN = True
# development_settings.py
from .base_settings import *
DEBUG = True
SENDGRID_API_KEY = os.environ.get("SENDGRID_DEV_API_KEY")
SENDGRID_SANDBOX_MODE_IN_DEBUG = True
SENDGRID_ECHO_TO_STDOUT = True
# production_settings.py
from .base_settings import *
DEBUG = False
SENDGRID_API_KEY = os.environ.get("SENDGRID_PROD_API_KEY")
SENDGRID_HOST_URL = "https://api.eu.sendgrid.com" # EU compliance
# Disable debug features
SENDGRID_ECHO_TO_STDOUT = False
# testing_settings.py
from .base_settings import *
DEBUG = True
SENDGRID_API_KEY = "test-key" # Fake key for testing
SENDGRID_SANDBOX_MODE_IN_DEBUG = True
# Capture output for test assertions
SENDGRID_ECHO_TO_STDOUT = TrueHelper functions for working with Django settings in the context of SendGrid configuration.
def get_django_setting(setting_str, default=None):
"""
Safely retrieve Django setting with fallback default.
Parameters:
- setting_str (str): Name of Django setting
- default: Default value if setting not found
Returns:
Setting value or default
"""from sendgrid_backend.util import get_django_setting
# Safe setting retrieval with defaults
sandbox_mode = get_django_setting("SENDGRID_SANDBOX_MODE_IN_DEBUG", True)
track_opens = get_django_setting("SENDGRID_TRACK_EMAIL_OPENS", True)
api_timeout = get_django_setting("SENDGRID_API_TIMEOUT", 30)
# Use in custom configuration logic
if get_django_setting("CUSTOM_EMAIL_THROTTLING", False):
# Apply custom rate limiting
passConstants for detecting SendGrid API version compatibility.
# Available from sendgrid_backend.util
SENDGRID_VERSION: str # SendGrid package version string
SENDGRID_5: bool # True if using SendGrid v5.x
SENDGRID_6: bool # True if using SendGrid v6.xfrom sendgrid_backend.util import SENDGRID_5, SENDGRID_6, SENDGRID_VERSION
# Check SendGrid version for compatibility
if SENDGRID_6:
# Use v6-specific features like dynamic_template_data
msg.dynamic_template_data = {"name": "John"}
else:
# Use v5-compatible substitutions
msg.substitutions = {"name": "John"}
# Log version information
print(f"Using SendGrid version: {SENDGRID_VERSION}")Utility function for converting dictionary data to SendGrid Personalization objects.
def dict_to_personalization(data: dict) -> Personalization:
"""
Convert dictionary to SendGrid Personalization object.
Reverses Sendgrid's Personalization.get() method to create a
Personalization object from its emitted data structure.
Parameters:
- data (dict): Dictionary containing personalization data
Returns:
- Personalization: SendGrid Personalization object
"""from sendgrid_backend.util import dict_to_personalization
# Convert dictionary to Personalization object
personalization_data = {
"to": [{"email": "user@example.com", "name": "User"}],
"dynamic_template_data": {"name": "John", "product": "Widget"},
"custom_args": {"campaign": "spring_sale"}
}
personalization = dict_to_personalization(personalization_data)
# Use in EmailMessage
msg = EmailMessage(from_email="sender@example.com")
msg.personalizations = [personalization]
msg.send()Install with Tessl CLI
npx tessl i tessl/pypi-django-sendgrid-v5