Commit Graph

38 Commits

Author SHA1 Message Date
Mike Edmunds
66c677e4ab [black reformatting] 2024-08-07 13:25:57 -07:00
Mike Edmunds
0776b12331 Feature: Implement merge_headers
Implement and document `merge_headers`
for all other ESPs that can support it. (See #371
for base and Amazon SES implementation.)

Closes #374
2024-06-20 15:31:58 -07:00
Mike Edmunds
05afde0651 SendGrid: support multiple reply_to
Closes #325
2023-07-27 18:37:31 -07:00
medmunds
b4e22c63b3 Reformat code with automated tools
Apply standardized code style
2023-02-06 15:05:24 -08:00
Mike Edmunds
adc92f037b Tests: tox and mock cleanup
* Remove mock dependency
  (mock is now part of standard unittest package)
* Cleanup tox dependency installation logic
2021-06-13 12:13:31 -07: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
920d8dd70f SendGrid: Fix multiple recipients with only merge_global_data
In SendGrid backend, support non-batch template send to multiple
recipients when `merge_global_data` is set without `merge_data`.
Regression introduced in v6.0.

Fixes #179
2020-03-18 17:08:10 -04:00
medmunds
578bad9a57 SendGrid: generate unique message_id for each batch recipient
Closes #139
2019-02-23 15:01:54 -08:00
medmunds
d2d568b6d3 SendGrid: simplify personalizations processing; stop using "sections"
* Rework and simplify personalizations code (that had grown convoluted
  through several feature additions).

* Stop putting merge_global_data in legacy template "sections"; instead
  just merge it into individual personalization substitutions like we
  do for dynamic templates. (The "sections" version didn't add any
  functionality, had the potential for conflicts with the user's own
  template section tags, and was needlessly complex.)
2019-02-23 14:07:01 -08:00
Janne Thoft
85dce5fd6a SendGrid: add merge_metadata
Add support in SendGrid backend for per-recipient metadata.
2019-02-21 12:44:53 -08:00
Mike Edmunds
978996d7b8 Test without optional packages
Tox:
* Add Tox factor for extras (all, none, individual ESP).
  For now, only break out ESPs that have specific extra
  dependencies (amazon_ses, sparkpost).
* Install most package dependencies (including extras)
  through the package itself.
* Use new runtests.py environment vars to limit test tags
  when Tox isn't installing all extras.

Travis:
* Rework matrix to request specific TOXENVs directly;
  drop tox-travis.

Test runner (runtests.py):
* Centralize RUN_LIVE_TESTS logic in runtests.py
* Add ANYMAIL_ONLY_TEST and ANYMAIL_SKIP_TESTS env vars
  (comma-separated lists of tags)

Test implementations:
* Tag all ESP-specific tests with ESP
* Tag live tests with "live"
* Don't import ESP-specific packages at test module level. 
  (Test discovery imports test modules before tag-based filtering.)

Closes #104
2019-02-09 15:04:08 -08:00
medmunds
382ebf249c SendGrid: Improve esp_extra["personalizations"] handling.
Allow merging `esp_extra["personalizations"]` dict into other
message-derived personalizations.

