Add new `merge_headers` message option
for per-recipient headers with template sends.
* Support in base backend
* Implement in Amazon SES backend
(Requires boto3 >= 1.34.98.)
---------
Co-authored-by: Mike Edmunds <medmunds@gmail.com>
Improve handling of alternative parts and `content_subtype`
to match how Django's SMTP backend handles some unusual cases.
Change Test backend to support (and record) text/* alternative
parts. (But still reject other types of alternatives.)
Fixes#252
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)
Support merge_metadata in Mailgun, Mailjet, Mandrill, Postmark,
SparkPost, and Test backends. (SendGrid covered in earlier PR.)
Also:
* Add `merge_metadata` to AnymailMessage, AnymailMessageMixin
* Add `is_batch()` logic to BasePayload, for consistent handling
* Docs
Note: Mailjet implementation switches *all* batch sending from their
"Recipients" field to to the "Messages" array bulk sending option.
This allows an independent payload for each batch recipient.
In addition to supporting merge_metadata, this also removes the
prior limitation on mixing Cc/Bcc with merge_data.
Closes#141.
New EmailMessage attribute `envelope_sender` controls ESP's sender,
sending domain, or return path where supported:
* Mailgun: overrides SENDER_DOMAIN on individual message
(domain portion only)
* Mailjet: becomes `Sender` API param
* Mandrill: becomes `return_path_domain` API param
(domain portion only)
* SparkPost: becomes `return_path` API param
* Other ESPs: not believed to be supported
Also support undocumented Django SMTP backend behavior, where envelope
sender is given by `message.from_email` when
`message.extra_headers["From"]` is set. Fixes#91.
* Un-hardcode status message_id in test backend
For the test EmailBackend, get message ID's based on array position in
`mail.outbox`, so that tests can predict the message ID.
* Add a console backend for use in development
Adds an EmailBackend derived from both Anymail's test backend and
Django's console backend, to provide anymail statuses and signal
handling while printing messages to the console. For use during
development on localhost.
Closes#87
Within an EmailAddress (previously ParsedEmail object), properties
now match Python 3.6 email.headerregistry.Address naming:
* .email --> .addr_spec
* .name --> .display_name
* .localpart --> .username
(Completes work started in 386668908423d1d4eade90cf7a21a546a1e96514;
this updates remaining uses of old names and removes them.)
* Change Anymail's test EmailBackend to collect sent messages in
django.core.mail.outbox, same as Django's own locmem EmailBackend.
(So Django's test runner will automatically clear accumulated mail
between test cases.)
* Rename EmailMessage `test_response` attr to `anymail_test_response`
to avoid conflicts, and record merged ESP send params in
new `anymail_send_params` attr.
* Add docs
Closes#36.
* **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.
* Create generic TestBackend that simply collects
send parameters
* Change BackendSettingsTests to TestBackend,
and add some missing cases
* Add UnsupportedFeatureTests
* Replace repetitive per-backend SEND_DEFAULTS
test cases with single (and more comprehensive)
SendDefaultsTests