-
Notifications
You must be signed in to change notification settings - Fork 4
Django Backend
postmark.django.EmailBackend is a drop-in EMAIL_BACKEND that sends Django's django.core.mail through the Postmark API. Requires the django extra:
pip install postmark-python[django]Supports Django 4.2 LTS, 5.2 LTS, 6.0, and 6.1.
# settings.py
EMAIL_BACKEND = "postmark.django.EmailBackend"
POSTMARK_SERVER_TOKEN = "your-server-token"from django.core.mail import send_mail
send_mail(
subject="Hello from Postmark",
message="Sent with postmark.django.EmailBackend.",
from_email="sender@example.com",
recipient_list=["receiver@example.com"],
html_message="<p>Sent with <b>postmark.django.EmailBackend</b>.</p>",
)| Setting | Default | Description |
|---|---|---|
POSTMARK_SERVER_TOKEN |
(required) | Your Postmark server token. Can also be passed as server_token= to get_connection(). |
POSTMARK_TEST_MODE |
False |
When True, sends using Postmark's POSTMARK_API_TEST token instead — validates requests without delivering mail. |
POSTMARK_TRACK_OPENS |
False |
Default TrackOpens value for every message, unless overridden per-message (see below). |
POSTMARK_MESSAGE_STREAM |
None |
Default message stream, unless overridden per-message. |
Postmark's tag, metadata, and message-stream fields have no equivalent on Django's EmailMessage, so use PostmarkEmailMessage / PostmarkEmailMultiAlternatives instead:
from postmark.django import PostmarkEmailMessage
PostmarkEmailMessage(
subject="Your invitation",
body="You're invited!",
from_email="sender@example.com",
to=["receiver@example.com"],
tag="invitation",
metadata={"user_id": "12345"},
message_stream="outbound",
).send()PostmarkEmailMixin is also available if you want to add these fields to your own EmailMessage subclass.
Use Django's normal APIs — EmailMultiAlternatives.attach_alternative(html, "text/html") for an HTML body, and EmailMessage.attach(filename, content, mimetype) for attachments. Attachment content is base64-encoded automatically. Postmark's Email API accepts a single HTML body; any other alternative content type is dropped with a logged warning rather than raising.
Legacy email.mime.base.MIMEBase objects passed to .attach() are not supported — use the (filename, content, mimetype) form instead. This also means inline (Content-ID / cid:) images aren't currently supported through this backend, since Django only exposes a Content-ID header via that same legacy MIMEBase path. For inline images, either host the image externally and reference it by URL in your HTML body (see examples/django/send_with_external_image.py), or send directly with postmark.ServerClient / postmark.sync.ServerClient using an Attachment with content_id set.
send_messages() batches messages in groups of up to 500 per Postmark API request. Postmark returns HTTP 200 even when individual recipients fail, so failures raise the same typed exceptions as the rest of the SDK (see Error Handling) — fail_silently=True swallows them and returns only the count of messages that actually sent, matching Django's BaseEmailBackend contract.
from postmark.django import pre_send, post_send, on_exception-
pre_send— fires just before a batch is submitted.messageskwarg: thepostmark.Emailobjects about to be sent. -
post_send— fires just after a successful batch submission.messages/responsekwargs. -
on_exception— fires whensend_messages()raises.raw_messages(the original Django messages) /exceptionkwargs.
-
examples/django/settings_snippet.py— settings to add to your project -
examples/django/send_simple.py— send a single email -
examples/django/send_batch.py— send several distinct messages in one call -
examples/django/send_simple_with_attachment.py— attachments -
examples/django/send_simple_with_custom_header.py— custom headers -
examples/django/send_with_external_image.py— HTML body with an external tracking image -
examples/django/send_with_tags_and_metadata.py— tags, metadata, message stream