mirror of
https://github.com/pacnpal/django-anymail.git
synced 2025-12-20 11:51:05 -05:00
Mailjet: add docs
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
Anymail: Django email backends for Mailgun, Postmark, SendGrid, SparkPost and more
|
Anymail: Django email backends for Mailgun, Mailjet, Postmark, SendGrid, SparkPost and more
|
||||||
==================================================================================
|
===========================================================================================
|
||||||
|
|
||||||
**PRE-1.0**
|
**PRE-1.0**
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ Anymail integrates several transactional email service providers (ESPs) into Dja
|
|||||||
with a consistent API that lets you use ESP-added features without locking your code
|
with a consistent API that lets you use ESP-added features without locking your code
|
||||||
to a particular ESP.
|
to a particular ESP.
|
||||||
|
|
||||||
It currently fully supports Mailgun, Postmark, SendGrid, and SparkPost,
|
It currently fully supports Mailgun, Mailjet, Postmark, SendGrid, and SparkPost,
|
||||||
and has limited support for Mandrill.
|
and has limited support for Mandrill.
|
||||||
|
|
||||||
Anymail normalizes ESP functionality so it "just works" with Django's
|
Anymail normalizes ESP functionality so it "just works" with Django's
|
||||||
@@ -75,7 +75,7 @@ Anymail 1-2-3
|
|||||||
|
|
||||||
.. This quickstart section is also included in docs/quickstart.rst
|
.. This quickstart section is also included in docs/quickstart.rst
|
||||||
|
|
||||||
This example uses Mailgun, but you can substitute Postmark or SendGrid
|
This example uses Mailgun, but you can substitute Mailjet or Postmark or SendGrid
|
||||||
or SparkPost or any other supported ESP where you see "mailgun":
|
or SparkPost or any other supported ESP where you see "mailgun":
|
||||||
|
|
||||||
1. Install Anymail from PyPI:
|
1. Install Anymail from PyPI:
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ and notes about any quirks or limitations:
|
|||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
mailgun
|
mailgun
|
||||||
|
mailjet
|
||||||
mandrill
|
mandrill
|
||||||
postmark
|
postmark
|
||||||
sendgrid
|
sendgrid
|
||||||
@@ -26,28 +27,28 @@ The table below summarizes the Anymail features supported for each ESP.
|
|||||||
|
|
||||||
.. currentmodule:: anymail.message
|
.. currentmodule:: anymail.message
|
||||||
|
|
||||||
============================================ ========== ========== ========== ========== ===========
|
============================================ ========== ========== ========== ========== ========== ===========
|
||||||
Email Service Provider |Mailgun| |Mandrill| |Postmark| |SendGrid| |SparkPost|
|
Email Service Provider |Mailgun| |Mailjet| |Mandrill| |Postmark| |SendGrid| |SparkPost|
|
||||||
============================================ ========== ========== ========== ========== ===========
|
============================================ ========== ========== ========== ========== ========== ===========
|
||||||
.. rubric:: :ref:`Anymail send options <anymail-send-options>`
|
.. rubric:: :ref:`Anymail send options <anymail-send-options>`
|
||||||
---------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------------------
|
||||||
:attr:`~AnymailMessage.metadata` Yes Yes No Yes Yes
|
:attr:`~AnymailMessage.metadata` Yes Yes Yes No Yes Yes
|
||||||
:attr:`~AnymailMessage.send_at` Yes Yes No Yes Yes
|
:attr:`~AnymailMessage.send_at` Yes No Yes No Yes Yes
|
||||||
:attr:`~AnymailMessage.tags` Yes Yes Max 1 tag Yes Max 1 tag
|
:attr:`~AnymailMessage.tags` Yes Max 1 tag Yes Max 1 tag Yes Max 1 tag
|
||||||
:attr:`~AnymailMessage.track_clicks` Yes Yes Yes Yes Yes
|
:attr:`~AnymailMessage.track_clicks` Yes Yes Yes Yes Yes Yes
|
||||||
:attr:`~AnymailMessage.track_opens` Yes Yes Yes Yes Yes
|
:attr:`~AnymailMessage.track_opens` Yes Yes Yes Yes Yes Yes
|
||||||
|
|
||||||
.. rubric:: :ref:`templates-and-merge`
|
.. rubric:: :ref:`templates-and-merge`
|
||||||
---------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------------------
|
||||||
:attr:`~AnymailMessage.template_id` No Yes Yes Yes Yes
|
:attr:`~AnymailMessage.template_id` No Yes Yes Yes Yes Yes
|
||||||
:attr:`~AnymailMessage.merge_data` Yes Yes No Yes Yes
|
:attr:`~AnymailMessage.merge_data` Yes Yes Yes No Yes Yes
|
||||||
:attr:`~AnymailMessage.merge_global_data` (emulated) Yes Yes Yes Yes
|
:attr:`~AnymailMessage.merge_global_data` (emulated) Yes Yes Yes Yes Yes
|
||||||
|
|
||||||
.. rubric:: :ref:`Status <esp-send-status>` and :ref:`event tracking <event-tracking>`
|
.. rubric:: :ref:`Status <esp-send-status>` and :ref:`event tracking <event-tracking>`
|
||||||
---------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------------------
|
||||||
:attr:`~AnymailMessage.anymail_status` Yes Yes Yes Yes Yes
|
:attr:`~AnymailMessage.anymail_status` Yes Yes Yes Yes Yes Yes
|
||||||
|AnymailTrackingEvent| from webhooks Yes Yes Yes Yes Yes
|
|AnymailTrackingEvent| from webhooks Yes Yes Yes Yes Yes Yes
|
||||||
============================================ ========== ========== ========== ========== ===========
|
============================================ ========== ========== ========== ========== ========== ===========
|
||||||
|
|
||||||
|
|
||||||
Trying to choose an ESP? Please **don't** start with this table. It's far more
|
Trying to choose an ESP? Please **don't** start with this table. It's far more
|
||||||
@@ -56,6 +57,7 @@ and support for developers. The *number* of extra features an ESP offers is almo
|
|||||||
meaningless. (And even specific features don't matter if you don't plan to use them.)
|
meaningless. (And even specific features don't matter if you don't plan to use them.)
|
||||||
|
|
||||||
.. |Mailgun| replace:: :ref:`mailgun-backend`
|
.. |Mailgun| replace:: :ref:`mailgun-backend`
|
||||||
|
.. |Mailjet| replace:: :ref:`mailjet-backend`
|
||||||
.. |Mandrill| replace:: :ref:`mandrill-backend`
|
.. |Mandrill| replace:: :ref:`mandrill-backend`
|
||||||
.. |Postmark| replace:: :ref:`postmark-backend`
|
.. |Postmark| replace:: :ref:`postmark-backend`
|
||||||
.. |SendGrid| replace:: :ref:`sendgrid-backend`
|
.. |SendGrid| replace:: :ref:`sendgrid-backend`
|
||||||
|
|||||||
252
docs/esps/mailjet.rst
Normal file
252
docs/esps/mailjet.rst
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
.. _mailjet-backend:
|
||||||
|
|
||||||
|
Mailjet
|
||||||
|
=======
|
||||||
|
|
||||||
|
Anymail integrates with the `Mailjet`_ email service, using their transactional `Send API`_ (v3).
|
||||||
|
|
||||||
|
.. versionadded:: 0.11
|
||||||
|
|
||||||
|
.. _mailjet-v31-api:
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Mailjet is developing an improved `v3.1 Send API`_ (in public beta as of mid-2017).
|
||||||
|
Once the v3.1 API is released, Anymail will switch to it. This change should be
|
||||||
|
largely transparent to your code, unless you are using Anymail's
|
||||||
|
:ref:`esp_extra <mailjet-esp-extra>` feature to set API-specific options.
|
||||||
|
|
||||||
|
|
||||||
|
.. _Mailjet: https://www.mailjet.com/
|
||||||
|
.. _Send API: https://dev.mailjet.com/guides/#choose-sending-method
|
||||||
|
.. _v3.1 Send API: https://dev.mailjet.com/guides/#send-api-v3-1-beta
|
||||||
|
|
||||||
|
|
||||||
|
Settings
|
||||||
|
--------
|
||||||
|
|
||||||
|
|
||||||
|
.. rubric:: EMAIL_BACKEND
|
||||||
|
|
||||||
|
To use Anymail's Mailjet backend, set:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
EMAIL_BACKEND = "anymail.backends.mailjet.EmailBackend"
|
||||||
|
|
||||||
|
in your settings.py.
|
||||||
|
|
||||||
|
|
||||||
|
.. setting:: ANYMAIL_MAILJET_API_KEY
|
||||||
|
|
||||||
|
.. rubric:: MAILJET_API_KEY and MAILJET_SECRET_KEY
|
||||||
|
|
||||||
|
Your Mailjet API key and secret, from your Mailjet account REST API settings
|
||||||
|
under `API Key Management`_. (Mailjet's documentation also sometimes uses
|
||||||
|
"API private key" to mean the same thing as "API secret.")
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
ANYMAIL = {
|
||||||
|
...
|
||||||
|
"MAILJET_API_KEY": "<your API key>",
|
||||||
|
"MAILJET_API_SECRET": "<your API secret>",
|
||||||
|
}
|
||||||
|
|
||||||
|
You can use either a master or sub-account API key.
|
||||||
|
|
||||||
|
|
||||||
|
Anymail will also look for ``MAILJET_API_KEY`` and ``MAILJET_API_SECRET`` at the
|
||||||
|
root of the settings file if neither ``ANYMAIL["MAILJET_API_KEY"]``
|
||||||
|
nor ``ANYMAIL_MAILJET_API_KEY`` is set.
|
||||||
|
|
||||||
|
.. _API Key Management: https://app.mailjet.com/account/api_keys
|
||||||
|
|
||||||
|
|
||||||
|
.. setting:: ANYMAIL_MAILJET_API_URL
|
||||||
|
|
||||||
|
.. rubric:: MAILJET_API_URL
|
||||||
|
|
||||||
|
The base url for calling the Mailjet API.
|
||||||
|
|
||||||
|
The default is ``MAILJET_API_URL = "https://api.mailjet.com/v3"``
|
||||||
|
(It's unlikely you would need to change this. This setting cannot be used
|
||||||
|
to opt into a newer API version; the parameters are not backwards compatible.)
|
||||||
|
|
||||||
|
|
||||||
|
.. _mailjet-esp-extra:
|
||||||
|
|
||||||
|
esp_extra support
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
To use Mailjet features not directly supported by Anymail, you can
|
||||||
|
set a message's :attr:`~anymail.message.AnymailMessage.esp_extra` to
|
||||||
|
a `dict` of Mailjet's `Send API json properties`_.
|
||||||
|
Your :attr:`esp_extra` dict will be merged into the
|
||||||
|
parameters Anymail has constructed for the send, with `esp_extra`
|
||||||
|
having precedence in conflicts.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Any ``esp_extra`` settings will need to be updated when Anymail changes
|
||||||
|
to use Mailjet's upcoming v3.1 API. (See :ref:`note above <mailjet-v31-api>`.)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
message.esp_extra = {
|
||||||
|
# Mailjet v3.0 Send API options:
|
||||||
|
"Mj-prio": 3, # Use Mailjet critically-high priority queue
|
||||||
|
"Mj-CustomID": my_event_tracking_id,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
(You can also set `"esp_extra"` in Anymail's
|
||||||
|
:ref:`global send defaults <send-defaults>` to apply it to all
|
||||||
|
messages.)
|
||||||
|
|
||||||
|
|
||||||
|
.. _Send API json properties: https://dev.mailjet.com/guides/#send-api-json-properties
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Limitations and quirks
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
**Single tag**
|
||||||
|
Anymail uses Mailjet's `campaign`_ option for tags, and Mailjet allows
|
||||||
|
only a single campaign 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.
|
||||||
|
|
||||||
|
.. _campaign: https://dev.mailjet.com/guides/#grouping-into-a-campaign
|
||||||
|
|
||||||
|
**No delayed sending**
|
||||||
|
Mailjet does not support :attr:`~anymail.message.AnymailMessage.send_at`.
|
||||||
|
|
||||||
|
**Commas in recipient names**
|
||||||
|
Mailjet's v3 API does not properly handle commas in recipient display-names
|
||||||
|
*if* your message also uses the ``cc`` or ``bcc`` fields.
|
||||||
|
(Tested July, 2017, and confirmed with Mailjet API support.)
|
||||||
|
|
||||||
|
If your message would be affected, Anymail attempts to work around
|
||||||
|
the problem by switching to `MIME encoded-word`_ syntax where needed.
|
||||||
|
|
||||||
|
Most modern email clients should support this syntax, but if you run
|
||||||
|
into issues either avoid using ``cc`` and ``bcc``, or strip commas from all
|
||||||
|
recipient names (in ``to``, ``cc``, *and* ``bcc``) before sending.
|
||||||
|
|
||||||
|
.. _MIME encoded-word: https://en.wikipedia.org/wiki/MIME#Encoded-Word
|
||||||
|
|
||||||
|
**Merge data not compatible with cc/bcc**
|
||||||
|
Mailjet's v3 API is not capable of representing both ``cc`` or ``bcc`` fields
|
||||||
|
and :attr:`~anymail.message.AnymailMessage.merge_data` in the same message.
|
||||||
|
If you attempt to combine them, Anymail will raise an error at send time.
|
||||||
|
|
||||||
|
(The latter two limitations should be resolved in a future release when
|
||||||
|
Anymail :ref:`switches <mailjet-v31-api>` to Mailjet's upcoming v3.1 API.)
|
||||||
|
|
||||||
|
|
||||||
|
.. _mailjet-templates:
|
||||||
|
|
||||||
|
Batch sending/merge and ESP templates
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
Mailjet offers both :ref:`ESP stored templates <esp-stored-templates>`
|
||||||
|
and :ref:`batch sending <batch-send>` with per-recipient merge data.
|
||||||
|
|
||||||
|
You can use a Mailjet stored transactional template by setting a message's
|
||||||
|
:attr:`~anymail.message.AnymailMessage.template_id` to the
|
||||||
|
template's *numeric* template ID. (*Not* the template's name. To get the
|
||||||
|
numeric template id, click on the name in your Mailjet `transactional templates`_,
|
||||||
|
then look for "Template ID" above the preview that appears.)
|
||||||
|
|
||||||
|
Supply the template merge data values with Anymail's
|
||||||
|
normalized :attr:`~anymail.message.AnymailMessage.merge_data`
|
||||||
|
and :attr:`~anymail.message.AnymailMessage.merge_global_data`
|
||||||
|
message attributes.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
message = EmailMessage(
|
||||||
|
...
|
||||||
|
# omit subject and body (or set to None) to use template content
|
||||||
|
to=["alice@example.com", "Bob <bob@example.com>"]
|
||||||
|
)
|
||||||
|
message.template_id = "176375" # Mailjet numeric template id
|
||||||
|
message.from_email = None # Use the From address stored with the template
|
||||||
|
message.merge_data = {
|
||||||
|
'alice@example.com': {'name': "Alice", 'order_no': "12345"},
|
||||||
|
'bob@example.com': {'name': "Bob", 'order_no': "54321"},
|
||||||
|
}
|
||||||
|
message.merge_global_data = {
|
||||||
|
'ship_date': "May 15",
|
||||||
|
}
|
||||||
|
|
||||||
|
Any ``from_email`` in your EmailMessage will override the template's default sender
|
||||||
|
address. To use the template's sender, you must explicitly set ``from_email = None``
|
||||||
|
after creating the EmailMessage, as shown above. (If you omit this, Django's default
|
||||||
|
:setting:`DEFAULT_FROM_EMAIL` will be used.)
|
||||||
|
|
||||||
|
Instead of creating a stored template at Mailjet, you can also refer to merge fields
|
||||||
|
directly in an EmailMessage's body---the message itself is used as an on-the-fly template:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
message = EmailMessage(
|
||||||
|
from_email="orders@example.com",
|
||||||
|
to=["alice@example.com", "Bob <bob@example.com>"],
|
||||||
|
subject="Your order has shipped", # subject doesn't support on-the-fly merge fields
|
||||||
|
# Use [[var:FIELD]] to for on-the-fly merge into plaintext or html body:
|
||||||
|
body="Dear [[var:name]]: Your order [[var:order_no]] shipped on [[var:ship_date]]."
|
||||||
|
)
|
||||||
|
message.merge_data = {
|
||||||
|
'alice@example.com': {'name': "Alice", 'order_no': "12345"},
|
||||||
|
'bob@example.com': {'name': "Bob", 'order_no': "54321"},
|
||||||
|
}
|
||||||
|
message.merge_global_data = {
|
||||||
|
'ship_date': "May 15",
|
||||||
|
}
|
||||||
|
|
||||||
|
(Note that on-the-fly templates use square brackets to indicate `"personalization"`_ merge fields,
|
||||||
|
rather than the curly brackets used with stored templates in Mailjet's template language.)
|
||||||
|
|
||||||
|
See Mailjet's `template documentation`_ and `template language`_ docs
|
||||||
|
for more information.
|
||||||
|
|
||||||
|
.. _transactional templates: https://app.mailjet.com/templates/transactional
|
||||||
|
.. _"personalization": https://dev.mailjet.com/guides/#personalisation
|
||||||
|
.. _template documentation: https://www.mailjet.com/docs/template_builder_transactional
|
||||||
|
.. _template language: https://dev.mailjet.com/template-language/
|
||||||
|
|
||||||
|
|
||||||
|
.. _mailjet-webhooks:
|
||||||
|
|
||||||
|
Status tracking webhooks
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
If you are using Anymail's normalized :ref:`status tracking <event-tracking>`, enter
|
||||||
|
the url in your Mailjet account REST API settings under `Event tracking (triggers)`_:
|
||||||
|
|
||||||
|
:samp:`https://{random}:{random}@{yoursite.example.com}/anymail/mailjet/tracking/`
|
||||||
|
|
||||||
|
* *random:random* is an :setting:`ANYMAIL_WEBHOOK_AUTHORIZATION` shared secret
|
||||||
|
* *yoursite.example.com* is your Django site
|
||||||
|
|
||||||
|
Be sure to enter the URL in the Mailjet settings for all the event types you want to receive.
|
||||||
|
It's also recommended to select the "group events" checkbox for each trigger, to minimize your
|
||||||
|
server load.
|
||||||
|
|
||||||
|
Mailjet will report these Anymail :attr:`~anymail.signals.AnymailTrackingEvent.event_type`\s:
|
||||||
|
rejected, bounced, deferred, delivered, opened, clicked, complained, unsubscribed.
|
||||||
|
|
||||||
|
The event's :attr:`~anymail.signals.AnymailTrackingEvent.esp_event` field will be
|
||||||
|
a `dict` of `Mailjet event`_ fields, for a single event. (Although Mailjet calls
|
||||||
|
webhooks with batches of events, Anymail will invoke your signal receiver separately
|
||||||
|
for each event in the batch.)
|
||||||
|
|
||||||
|
.. _Event tracking (triggers): https://app.mailjet.com/account/triggers
|
||||||
|
.. _Mailjet event: https://dev.mailjet.com/guides/#events
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
Anymail: Django email backends for Mailgun, Postmark, SendGrid and more
|
Anymail: Django email backends for Mailgun, Mailjet, Postmark, SendGrid and more
|
||||||
=======================================================================
|
================================================================================
|
||||||
|
|
||||||
Version |release|
|
Version |release|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user