Settings Guide¶
There are several settings available to ensure django-templated-email-md can be configured for your needs.
The only one that is required is TEMPLATED_EMAIL_BACKEND.
Core Settings¶
TEMPLATED_EMAIL_BACKEND¶
Default: None
Required: Yes
Type: String
Description: The backend class to use for processing Markdown email templates.
Example:
TEMPLATED_EMAIL_BACKEND = 'templated_email_md.backend.MarkdownTemplateBackend'
TEMPLATED_EMAIL_TEMPLATE_DIR¶
Default: ‘templated_email/’
Required: No
Type: String
Description: Directory where email templates are stored. Must include a trailing slash. This is set by default in the
django-templated-emailpackage.Example:
TEMPLATED_EMAIL_TEMPLATE_DIR = 'templated_email/'
Further Reading: Django Template Loading Documentation
TEMPLATED_EMAIL_FILE_EXTENSION¶
Default: ‘md’
Required: No
Type: String
Description: File extension for Markdown template files.
Example:
TEMPLATED_EMAIL_FILE_EXTENSION = 'md'
TEMPLATED_EMAIL_BASE_HTML_TEMPLATE¶
Default: ‘templated_email/markdown_base.html’
Required: No
Type: String
Description: Path to the base HTML template that wraps the Markdown content. See the usage guide for more information on available approaches to overriding the default template.
Example:
TEMPLATED_EMAIL_BASE_HTML_TEMPLATE = 'my_app/markdown_base.html'
Further Reading: Django Template Inheritance
Markdown Settings¶
TEMPLATED_EMAIL_MARKDOWN_EXTENSIONS¶
Default: [‘markdown.extensions.extra’, ‘markdown.extensions.meta’, ‘markdown.extensions.tables’]
Required: No
Type: List
Description: List of Markdown extensions to enable when processing templates.
Example:
TEMPLATED_EMAIL_MARKDOWN_EXTENSIONS = [
'markdown.extensions.extra',
'markdown.extensions.meta',
'markdown.extensions.tables',
'markdown.extensions.codehilite',
]
Further Reading:
Popular extensions:
URL Settings¶
TEMPLATED_EMAIL_BASE_URL¶
Default: None
Required: No
Type: String
Description: Base URL to prepend to relative URLs in email templates.
Example:
TEMPLATED_EMAIL_BASE_URL = 'https://example.com'
Further Reading:
Default Content Settings¶
TEMPLATED_EMAIL_DEFAULT_SUBJECT¶
Default: ‘Hello!’
Required: No
Type: String
Description: Default subject line used when no subject is provided in the template or context.
Example:
TEMPLATED_EMAIL_DEFAULT_SUBJECT = 'Message from Our Company'
TEMPLATED_EMAIL_DEFAULT_PREHEADER¶
Default: ‘’
Required: No
Type: String
Description: Default preheader text used when no preheader is provided in the template or context.
Example:
TEMPLATED_EMAIL_DEFAULT_PREHEADER = 'Important information from Our Company'
Further Reading: Email Preheader Best Practices (referred to in this blog as ‘preview text’)
Branding Settings¶
TEMPLATED_EMAIL_BRANDING¶
Default: See defaults table below
Required: No
Type: Dictionary
Description: Controls the visual branding of emails rendered by
MarkdownTemplateBackend. Any keys you provide are merged over the built-in defaults, so you only need to specify the values you want to override. The full set of defaults reproduces the original package styling exactly, ensuring backward compatibility.
Default values:
Key |
Default |
Description |
|---|---|---|
|
|
Button backgrounds and accents |
|
|
Hyperlink color |
|
|
Color for h1-h4 headings |
|
|
Body paragraph text color |
|
|
Page/email background color |
|
|
Inner content container background |
|
|
Font stack for body and headings |
|
|
URL of the logo image; empty = no logo rendered |
|
|
Alt text for the logo image |
|
|
Width of the logo image in pixels (as a string) |
Example:
TEMPLATED_EMAIL_BRANDING = {
"primary_color": "#e74c3c",
"link_color": "#e74c3c",
"heading_color": "#2c3e50",
"text_color": "#555555",
"background_color": "#f0f0f0",
"container_background": "#ffffff",
"font_family": "Georgia, serif",
"logo_url": "https://cdn.example.com/logo.png",
"logo_alt": "Acme Corp",
"logo_width": "180",
}
Tip: If you only want to change one or two colors, you can set just those keys and all other defaults will be preserved automatically.
Plain Text Generation Settings¶
TEMPLATED_EMAIL_HTML2TEXT_SETTINGS¶
Default: {}
Required: No
Type: Dictionary
Description: Configuration options for html2text when generating plain text versions of emails.
Some of the Available Options:
ignore_links: Exclude links from plain text outputignore_images: Exclude image descriptionsbody_width: Maximum line width before wrappingignore_emphasis: Exclude emphasis markersmark_code: Wrap code blocks with backtickswrap_links: Wrap URLs in angle brackets
Example:
TEMPLATED_EMAIL_HTML2TEXT_SETTINGS = {
'ignore_links': False,
'ignore_images': True,
'body_width': 0,
'ignore_emphasis': True,
'mark_code': False,
'wrap_links': False,
}
Further Reading: Available html2text Options
Error Handling Settings¶
TEMPLATED_EMAIL_FAIL_SILENTLY¶
Default: False
Required: No
Type: Boolean
Description: If True, suppresses exceptions during email rendering and sends fallback email instead.
Example:
TEMPLATED_EMAIL_FAIL_SILENTLY = True
HTML Sanitization Settings¶
Note: HTML sanitization requires the optional
nh3dependency. Install it with:pip install django-templated-email-md[sanitize]If
TEMPLATED_EMAIL_SANITIZE = Truebutnh3is not installed, email sending will raiseImportError- install the[sanitize]extra to resolve it. This error is raised even whenTEMPLATED_EMAIL_FAIL_SILENTLY = True, because silently skipping requested sanitization would be a security risk.
TEMPLATED_EMAIL_SANITIZE¶
Default:
FalseRequired: No
Type: Boolean
Description: When
True, sanitizes the HTML produced from the Markdowncontentblock before it is wrapped in the base template. Uses thenh3library (Python bindings for the Rustammoniacrate) to strip dangerous constructs such as<script>tags, event handler attributes (onclick, etc.), andjavascript:URLs. Defaults toFalsefor full backward compatibility - existing templates are unaffected unless you explicitly opt in.Important caveat:
nh3’s default allowlist is conservative. By default it stripsclassattributes and some table/button markup. Sanitization runs on the Markdowncontentfragment before it is wrapped in the base template, so the base template’s own classes are never affected - onlyclassattributes in raw HTML written directly in yourcontentblock (e.g.<div class="foo">placed inline in the Markdown source) will be stripped. If you use such markup, you must extend the allowlist viaTEMPLATED_EMAIL_SANITIZE_KWARGS. Users who render fully trusted template markup (e.g. no user-supplied context values reach the content block) may prefer to leave sanitization off.Example:
TEMPLATED_EMAIL_SANITIZE = True
TEMPLATED_EMAIL_SANITIZE_KWARGS¶
Default:
{}Required: No
Type: Dictionary
Description: Keyword arguments passed directly to
nh3.clean(). Use this to extend or restrict the default allowlists. Common keys include:tags:set[str]- allowed HTML tag names (overrides nh3 default allowlist).attributes:dict[str, set[str]]- maps tag names to sets of allowed attribute names. Note that passing this key overrides nh3’s entire default attribute allowlist, so include all attributes you need (not just the additions).url_schemes:set[str]- allowed URL schemes (default includeshttp,https,mailto).
Refer to the nh3 documentation for the full list of accepted keyword arguments.
Example (allow
classattribute on all elements):
TEMPLATED_EMAIL_SANITIZE = True
TEMPLATED_EMAIL_SANITIZE_KWARGS = {
"attributes": {
"*": {"class"},
"a": {"href", "title", "class"},
"img": {"src", "alt", "class"},
}
}
Note: nh3’s DEFAULT allowlist strips most attributes, including
classandtarget. Because sanitization runs on the Markdown-rendered content fragment, this has two consequences for the bundled components:(a) The shipped bulletproof partials (
templated_email/components/button.htmlanddivider.html) included from acontentblock will lose theirclass="btn btn-primary"/class="email-divider"andtargetattributes, so Premailer can no longer style them correctly.(b) Any
class-based styling written as raw HTML directly in yourcontentblock (e.g.<div class="foo">) is also removed.To keep those attributes, extend the allowlist via
TEMPLATED_EMAIL_SANITIZE_KWARGS(e.g. allowclasson the relevant tags, as shown in the example above).Important interaction with render caching: nh3 allowlists are typically expressed as Python
sets (e.g.{"class"}), and sets are not JSON-serializable. The render cache key is built withjson.dumps, so ifTEMPLATED_EMAIL_SANITIZE_KWARGScontains a set (or any other non-JSON-serializable value), render caching is silently skipped for those calls. If you want both sanitization with custom kwargs and caching, be aware of this limitation, or express allowlists in a JSON-serializable form where possible.
Complete Configuration Example¶
Here’s a complete example showing all settings with their default values:
# Email Backend Configuration
TEMPLATED_EMAIL_BACKEND = 'templated_email_md.backend.MarkdownTemplateBackend'
TEMPLATED_EMAIL_TEMPLATE_DIR = 'templated_email/'
TEMPLATED_EMAIL_FILE_EXTENSION = 'md'
TEMPLATED_EMAIL_BASE_HTML_TEMPLATE = 'templated_email/markdown_base.html'
# Markdown Extensions
TEMPLATED_EMAIL_MARKDOWN_EXTENSIONS = [
'markdown.extensions.extra',
'markdown.extensions.meta',
'markdown.extensions.tables',
]
# URL Configuration
TEMPLATED_EMAIL_BASE_URL = ''
# Default Content
TEMPLATED_EMAIL_DEFAULT_SUBJECT = 'Hello!'
TEMPLATED_EMAIL_DEFAULT_PREHEADER = ''
# Plain Text Generation
TEMPLATED_EMAIL_HTML2TEXT_SETTINGS = {
'ignore_links': False,
'ignore_images': True,
'body_width': 0,
'ignore_emphasis': True,
'mark_code': False,
'wrap_links': False,
}
# Error Handling
TEMPLATED_EMAIL_FAIL_SILENTLY = False
# HTML Sanitization (requires: pip install django-templated-email-md[sanitize])
TEMPLATED_EMAIL_SANITIZE = False
TEMPLATED_EMAIL_SANITIZE_KWARGS = {}
# Render Caching
TEMPLATED_EMAIL_CACHE_RENDERED = False
TEMPLATED_EMAIL_CACHE_TIMEOUT = 300
TEMPLATED_EMAIL_CACHE_ALIAS = "default"
Render Caching¶
The backend can cache the result of the full render pipeline (Markdown to HTML to CSS inlining to plain text) in Django’s cache framework. Caching is off by default to preserve the existing behaviour.
TEMPLATED_EMAIL_CACHE_RENDERED¶
Type |
Default |
|---|---|
|
|
Set to True to enable render caching. When enabled, the backend stores the
rendered {"html", "plain", "subject", "preheader"} dict in the cache under a
deterministic SHA-256 key. Subsequent renders with identical template name,
context, language, and base URL will be served from the cache, skipping the
expensive premailer.transform call.
The cache key incorporates the template name, context, active language, base URL, and all rendering-relevant settings - markdown extensions, html2text settings, sanitize flags, and branding. A change to any of these settings produces a different cache key, so cached HTML is never served after a settings change.
Note: Only contexts and settings whose values are JSON-serializable are
cached. If the context or TEMPLATED_EMAIL_SANITIZE_KWARGS contains values
that are not JSON-serializable (e.g. a set used as an nh3 allowlist, or a
model instance), caching is skipped for that call and the email is rendered
normally - this is a safe fallback, not an error.
Note: The cache key incorporates the template NAME, context, active language, base URL, and rendering-relevant settings (markdown extensions, html2text settings, sanitize flags, and branding) - but NOT the template file’s contents. If you edit a template file without changing any of those inputs, cached output continues to be served until the entry expires. After deploying changed templates, either flush the cache (or cycle the cache alias) or keep
TEMPLATED_EMAIL_CACHE_TIMEOUTshort relative to your deploy cadence.If the context (or
TEMPLATED_EMAIL_SANITIZE_KWARGS) contains values that are not JSON-serializable, the cache key cannot be computed and caching is safely skipped for that call - no error is raised.
TEMPLATED_EMAIL_CACHE_TIMEOUT¶
Type |
Default |
|---|---|
|
|
Cache TTL in seconds. Passed directly to Django’s cache.set(key, value, timeout). Set to None for a non-expiring entry (if the cache backend
supports it).
TEMPLATED_EMAIL_CACHE_ALIAS¶
Type |
Default |
|---|---|
|
|
The Django cache alias to use. Must be a key defined in settings.CACHES.
Example¶
# settings.py
CACHES = {
"default": {
"BACKEND": "django.core.cache.backends.redis.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
}
}
TEMPLATED_EMAIL_CACHE_RENDERED = True
TEMPLATED_EMAIL_CACHE_TIMEOUT = 600 # 10 minutes
TEMPLATED_EMAIL_CACHE_ALIAS = "default"
Notes¶
To implement any of the above settings, the setting should be added to your Django project’s
settings.pyfile.Many settings have sensible defaults and are optional.
The TEMPLATED_EMAIL_BACKEND setting is required and must be set explicitly.
When using relative URLs in templates (either explicitly in the template or when using Django’s url template tags), either TEMPLATED_EMAIL_BASE_URL should be set in settings, or base_url should be provided when calling send_templated_mail.