Issue a better error message if message.reply_to
is set to a single string.
(Would also like to do this for to, cc, and bcc,
but Django core EmailMessage.recipients is called
and stumbles over thoses cases before Anymail's
backend gets involved.)
Fixes#57
Track change to Mailgun's events API, which
no longer includes message recipients.
(Only affected check for successful send
in the integration tests; Anymail doesn't
use the events API outside test code.)
Fixes#58
* Mandrill now refers to "whitelist change" events
(used to be "whitelist sync").
* More details on solving validation failures due to
webhook url mismatches.
* The default (GitHub) readme should point
to the stable docs version, rather than
the latest development version.
* The frozen links in PyPI should use the full
patch version number (X.Y.Z), not just the minor
X.Y version. (Leftover from Djrill's branch-based
version management; Anymail uses tags
for versions, and old way was creating incorrect
frozen doc links for patch releases.)
Only real problem is in json serialization tests:
Python 3.6 [changed][1] the json serialization
error message to use the object's class name
rather than its repr. E.g.:
"Decimal('19.99') is not JSON serializable"
becomes:
"Object of type 'Decimal' is not JSON serializable"
Update tests that looked for specific serialization
error message to just look for the word "Decimal"
instead. (Works with all Python versions.)
[1]: https://bugs.python.org/issue26623
* **Future breaking change:**
Rename all Anymail backends to just `EmailBackend`,
matching Django's naming convention.
(E.g., switch to "anymail.backends.mailgun.EmailBackend"
rather than "anymail.backends.mailgun.MailgunBackend".)
The old names still work, but will issue a DeprecationWarning
and will be removed in some future release.
(Apologies for this change; the old naming convention was
a holdover from Djrill, and I wanted consistency with
other Django EmailBackends before hitting 1.0.)
Fixes#49.
Mandrill's webhook signature calculation uses the
*exact url* Mandrill is posting to. If HTTP basic
auth is also used, that auth is included in the url.
Anymail was using Django's request.build_absolute_uri,
which doesn't include HTTP basic auth. Anymail now
includes the auth in the calculation, if it was present
in the request.
This should eliminate the need to use the
ANYMAIL_MANDRILL_WEBHOOK_URL override,
if Django's SECURE_PROXY_SSL_HEADER and
USE_X_FORWARDED_HOST (and/or
USE_X_FORWARDED_PROTO) settings are correct
for your server.
(The calculated url is now also included in
the validation failure error message, to aid
debugging.)
Fixes#48
SendGrid: update to v3 send API
**SendGrid:** **[possibly-breaking]** Update SendGrid backend to newer Web API v3. This should be a transparent change for most projects. Exceptions: if you use SendGrid username/password auth, esp_extra with "x-smtpapi", or multiple Reply-To addresses, please review the [porting notes](http://anymail.readthedocs.io/en/latest/esps/sendgrid/#sendgrid-v3-upgrade).
Closes#28
In BasePayload, ensure any Django ugettext_lazy
(or similar) are converted to real strings before
handing off to ESP code. This resolves problems where
calling code expects it can use lazy strings "anywhere",
but non-Django code (requests, ESP packages) don't
always handle them correctly.
* Add utils helpers for lazy objects (is_lazy, force_non_lazy*)
* Add lazy object handling to utils.Attachment
* Add lazy object handling converters to BasePayload attr
processing where appropriate. (This ends up varying by
the expected attribute type.)
Fixes#34.
Anymail was requiring Mandrill's webhook authentication key for the initial webhook url validation request from Mandrill, but Mandrill doesn't issue the key until that validation request succeeds.
* Defer complaining about missing Mandrill webhook key until actual event post.
* Document the double-deploy process required to set up Mandrill webhooks.
Fixes#46.
Add support for Postmark's recently-released [delivery tracking webhook] to Anymail's normailized status event handling. The existing Anymail tracking webhook URL can be copied to "Delivery webhook" in your Postmark outbound server settings.
Closes#45.
A message's `from_email` and each address in its `to`, `cc`, and `bcc` lists must contain exactly one email address. Previous code would silently ignore additional addresses, leading to unusual behavior. Now, raises new `AnymailInvalidAddress` exception.
Example: `from_email='Widgets, Inc. <widgets@example.com>'` is invalid: it needs double-quotes around the "Widgets, Inc." display-name portion. In earlier versions, this probably would have sent the message from something like "From: Widgets <@localhost>". Now, it will raise an exception.
**Potentially-breaking change:** If your code is using an unquoted display-name containing a comma in an email address, it will now raise an error. In earlier versions, this may have appeared to succeed, but was almost certainly not doing what you intended.
Fixes#44.
* Trailing comma after "anymail" (see #40)
* Note order doesn't matter
* Change tuple to list (match examples to
Django 1.9+ project template)
[ci skip]
Compatibility with Python 2.7 versions older than 2.7.7
* Use Django's constant_time_compare method
* Include sparkpost in test requirements
* Don't use non-public `EnvironmentVarGuard` in tests
Fixes#41
Allows clients that use AnymailMessage or AnymailMessageMixin
to access (e.g.) message.anymail_status.message_id without
an AttributeError, even when using a non-Anymail backend
(e.g., during testing).
Also clarify docs of anymail_status attribute to note it only gets
attached to a normal Django EmailMessage when sent through
an Anymail backend.
(May help with situation described in #36)
Drop `from __future__ import unicode_literals`;
it was there for Python 3.2 compatibility (which
Anymail doesn't support). Ensures tests use normal
strs in Python 2.x.
Allow custom MAILGUN_SENDER_DOMAIN in Anymail
settings. (Replaces need to use global esp_extra.)
Improve docs to cover cases where this is needed.
(esp_extra sender_domain is still supported for
overriding individual messages.)
Fixes#26.
When using a stored template, SparkPost disallows
subject, text, and html. Django's EmailMessage default
empty strings are enough to provoke "Both content
object and template_id are specified" from SparkPost,
so remove them (if empty) when using stored templates.
Update docs and tests; add integration test for template_id.
Fixes#24