(See comments in #120)
2018-08-27 11:10:48 -07:00
medmunds
dbca13243f SendGrid: support new "dynamic" transactional templates
Closes #120
2018-08-24 18:21:42 -07:00
medmunds
02e6daf9d4 SendGrid: drop deprecated sendgrid_v2 EmailBackend 2018-05-30 16:02:21 -07:00
medmunds
c0172063a4 SendGrid UUID message_id cleanup
* Update authors
* Update integration tests
* Add webhook message_id = smtp-id fallback test case
* Test webhooks ignore smtp-id in non-fallback cases
* Update docs
2018-05-30 13:50:35 -07:00
Josh Kersey
d8d1407c61 SendGrid: change message_id from Message-ID/smtp-id to UUID anymail_id
SendGrid does not always correctly provide the sent Message-ID header value 
to a tracking webhook's smtp-id field, making it unreliable to use for Anymail's 
`message_id`.

Instead, generate a UUID `message_id` for Anymail tracking, and pass it from 
send to webhooks in SendGrid custom args as anymail_id.

Webhooks will fall back to smtp-id for compatibility with previously-sent 
messages that didn't have an anymail_id custom arg.

Fixes #108
2018-05-30 11:52:36 -07: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
8cad1a6367 Keep flake happy on int/long test code 2017-09-14 11:54:30 -07:00
medmunds
3b9cb963ef SendGrid: convert long to str in headers, metadata
SendGrid requires extra headers and metadata values be strings.
Anymail has always coerced int and float; this treats Python 2's
`long` integer type the same.

Fixes #74
2017-09-14 11:45:17 -07:00
medmunds
a67e174f38 Remove deprecated <ESP>Backend names
(Deprecated with warnings since v0.8)
2017-09-08 16:42:28 -07:00
medmunds
8bdc67939a Flake8 clean 2017-04-16 11:43:13 -07:00
medmunds
23800657b8 Support Python 3.6 with Django 1.11-alpha
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
2017-01-22 11:34:57 -08:00
medmunds
56d2b53c2b Use specific ESP name in error messages.
Change  (e.g.,) "ESP API response 400"
to "Mailgun API response 400".
2017-01-22 10:21:19 -08: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
medmunds
a1380b82f3 SendGrid: force empty text and html to " " with template_id
Work around an unexpected limitation in SendGrid template
rendering, where template text or html bodies are omitted
if the supplied message text or html is "". Changing empty
string to " " works around the issue.

https://sendgrid.com/docs/API_Reference/Web_API_v3/Transactional_Templates/smtpapi.html#-Text-or-HTML-Templates

Closes #32
2016-10-13 15:15:37 -07:00
medmunds
771ed513b2 Tests: switch to explicit u"unicode" literals
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.
2016-10-13 14:37:08 -07:00
Adam Chainz
731670427c Tests: Convert readthedocs links to .io
Convert readthedocs links for their .org -> .io migration for hosted projects

As per [their blog post of the 27th April](https://blog.readthedocs.com/securing-subdomains/) ‘Securing subdomains’:

> Starting today, Read the Docs will start hosting projects from subdomains on the domain readthedocs.io, instead of on readthedocs.org. This change addresses some security concerns around site cookies while hosting user generated data on the same domain as our dashboard.

Test Plan: Manually visited all the links I’ve modified.
2016-06-22 14:57:58 -07:00
medmunds
5d417080ee SendGrid: set to to from in batch send.
Set ignored (but required-valid) `to` field to
the from_email for batch send with merge_data.
See https://github.com/anymail/django-anymail/pull/14#issuecomment-220231250
2016-06-01 08:05:51 -07:00
medmunds
995617a130 SendGrid: improve to handling with merge_data
* Add merge_data integration test
* Simplify backend handling for this case
  (also fixes duplicated to's in all_recipients
  from previous fix)
2016-05-18 11:23:01 -07:00
Lewis Taylor
72d899460c SendGrid: Set to field when using merge_data (#14)
* Set to field when using merge_data

The `to` field is required even if providing recipient addresses in x-smtpapi. See https://sendgrid.com/docs/API_Reference/Web_API/mail.html#-send.

* Check data['to'] contains expected emails

* Add space for toname check

* Make `to` expected data contain email only
2016-05-18 11:01:54 -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
75730e8219 Add ESP templates, batch send and merge
* message.template_id to use ESP stored templates
* message.merge_data and merge_global_data
  to supply per-recipient/global merge variables
  (with or without an ESP stored template)
* When using per-recipient merge_data, tell ESP to use
  batch send: individual message per "to" address.
  (Mailgun does this automatically; SendGrid requires
  using a different "to" field; Mandrill requires
  `preserve_recipients=False`; Postmark doesn't
  support *this type* of batch sending with merge data.)
* Allow message.from_email=None (must be set after
  init) and message.subject=None to suppress those
  fields in API calls (for ESPs that allow "From" and
  "Subject" in their template definitions).

Mailgun:
* Emulate merge_global_data by copying to
  recipient-variables for each recipient.

SendGrid:
* Add delimiters to merge field names via
  esp_extra['merge_field_format'] or
  ANYMAIL_SENDGRID_MERGE_FIELD_FORMAT setting.

Mandrill:
* Remove Djrill versions of these features;
  update migration notes.

Closes #5.
2016-05-06 12:27:11 -07:00
medmunds
c7a8c81e32 Remove pre-Django 1.8 compatibility code 2016-04-30 10:33:51 -07:00
medmunds
1372ef21eb SendGrid: merge 'filters' in esp_extra
Previously, setting esp_extra['x-smtpapi']['filters']
would override the entire filters setting, potentially
undoing other Anymail options that use SendGrid
filters (like track_opens).

Now, 'filters' is special-cased, and merged with
any other Anymail filter options.

(We don't do a fully deep merge, because otherwise
there would be no way to use esp_extra to *clear*
Anymail settings.)
2016-04-30 10:21:11 -07:00
medmunds
36461e57b9 Keep angle brackets on SendGrid smtp-id
SendGrid seems to consistently use <angle brackets>
on Message-ID and smtp-id.
2016-04-29 15:05:58 -07:00
medmunds
8e43f29944 Workaround missing smtp-id in SendGrid tracking.
* Add smtp-id in unique_args (metadata), to ensure
  it shows up in click and open events.
* Add SENDGRID_GENERATE_MESSAGE_ID setting,
  default True, to control auto-Message-ID behavior.
* Document it.
2016-04-29 09:44:31 -07:00
medmunds
385d76b53a Move tests out of app module
(Directory structure as suggested in
[Django testing docs][1].)

[1]: https://docs.djangoproject.com/en/1.9/topics/testing/advanced/#using-the-django-test-runner-to-test-reusable-applications
2016-03-21 11:38:58 -07:00