Postal
Anymail integrates with the Postal self-hosted transactional email platform, using their HTTP email API.
Settings
EMAIL_BACKEND
To use Anymail’s Postal backend, set:
EMAIL_BACKEND = "anymail.backends.postal.EmailBackend"
in your settings.py.
POSTAL_API_KEY
Required. A Postal API key.
ANYMAIL = { ... "POSTAL_API_KEY": "<your api key>", }
Anymail will also look for POSTAL_API_KEY at the
root of the settings file if neither ANYMAIL["POSTAL_API_KEY"]
nor ANYMAIL_POSTAL_API_KEY is set.
POSTAL_API_URL
Required. The base URL of your Postal server (without /api/v1 or any API paths). Anymail will automatically append the required API paths.
ANYMAIL = { ... "POSTAL_API_URL": "https://yourpostal.example.com", }
POSTAL_WEBHOOK_KEY
Required when using status tracking or inbound webhooks.
This should be set to the public key of the Postal instance.
You can find it by running postal default-dkim-record on your
Postal instance.
Use the part that comes after p=, until the semicolon at the end.
esp_extra support
To use Postal features not directly supported by Anymail, you can
set a message’s esp_extra to
a dict that will be merged into the json sent to Postal’s
email API.
Example:
message.esp_extra = { 'HypotheticalFuturePostalParam': '2022', # merged into send params }
(You can also set "esp_extra" in Anymail’s
global send defaults to apply it to all
messages.)
Limitations and quirks
Postal does not support a few tracking and reporting additions offered by other ESPs.
Anymail normally raises an AnymailUnsupportedFeature
error when you try to send a message using features that Postal doesn’t support
You can tell Anymail to suppress these errors and send the messages anyway –
see Unsupported features.
- Single tag
Postal allows a maximum of one tag per message. If your message has two or more
tags, you’ll get anAnymailUnsupportedFeatureerror—or if you’ve enabledANYMAIL_IGNORE_UNSUPPORTED_FEATURES, Anymail will use only the first tag.- No delayed sending
Postal does not support
send_at.- Toggle click-tracking and open-tracking
By default, Postal does not enable click-tracking and open-tracking. To enable it, see their docs on click- & open-tracking. Anymail’s
track_clicksandtrack_openssettings are unsupported.
- Attachments must be named
Postal issues an
AttachmentMissingNameerror when trying to send an attachment without name.- No merge features
Because Postal does not support batch sending, Anymail’s
merge_headers,merge_metadata, andmerge_dataare not supported.
Batch sending/merge and ESP templates
Postal does not support batch sending or ESP templates.
Status tracking webhooks
If you are using Anymail’s normalized status tracking, set up a webhook in your Postal mail server settings, under Webhooks. The webhook URL is:
https://yoursite.example.com/anymail/postal/tracking/
yoursite.example.com is your Django site
Choose all the event types you want to receive.
Postal signs its webhook payloads. You need to set ANYMAIL_POSTAL_WEBHOOK_KEY.
If you use multiple Postal mail servers, you’ll need to repeat entering the webhook settings for each of them.
Postal will report these Anymail event_types:
failed, bounced, deferred, queued, delivered, clicked.
The event’s esp_event field will be
a dict of Postal’s webhook data.
Inbound webhook
If you want to receive email from Postal through Anymail’s normalized inbound
handling, follow Postal’s guide to for receiving emails (Help > Receiving Emails) to create an
incoming route. Then set up an HTTP Endpoint, pointing to Anymail’s inbound webhook.
The url will be:
https://yoursite.example.com/anymail/postal/inbound/
yoursite.example.com is your Django site
Set Format to Delivered as the raw message.
You also need to set ANYMAIL_POSTAL_WEBHOOK_KEY to enable signature validation.