* Update docs to (usually) refer to Brevo rather than Sendinblue
* Change SENDINBLUE_API_URL to api.brevo.com
(same API is available on both domains)
* Leave code references (settings, backend name, webhook urls)
unchanged as `sendinblue`, to avoid unnecessary client changes
Work around recent (unannounced) Sendinblue API change
that caused "Invalid headers" API error with non-string
custom header values, by converting basic numeric types
to strings. (Borrowed code from SendGrid backend.)
Fixes#288
Minimum supported versions are now Django 2.0, Python 3.5.
This touches a lot of code, to:
* Remove obsolete portability code and workarounds
(six, backports of email parsers, test utils, etc.)
* Use Python 3 syntax (class defs, raise ... from, etc.)
* Correct inheritance for mixin classes
* Fix outdated docs content and links
* Suppress Python 3 "unclosed SSLSocket" ResourceWarnings
that are beyond our control (in integration tests due to boto3,
python-sparkpost)
Additional changes related to SendinBlue improvements in #158:
* Support multiple tags in webhooks (closes#162)
* Remove additional outdated template code in backend
* Update integration tests
* Update docs and changelog; note breaking changes as discussed in #161
Track Sendinblue API updates:
* Multiple tags are now supported
* When using a template, display name is now supported on 'to', 'bcc', 'cc' and 'replyTo'
* Templates now support overriding 'from_email' and 'subject'
* Templates no longer require separate API endpoint
* 'merge_global_data' can be used without templates
Django allows setting the reply address with either message.reply_to
or message.extra_headers["Reply-To"]. If both are supplied, the extra
headers version takes precedence. (See EmailMessage.message().)
Several Anymail backends had duplicate logic to handle conflicting
properties. Move that logic into the base Payload.
(Also prepares for common handling of extra_headers['From'], later.)
Related changes:
* Use CaseInsensitiveDict for processing extra_headers.
This is potentially a breaking change, but any code that was trying
to send multiple headers differing only in case was likely already
broken. (Email header field names are case-insensitive, per RFC-822.)
* Handle CaseInsensitiveDict in RequestsPayload.serialize_json().
(Several backends had duplicate code for handling this, too.)
* Fixes SparkPost backend, which had been incorrectly treating
message.reply_to and message.extra_headers['Reply-To'] differently.
Add support for sending transactional email through SendinBlue. (Thanks to @RignonNoel.)
Partially implements #84. (Tracking webhooks will be a separate PR. SendinBlue doesn't support inbound handling.)