Commit Graph

18 Commits

Author SHA1 Message Date
medmunds
10f569cd50 Fix: don't include sender/recipient in AnymailError description
Remove `AnymailError.describe_send`, which added sender and
recipient email addresses to every AnymailError message
(whether or not relevant to the error).

Addresses #245
2022-01-11 17:03:03 -08:00
medmunds
60fbe1e896 Fix: treat first text/plain alternative as plaintext body
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
2022-01-10 15:35:00 -08:00
Mike Edmunds
85cec5e9dc Drop Python 2 and Django 1.11 support
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)
2020-08-01 14:53:10 -07:00
Mike Edmunds
75d7671056 Add merge_metadata for other ESPs
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.
2019-02-23 13:32:28 -08:00
medmunds
52a6d2d822 Tests: stop using sendgrid_v2 backend for settings tests 2018-05-30 16:00:49 -07:00
medmunds
5598c87e62 Backends: identify source of problem in AnymailInvalidAddress message
Include the name of the field with the the unparsable email address
in AnymailInvalidAddress error messages.

Should help tracking down problems like in #98.
2018-04-11 11:50:06 -07:00
medmunds
06c7077e37 Fix: flag extra_headers["To"] as unsupported
Django's SMTP EmailBackend allows spoofing the To header by setting
`message.extra_headers["To"]`` different from `message.to`.

No current Anymail ESP supports this. Treat extra_headers["To"] as
an unsupported ESP feature, to flag attempts to use it.

Also document Anymail's special header handling that replicates
Django's SMTP EmailBackend behavior.
2018-02-27 13:43:58 -08:00
medmunds
07fbeac6bd Feature: Add envelope_sender
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.
2018-02-26 18:42:19 -08:00
medmunds
bd9d92f5a0 Cleanup: centralize Reply-To header handling; case-insensitive headers
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.
2018-02-26 12:25:57 -08:00
medmunds
2faa5f96cb Clean up and document Anymail's test EmailBackend
* 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.
2017-09-01 13:13:25 -07:00
medmunds
8bdc67939a Flake8 clean 2017-04-16 11:43:13 -07:00
medmunds
09bec9e463 Improve error when reply_to isn't list.
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
2017-04-04 11:57:11 -07:00
medmunds
79288603fb Rename EmailBackends for Django consistency
* **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.
2017-01-20 15:47:37 -08:00
Mike Edmunds
e568e50d0c SendGrid: update to new v3 send API (#50)
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
2017-01-19 14:29:15 -08:00
Mike Edmunds
edf2a3ddcf Handle Django lazy strings.
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.
2016-12-30 15:48:08 -05:00
medmunds
f8eafba0df Add pre_send and post_send signals
Closes #8
2016-05-12 21:18:04 -07:00
medmunds
c60790fb52 Use generic TestBackend for base functionality tests
* 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
2016-05-12 17:18:48 -07:00
medmunds
df881fdb75 Allow kwargs overrides for (nearly) all settings
* Update utils.get_anymail_setting to support
  kwargs override of django.conf.settings values
* Use the updated version everywhere
* Switch from ImproperlyConfigured to
  AnymailConfigurationError exception
  (anticipates feature_wehooks change)

Closes #12
2016-04-29 14:34:34 -07:00