diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bd1526e..1eff486 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -25,6 +25,20 @@ Release history ^^^^^^^^^^^^^^^ .. This extra heading level keeps the ToC from becoming unmanageably long +vNext +----- + +*Unreleased changes* + +Fixes +~~~~~ + +* **SparkPost:** Drop support for multiple `from_email` addresses. SparkPost has + started issuing a cryptic "No sending domain specified" error for this case; with + this fix, Anymail will now treat it as an unsupported feature. + + + v8.1 ---- diff --git a/anymail/backends/sparkpost.py b/anymail/backends/sparkpost.py index 988cc3d..0dc7f8c 100644 --- a/anymail/backends/sparkpost.py +++ b/anymail/backends/sparkpost.py @@ -117,10 +117,8 @@ class SparkPostPayload(RequestsPayload): "recipients": [], } - def set_from_email_list(self, emails): - # SparkPost supports multiple From email addresses, - # as a single comma-separated string - self.data["content"]["from"] = ", ".join(email.address for email in emails) + def set_from_email(self, email): + self.data["content"]["from"] = email.address def set_to(self, emails): if emails: diff --git a/docs/esps/sparkpost.rst b/docs/esps/sparkpost.rst index ec5f94a..404500f 100644 --- a/docs/esps/sparkpost.rst +++ b/docs/esps/sparkpost.rst @@ -213,6 +213,18 @@ Limitations and quirks use only the domain portion and substitute its own encoded mailbox before the @. +**Multiple from_email addresses** + Prior to November, 2020, SparkPost supporting sending messages with multiple + *From* addresses. (This is technically allowed by email specs, but many + ISPs bounce such messages.) Anymail v8.1 and earlier will pass multiple + ``from_email`` addresses to SparkPost's API. + + SparkPost has since dropped support for more than one from address, and now issues + error code 7001 "No sending domain specified". To avoid confusion, Anymail v8.2 + treats multiple from addresses as an unsupported feature in the SparkPost backend. + + .. versionchanged:: 8.2 + .. _sparkpost-templates: diff --git a/tests/test_sparkpost_backend.py b/tests/test_sparkpost_backend.py index 3aff660..7474bc9 100644 --- a/tests/test_sparkpost_backend.py +++ b/tests/test_sparkpost_backend.py @@ -10,7 +10,7 @@ from django.test import override_settings, tag from django.utils.timezone import get_fixed_timezone, override as override_current_timezone, utc from anymail.exceptions import ( - AnymailAPIError, AnymailConfigurationError, AnymailInvalidAddress, AnymailRecipientsRefused, + AnymailAPIError, AnymailConfigurationError, AnymailRecipientsRefused, AnymailSerializationError, AnymailUnsupportedFeature) from anymail.message import attach_inline_image_file @@ -318,20 +318,6 @@ class SparkPostBackendStandardEmailTests(SparkPostBackendMockAPITestCase): }, }]) - def test_multiple_from_emails(self): - """SparkPost supports multiple addresses in from_email""" - self.message.from_email = 'first@example.com, "From, also" ' - self.message.send() - data = self.get_api_call_json() - self.assertEqual(data["content"]["from"], - 'first@example.com, "From, also" ') - - # Make sure the far-more-likely scenario of a single from_email - # with an unquoted display-name issues a reasonable error: - self.message.from_email = 'Unquoted, display-name ' - with self.assertRaises(AnymailInvalidAddress): - self.message.send() - def test_api_failure(self): self.set_mock_response(status_code=400) with self.assertRaisesMessage(AnymailAPIError, "SparkPost API response 400"): diff --git a/tests/test_sparkpost_integration.py b/tests/test_sparkpost_integration.py index 3d9a8d3..013c936 100644 --- a/tests/test_sparkpost_integration.py +++ b/tests/test_sparkpost_integration.py @@ -59,9 +59,7 @@ class SparkPostBackendIntegrationTests(AnymailTestMixin, SimpleTestCase): message = AnymailMessage( subject="Anymail all-options integration test", body="This is the text body", - # Caution: although SparkPost allows multiple From addresses, - # many ISPs will just bounce email that tries it... - from_email="Test From , also-from@test-sp.anymail.info", + from_email="Test From ", to=["to1@test.sink.sparkpostmail.com", "Recipient 2 "], # Limit the live b/cc's to avoid running through our small monthly allowance: # cc=["cc1@test.sink.sparkpostmail.com", "Copy 2 "],