mirror of
https://github.com/pacnpal/django-anymail.git
synced 2025-12-20 03:41:05 -05:00
Add Postal support
Thanks to @tiltec for researching, implementing, testing and documenting it.
This commit is contained in:
@@ -16,6 +16,7 @@ and notes about any quirks or limitations:
|
||||
mailgun
|
||||
mailjet
|
||||
mandrill
|
||||
postal
|
||||
postmark
|
||||
sendgrid
|
||||
sendinblue
|
||||
@@ -31,35 +32,35 @@ The table below summarizes the Anymail features supported for each ESP.
|
||||
|
||||
.. rst-class:: sticky-left
|
||||
|
||||
============================================ ============ =========== ========== =========== ========== ========== ============ ===========
|
||||
Email Service Provider |Amazon SES| |Mailgun| |Mailjet| |Mandrill| |Postmark| |SendGrid| |Sendinblue| |SparkPost|
|
||||
============================================ ============ =========== ========== =========== ========== ========== ============ ===========
|
||||
============================================ ============ =========== ========== =========== ========== ========== ========== ============ ===========
|
||||
Email Service Provider |Amazon SES| |Mailgun| |Mailjet| |Mandrill| |Postal| |Postmark| |SendGrid| |Sendinblue| |SparkPost|
|
||||
============================================ ============ =========== ========== =========== ========== ========== ========== ============ ===========
|
||||
.. rubric:: :ref:`Anymail send options <anymail-send-options>`
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
:attr:`~AnymailMessage.envelope_sender` Yes Domain only Yes Domain only No No No Yes
|
||||
:attr:`~AnymailMessage.metadata` Yes Yes Yes Yes Yes Yes Yes Yes
|
||||
:attr:`~AnymailMessage.merge_metadata` No Yes Yes Yes Yes Yes No Yes
|
||||
:attr:`~AnymailMessage.send_at` No Yes No Yes No Yes No Yes
|
||||
:attr:`~AnymailMessage.tags` Yes Yes Max 1 tag Yes Max 1 tag Yes Yes Max 1 tag
|
||||
:attr:`~AnymailMessage.track_clicks` No Yes Yes Yes Yes Yes No Yes
|
||||
:attr:`~AnymailMessage.track_opens` No Yes Yes Yes Yes Yes No Yes
|
||||
:ref:`amp-email` Yes Yes No No No Yes No Yes
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
:attr:`~AnymailMessage.envelope_sender` Yes Domain only Yes Domain only Yes No No No Yes
|
||||
:attr:`~AnymailMessage.metadata` Yes Yes Yes Yes No Yes Yes Yes Yes
|
||||
:attr:`~AnymailMessage.merge_metadata` No Yes Yes Yes No Yes Yes No Yes
|
||||
:attr:`~AnymailMessage.send_at` No Yes No Yes No No Yes No Yes
|
||||
:attr:`~AnymailMessage.tags` Yes Yes Max 1 tag Yes Max 1 tag Max 1 tag Yes Yes Max 1 tag
|
||||
:attr:`~AnymailMessage.track_clicks` No Yes Yes Yes No Yes Yes No Yes
|
||||
:attr:`~AnymailMessage.track_opens` No Yes Yes Yes No Yes Yes No Yes
|
||||
:ref:`amp-email` Yes Yes No No No No Yes No Yes
|
||||
|
||||
.. rubric:: :ref:`templates-and-merge`
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
:attr:`~AnymailMessage.template_id` Yes Yes Yes Yes Yes Yes Yes Yes
|
||||
:attr:`~AnymailMessage.merge_data` Yes Yes Yes Yes Yes Yes No Yes
|
||||
:attr:`~AnymailMessage.merge_global_data` Yes (emulated) Yes Yes Yes Yes Yes Yes
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
:attr:`~AnymailMessage.template_id` Yes Yes Yes Yes No Yes Yes Yes Yes
|
||||
:attr:`~AnymailMessage.merge_data` Yes Yes Yes Yes No Yes Yes No Yes
|
||||
:attr:`~AnymailMessage.merge_global_data` Yes (emulated) Yes Yes No Yes Yes Yes Yes
|
||||
|
||||
.. rubric:: :ref:`Status <esp-send-status>` and :ref:`event tracking <event-tracking>`
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
:attr:`~AnymailMessage.anymail_status` Yes Yes Yes Yes Yes Yes Yes Yes
|
||||
|AnymailTrackingEvent| from webhooks Yes Yes Yes Yes Yes Yes Yes Yes
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
:attr:`~AnymailMessage.anymail_status` Yes Yes Yes Yes Yes Yes Yes Yes Yes
|
||||
|AnymailTrackingEvent| from webhooks Yes Yes Yes Yes Yes Yes Yes Yes Yes
|
||||
|
||||
.. rubric:: :ref:`Inbound handling <inbound>`
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|AnymailInboundEvent| from webhooks Yes Yes Yes Yes Yes Yes No Yes
|
||||
============================================ ============ =========== ========== =========== ========== ========== ============ ===========
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|AnymailInboundEvent| from webhooks Yes Yes Yes Yes Yes Yes Yes No Yes
|
||||
============================================ ============ =========== ========== =========== ========== ========== ========== ============ ===========
|
||||
|
||||
|
||||
Trying to choose an ESP? Please **don't** start with this table. It's far more
|
||||
@@ -71,6 +72,7 @@ meaningless. (And even specific features don't matter if you don't plan to use t
|
||||
.. |Mailgun| replace:: :ref:`mailgun-backend`
|
||||
.. |Mailjet| replace:: :ref:`mailjet-backend`
|
||||
.. |Mandrill| replace:: :ref:`mandrill-backend`
|
||||
.. |Postal| replace:: :ref:`postal-backend`
|
||||
.. |Postmark| replace:: :ref:`postmark-backend`
|
||||
.. |SendGrid| replace:: :ref:`sendgrid-backend`
|
||||
.. |Sendinblue| replace:: :ref:`sendinblue-backend`
|
||||
|
||||
173
docs/esps/postal.rst
Normal file
173
docs/esps/postal.rst
Normal file
@@ -0,0 +1,173 @@
|
||||
.. _postal-backend:
|
||||
|
||||
Postal
|
||||
========
|
||||
|
||||
Anymail integrates with the `Postal`_ self-hosted transactional email platform,
|
||||
using their `HTTP email API`_.
|
||||
|
||||
.. _Postal: https://postal.atech.media/
|
||||
.. _HTTP email API: https://github.com/postalhq/postal/wiki/Using-the-API
|
||||
|
||||
|
||||
Settings
|
||||
--------
|
||||
|
||||
.. rubric:: EMAIL_BACKEND
|
||||
|
||||
To use Anymail's Postal backend, set:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
EMAIL_BACKEND = "anymail.backends.postal.EmailBackend"
|
||||
|
||||
in your settings.py.
|
||||
|
||||
|
||||
.. setting:: ANYMAIL_POSTAL_API_KEY
|
||||
|
||||
.. rubric:: POSTAL_API_KEY
|
||||
|
||||
Required. A Postal API key.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
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.
|
||||
|
||||
|
||||
.. setting:: ANYMAIL_POSTAL_API_URL
|
||||
|
||||
.. rubric:: POSTAL_API_URL
|
||||
|
||||
Required. The base url for calling the Postal API.
|
||||
|
||||
|
||||
.. setting:: ANYMAIL_POSTAL_WEBHOOK_KEY
|
||||
|
||||
.. rubric:: 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.
|
||||
|
||||
|
||||
.. _postal-esp-extra:
|
||||
|
||||
esp_extra support
|
||||
-----------------
|
||||
|
||||
To use Postal features not directly supported by Anymail, you can
|
||||
set a message's :attr:`~anymail.message.AnymailMessage.esp_extra` to
|
||||
a `dict` that will be merged into the json sent to Postal's
|
||||
`email API`_.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
message.esp_extra = {
|
||||
'HypotheticalFuturePostalParam': '2022', # merged into send params
|
||||
}
|
||||
|
||||
|
||||
(You can also set `"esp_extra"` in Anymail's
|
||||
:ref:`global send defaults <send-defaults>` to apply it to all
|
||||
messages.)
|
||||
|
||||
|
||||
.. _email API: https://krystal.github.io/postal-api/controllers/send/message
|
||||
|
||||
|
||||
Limitations and quirks
|
||||
----------------------
|
||||
|
||||
Postal does not support a few tracking and reporting additions offered by other ESPs.
|
||||
|
||||
Anymail normally raises an :exc:`~anymail.exceptions.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 :ref:`unsupported-features`.
|
||||
|
||||
**Single tag**
|
||||
Postal allows a maximum of one tag per message. If your message has two or more
|
||||
:attr:`~anymail.message.AnymailMessage.tags`, you'll get an
|
||||
:exc:`~anymail.exceptions.AnymailUnsupportedFeature` error---or
|
||||
if you've enabled :setting:`ANYMAIL_IGNORE_UNSUPPORTED_FEATURES`,
|
||||
Anymail will use only the first tag.
|
||||
|
||||
**No delayed sending**
|
||||
Postal does not support :attr:`~anymail.message.AnymailMessage.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 :attr:`~anymail.message.AnymailMessage.track_clicks` and
|
||||
:attr:`~anymail.message.AnymailMessage.track_opens` settings are unsupported.
|
||||
|
||||
.. _see their docs on click- & open-tracking: https://github.com/postalhq/postal/wiki/Click-&-Open-Tracking
|
||||
|
||||
**Attachments must be named**
|
||||
Postal issues an `AttachmentMissingName` error when trying to send an attachment without name.
|
||||
|
||||
|
||||
.. _postal-templates:
|
||||
|
||||
Batch sending/merge and ESP templates
|
||||
-------------------------------------
|
||||
|
||||
Postal does not support batch sending or ESP templates.
|
||||
|
||||
|
||||
.. _postal-webhooks:
|
||||
|
||||
Status tracking webhooks
|
||||
------------------------
|
||||
|
||||
If you are using Anymail's normalized :ref:`status tracking <event-tracking>`, set up
|
||||
a webhook in your Postal mail server settings, under Webhooks. The webhook URL is:
|
||||
|
||||
:samp:`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 :setting:`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 :attr:`~anymail.signals.AnymailTrackingEvent.event_type`\s:
|
||||
failed, bounced, deferred, queued, delivered, clicked.
|
||||
|
||||
The event's :attr:`~anymail.signals.AnymailTrackingEvent.esp_event` field will be
|
||||
a `dict` of Postal's `webhook <https://github.com/postalhq/postal/wiki/Webhook-Events-&-Payloads>`_ data.
|
||||
|
||||
.. _postal-inbound:
|
||||
|
||||
Inbound webhook
|
||||
---------------
|
||||
|
||||
If you want to receive email from Postal through Anymail's normalized :ref:`inbound <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:
|
||||
|
||||
:samp:`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 :setting:`ANYMAIL_POSTAL_WEBHOOK_KEY` to enable signature validation.
|
||||
Reference in New Issue
Block a user