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 for calling the Postal API.

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 an AnymailUnsupportedFeature error—or if you’ve enabled ANYMAIL_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_clicks and track_opens settings are unsupported.

Attachments must be named

Postal issues an AttachmentMissingName error when trying to send an attachment without name.

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.