SendinBlue: update docs, readme, setup, Travis config

* Flesh out SendinBlue docs, add a readme mention
* Stop trying to list all the supported ESPs in the project short
  description and similar headlines -- it was becoming unwieldy.
* Support `pip install django-anymail[sendinblue]`
  and use it in Travis tests (for consistency; SendinBlue
  doesn't require any extra packages)
This commit is contained in:
medmunds
2018-03-01 17:29:57 -08:00
parent 9478bf5958
commit 1e7aacdcb4
6 changed files with 175 additions and 42 deletions

View File

@@ -56,7 +56,7 @@ install:
- if [[ -n $DJANGO ]]; then pip install $DJANGO; fi - if [[ -n $DJANGO ]]; then pip install $DJANGO; fi
# For now, install Anymail including all optional ESPs, and test at once # For now, install Anymail including all optional ESPs, and test at once
# (in future, might want to matrix ESPs to test cross-dependencies) # (in future, might want to matrix ESPs to test cross-dependencies)
- if [[ -n $DJANGO ]]; then pip install .[mailgun,mandrill,postmark,sendgrid,sparkpost]; fi - if [[ -n $DJANGO ]]; then pip install .[mailgun,mailjet,mandrill,postmark,sendinblue,sendgrid,sparkpost]; fi
- if [[ -n $FLAKE8 ]]; then pip install flake8; fi - if [[ -n $FLAKE8 ]]; then pip install flake8; fi
- pip list - pip list

View File

@@ -1,5 +1,5 @@
Anymail: Django email backends for Mailgun, Mailjet, Postmark, SendGrid, SparkPost and more Anymail: Django email integration for transactional ESPs
=========================================================================================== ========================================================
.. This README is reused in multiple places: .. This README is reused in multiple places:
* Github: project page, exactly as it appears here * Github: project page, exactly as it appears here
@@ -23,8 +23,8 @@ 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, Mailjet, Postmark, SendGrid, and SparkPost, It currently fully supports **Mailgun, Mailjet, Postmark, SendinBlue, SendGrid,**
and has limited support for Mandrill. and **SparkPost,** 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
built-in `django.core.mail` package. It includes: built-in `django.core.mail` package. It includes:

View File

@@ -49,7 +49,7 @@ Email Service Provider |Mailgun| |Mailjet| |Mandrill
.. 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 Yes Yes :attr:`~AnymailMessage.anymail_status` Yes Yes Yes Yes Yes Yes Yes
|AnymailTrackingEvent| from webhooks Yes Yes Yes Yes Yes No Yes |AnymailTrackingEvent| from webhooks Yes Yes Yes Yes Yes *Coming* Yes
.. rubric:: :ref:`Inbound handling <inbound>` .. rubric:: :ref:`Inbound handling <inbound>`
------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------

View File

@@ -3,26 +3,27 @@
SendinBlue SendinBlue
========== ==========
Anymail integrates with the `SendinBlue`_ email service, using their `Web API v3`_. Anymail integrates with the `SendinBlue`_ email service, using their `API v3`_.
SendinBlue's transactional API does not support some basic email features, such as
inline images. Be sure to review the :ref:`limitations <sendinblue-limitations>` below.
.. important:: .. important::
**Troubleshooting:** **Troubleshooting:**
If your SendinBlue messages aren't being delivered as expected, be sure to look for If your SendinBlue messages aren't being delivered as expected, be sure to look for
events in your SendinBlue `statistic panel`_. events in your SendinBlue `logs`_.
SendGrid detects certain types of errors only *after* the send API call appears SendinBlue detects certain types of errors only *after* the send API call reports
to succeed, and reports these errors in the statistic panel. the message as "queued." These errors appear in the logging dashboard.
.. _SendinBlue: https://www.sendinblue.com/ .. _SendinBlue: https://www.sendinblue.com/
.. _Web API v3: https://developers.sendinblue.com/docs .. _API v3: https://developers.sendinblue.com/docs
.. _statistic panel: https://app-smtp.sendinblue.com/statistics .. _logs: https://app-smtp.sendinblue.com/log
Settings Settings
-------- --------
.. rubric:: EMAIL_BACKEND .. rubric:: EMAIL_BACKEND
To use Anymail's SendinBlue backend, set: To use Anymail's SendinBlue backend, set:
@@ -38,57 +39,187 @@ in your settings.py.
.. rubric:: SENDINBLUE_API_KEY .. rubric:: SENDINBLUE_API_KEY
The API key can be retrieved from the The API key can be retrieved from your SendinBlue `SMTP & API settings`_.
`account settings`_. Make sure to get the Make sure the version column indicates "v3." (v2 keys don't work with
key for the version of the API you're Anymail. If you don't see a v3 key listed, use "Create a New API Key".)
using..)
Required. Required.
.. code-block:: python .. code-block:: python
ANYMAIL = { ANYMAIL = {
... ...
"SENDINBLUE_API_KEY": "<your API key>", "SENDINBLUE_API_KEY": "<your v3 API key>",
} }
Anymail will also look for ``SENDINBLUE_API_KEY`` at the Anymail will also look for ``SENDINBLUE_API_KEY`` at the
root of the settings file if neither ``ANYMAIL["SENDINBLUE_API_KEY"]`` root of the settings file if neither ``ANYMAIL["SENDINBLUE_API_KEY"]``
nor ``ANYMAIL_SENDINBLUE_API_KEY`` is set. nor ``ANYMAIL_SENDINBLUE_API_KEY`` is set.
.. _account settings: https://account.sendinblue.com/advanced/api .. _SMTP & API settings: https://account.sendinblue.com/advanced/api
.. setting:: ANYMAIL_SENDINBLUE_API_URL
.. rubric:: SENDINBLUE_API_URL
The base url for calling the SendinBlue API.
The default is ``SENDINBLUE_API_URL = "https://api.sendinblue.com/v3/"``
(It's unlikely you would need to change this.)
.. _sendinblue-esp-extra:
esp_extra support
-----------------
To use SendinBlue 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 SendinBlue's
`smtp/email API`_.
Example:
.. code-block:: python
message.esp_extra = {
'hypotheticalFutureSendinBlueParam': '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.)
.. _smtp/email API: https://developers.sendinblue.com/v3.0/reference#sendtransacemail
.. _sendinblue-limitations:
Limitations and quirks Limitations and quirks
---------------------- ----------------------
SendinBlue's v3 API has several limitations. In most cases below,
Anymail will raise an :exc:`~anymail.exceptions.AnymailUnsupportedFeature`
error if you try to send a message using missing features. You can
override this by enabling the :setting:`ANYMAIL_IGNORE_UNSUPPORTED_FEATURES`
setting, and Anymail will try to limit the API request to features
SendinBlue can handle.
**Inline images**
SendinBlue's v3 API doesn't support inline images, at all.
(Confirmed with SendinBlue support Feb 2018.)
If you are ignoring unsupported features, Anymail will try to send
inline images as ordinary image attachments.
**Attachment names must be filenames with recognized extensions**
SendinBlue determines attachment content type by assuming the attachment's
name is a filename, and examining that filename's extension (e.g., ".jpg").
Trying to send an attachment without a name, or where the name does not end
in a supported filename extension, will result in a SendinBlue API error.
Anymail has no way to communicate an attachment's desired content-type
to the SendinBlue API if the name is not set correctly.
**Additional template limitations**
If you are sending using a SendinBlue template, their API doesn't allow display
names in recipient or reply-to emails, and doesn't support overriding the template's
from_email, subject, or body. See the :ref:`templates <sendinblue-templates>`
section below.
**Single Reply-To** **Single Reply-To**
SendinBlue's v3 API only supports a single Reply-To address. SendinBlue's v3 API only supports a single Reply-To address.
If your message has multiple reply addresses, you'll get an If you are ignoring unsupported features and have multiple reply addresses,
:exc:`~anymail.exceptions.AnymailUnsupportedFeature` error---or
if you've enabled :setting:`ANYMAIL_IGNORE_UNSUPPORTED_FEATURES`,
Anymail will use only the first one. Anymail will use only the first one.
**Attachment content-type** **Single tag**
Attachment content-type is determined from the filename SendinBlue supports a single message tag, which can be used for filtering in their
extension and you can't specify a different one. Trying dashboard statistics and logs panels, and is available in tracking webhooks.
to send an attachment without a name or a name without Anymail will pass the first of a message's :attr:`~anymail.message.AnymailMessage.tags`
an extension generates an error with SendinBlue's API. to SendinBlue, using their :mailheader:`X-Mailin-tag` email header.
**Inline images** Trying to send a message with more than one tag will result in an error unless you
SendinBlue doesn't support inline images at all, it are ignoring unsupported features.
only support basic attachment.
**Email's display-names** **Metadata**
Email's display-names are only supported Anymail passes :attr:`~anymail.message.AnymailMessage.metadata` to SendinBlue
**without** :attr:`template_id`. If you specify as a JSON-encoded string using their :mailheader:`X-Mailin-custom` email header.
a :attr:`template_id` all display-names will be hidden. The metadata is available in tracking webhooks.
**Template's limitation** **No delayed sending**
If you use a template you will suffer some limitations: SendinBlue does not support :attr:`~anymail.message.AnymailMessage.send_at`.
you can't change the subject or/and the body, and all email's
display-names will be hidden. **No click-tracking or open-tracking options**
SendinBlue does not provide a way to control open or click tracking for individual
messages. Anymail's :attr:`~anymail.message.AnymailMessage.track_clicks` and
:attr:`~anymail.message.AnymailMessage.track_opens` settings are unsupported.
**No envelope sender overrides** **No envelope sender overrides**
SendinBlue does not support overriding :attr:`~anymail.message.AnymailMessage.envelope_sender` SendinBlue does not support overriding :attr:`~anymail.message.AnymailMessage.envelope_sender`
on individual messages. on individual messages.
.. _sendinblue-templates:
Batch sending/merge and ESP templates
-------------------------------------
SendinBlue supports :ref:`ESP stored templates <esp-stored-templates>`
populated with global merge data for all recipients, but does not
offer :ref:`batch sending <batch-send>` with per-recipient merge data.
Anymail's :attr:`~anymail.message.AnymailMessage.merge_data`
message attribute is not supported with the SendinBlue backend.
To use a SendinBlue template, set the message's
:attr:`~anymail.message.AnymailMessage.template_id` to the numeric
SendinBlue template ID, and supply substitution attributes using
the messages's :attr:`~anymail.message.AnymailMessage.merge_global_data`:
.. code-block:: python
message = EmailMessage(
subject=None, # required for SendinBlue templates
body=None, # required for SendinBlue templates
to=["alice@example.com"] # single recipient...
# ...multiple to emails would all get the same message
# (and would all see each other's emails in the "to" header)
)
message.from_email = None # required for SendinBlue templates
message.template_id = 3 # use this SendinBlue template
message.merge_global_data = {
'name': "Alice",
'order_no': "12345",
'ship_date': "May 15",
}
Within your SendinBlue template body and subject, you can refer to merge
variables using %-delimited names, e.g., `%order_no%` or `%ship_date%`
from the example above.
Note that SendinBlue's API does not permit overriding a template's
subject, body, or from_email. You *must* set them to `None` as shown above,
or Anymail will raise an :exc:`~anymail.exceptions.AnymailUnsupportedFeature`
error (if you are not ignoring unsupported features).
Also, SendinBlue's API does not permit display names in recipient or reply-to
emails when sending with a template. Code like `to=["Alice <alice@example.com>"]`
will result in an unsupported feature error. (SendinBlue supports display names
only in *non*-template sends.)
.. _sendinblue-webhooks:
Status tracking webhooks
------------------------
SendinBlue supports status tracking webhooks. Integration with Anymail's normalized
:ref:`status tracking <event-tracking>` is planned for a future release.
.. _sendinblue-inbound:
Inbound webhook
---------------
SendinBlue does not support inbound email handling.

View File

@@ -1,5 +1,5 @@
Anymail: Django email backends for Mailgun, Mailjet, Postmark, SendGrid and more Anymail: Django email integration for transactional ESPs
================================================================================ ========================================================
Version |release| Version |release|

View File

@@ -33,9 +33,10 @@ with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
setup( setup(
name="django-anymail", name="django-anymail",
version=version, version=version,
description='Django email backends for Mailgun, Mailjet, Postmark, SendGrid, SparkPost ' description='Django email integration for Mailgun, Mailjet, Postmark, SendGrid, SendinBlue, SparkPost '
'and other transactional ESPs', 'and other transactional ESPs',
keywords="django, email, email backend, ESP, transactional mail, mailgun, mailjet, mandrill, postmark, sendgrid", keywords="Django, email, email backend, ESP, transactional mail, "
"Mailgun, Mailjet, Mandrill, Postmark, SendinBlue, SendGrid, SparkPost",
author="Mike Edmunds and Anymail contributors", author="Mike Edmunds and Anymail contributors",
author_email="medmunds@gmail.com", author_email="medmunds@gmail.com",
url="https://github.com/anymail/django-anymail", url="https://github.com/anymail/django-anymail",
@@ -52,6 +53,7 @@ setup(
"mandrill": [], "mandrill": [],
"postmark": [], "postmark": [],
"sendgrid": [], "sendgrid": [],
"sendinblue": [],
"sparkpost": ["sparkpost"], "sparkpost": ["sparkpost"],
}, },
include_package_data=True, include_package_data=True,