Notice

Assets

Important updates

Breaking change: Drop support for deprecated WEBHOOK_AUTHORIZATION setting. If you are using webhooks and still have this Anymail setting, you must rename it to WEBHOOK_SECRET. See the v1.4 release notes.

New features

SendinBlue: Add new ESP (docs). Thanks to @RignonNoel for the implementation.

Add EmailMessage envelope_sender attribute, which can adjust the message's Return-Path if supported by your ESP (docs).

Add universal wheel to PyPI releases for faster installation.

Other changes

Handle Reply-To, From, and To in EmailMessage extra_headers the same as Django's SMTP EmailBackend if supported by your ESP, otherwise raise an unsupported feature error. Fixes the SparkPost backend to be consistent with other backends if both headers["Reply-To"] and reply_to are set on the same message. If you are setting a message's headers["From"] or headers["To"] (neither is common), the new behavior is likely a breaking change. See docs and #91.

Treat EmailMessage extra_headers keys as case-insensitive in all backends, for consistency with each other (and email specs). If you are specifying duplicate headers whose names differ only in case, this may be a breaking change. See docs.

Assets

Django error reporting includes the value of your Anymail WEBHOOK_AUTHORIZATION setting. In a properly-configured deployment, this should not be cause for concern. But if you have somehow exposed your Django error reports (e.g., by mis-deploying with DEBUG=True or by sending error reports through insecure channels), anyone who gains access to those reports could discover your webhook shared secret. An attacker could use this to post fabricated or malicious Anymail tracking/inbound events to your app, if you are using those Anymail features.

If you are using Anymail's event tracking and/or inbound webhooks, you should upgrade to this release and change "WEBHOOK_AUTHORIZATION" to "WEBHOOK_SECRET" in the ANYMAIL section of your settings.py. You may also want to rotate the shared secret value, particularly if you have ever exposed your Django error reports to untrusted individuals.

If you are only using Anymail's EmailBackends for sending email and have not set up Anymail's webhooks, this issue does not affect you.

The old WEBHOOK_AUTHORIZATION setting is still allowed in this release, but will issue a system-check warning when running most Django management commands. It will be removed completely in a near-future release, as a breaking change.

Assets

Security fix

If you are using Anymail's tracking webhooks, you should upgrade to this release, and you may want to rotate to a new WEBHOOK_AUTHORIZATION shared secret (see docs). You should definitely change your webhook auth if your logs indicate attempted exploit.

(If you are only sending email using an Anymail EmailBackend, and have not set up Anymail's event tracking webhooks, this issue does not affect you.)

More information

Anymail's webhook validation was vulnerable to a timing attack. A remote attacker could use this to obtain your WEBHOOK_AUTHORIZATION shared secret, potentially allowing them to post fabricated or malicious email tracking events to your app.

There have not been any reports of attempted exploit. (The vulnerability was discovered through code review.) Attempts would be visible in HTTP logs as a very large number of 400 responses on Anymail's webhook urls (by default "/anymail/esp_name/tracking/"), and in Python error monitoring as a very large number of AnymailWebhookValidationFailure exceptions.

Bug fixes

Other changes

Internal: Rework Anymail's ParsedEmail class and rename to EmailAddress to align it with similar functionality in the Python 3.6 email package, in preparation for future inbound support. ParsedEmail was not documented for use outside Anymail's internals (so this change does not bump the semver major version), but if you were using it in an undocumented way you will need to update your code.

Downloads

It's official: Anymail is no longer "pre-1.0." The API has been stable for many months, and there's no reason not to use Anymail in production.

Breaking changes

There are no new breaking changes in the 1.0 release, but a breaking change introduced several months ago in v0.8 is now strictly enforced. If you still have an EMAIL_BACKEND setting that looks like "anymail.backends.espname.EspNameBackend", you'll need to change it to just "anymail.backends.espname.EmailBackend". (Earlier versions had issued a DeprecationWarning. See the v0.8 release notes.)

Downloads

Breaking changes

All backends: The old EspNameBackend names that were deprecated in v0.8 have been removed. Attempting to use the old names will now fail, rather than issue a DeprecationWarning. See the v0.8 release notes.

Downloads

New features

Mailgun, SparkPost: Support multiple from addresses, as a comma-separated from_email string. (Not a list of strings, like the recipient fields.) RFC-5322 allows multiple from email addresses, and these two ESPs support it. Though as a practical matter, multiple from emails are either ignored or treated as a spam signal by receiving mail handlers. (See #60.)