-
Notifications
You must be signed in to change notification settings - Fork 133
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SparkPost: error on features incompatible with template_id
Raise an `AnymailUnsupportedFeature` error when trying to use a `template_id` along with other content payload fields that SparkPost silently ignores when template_id is present.
- Loading branch information
Showing
5 changed files
with
93 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -215,6 +215,29 @@ Limitations and quirks | |
management headers. (The list of allowed custom headers does not seem | ||
to be documented.) | ||
|
||
.. _sparkpost-template-limitations: | ||
|
||
**Features incompatible with template_id** | ||
When sending with a :attr:`~anymail.message.AnymailMessage.template_id`, | ||
SparkPost doesn't support attachments, inline images, extra headers, | ||
:attr:`!reply_to`, :attr:`!cc` recipients, or overriding the | ||
:attr:`!from_email`, :attr:`!subject`, or body (text or html) when | ||
sending the message. Some of these can be defined in the template itself, | ||
but SparkPost (often) silently drops them when supplied to their | ||
Transmissions send API. | ||
|
||
.. versionchanged:: 11.0 | ||
|
||
Using features incompatible with :attr:`!template_id` will raise an | ||
:exc:`~anymail.exceptions.AnymailUnsupportedFeature` error. In earlier | ||
releases, Anymail would pass the incompatible content to SparkPost's | ||
API, which in many cases would silently ignore it and send the message | ||
anyway. | ||
|
||
These limitations only apply when using stored templates (with a template_id), | ||
not when using SparkPost's template language for on-the-fly templating | ||
in a message's subject, body, etc. | ||
|
||
**Envelope sender may use domain only** | ||
Anymail's :attr:`~anymail.message.AnymailMessage.envelope_sender` is used to | ||
populate SparkPost's `'return_path'` parameter. Anymail supplies the full | ||
|
@@ -246,7 +269,8 @@ and :ref:`batch sending <batch-send>` with per-recipient merge data. | |
You can use a SparkPost stored template by setting a message's | ||
:attr:`~anymail.message.AnymailMessage.template_id` to the | ||
template's unique id. (When using a stored template, SparkPost prohibits | ||
setting the EmailMessage's subject, text body, or html body.) | ||
setting the EmailMessage's subject, text body, or html body, and has | ||
:ref:`several other limitations <sparkpost-template-limitations>`.) | ||
|
||
Alternatively, you can refer to merge fields directly in an EmailMessage's | ||
subject, body, and other fields---the message itself is used as an | ||
|
@@ -264,6 +288,7 @@ message attributes. | |
to=["[email protected]", "Bob <[email protected]>"] | ||
) | ||
message.template_id = "11806290401558530" # SparkPost id | ||
message.from_email = None # must set after constructor (see below) | ||
message.merge_data = { | ||
'[email protected]': {'name': "Alice", 'order_no': "12345"}, | ||
'[email protected]': {'name': "Bob", 'order_no': "54321"}, | ||
|
@@ -279,6 +304,9 @@ message attributes. | |
}, | ||
} | ||
When using a :attr:`~anymail.message.AnymailMessage.template_id`, you must set the | ||
message's :attr:`!from_email` to ``None`` as shown above. SparkPost does not permit | ||
specifying the from address at send time when using a stored template. | ||
|
||
See `SparkPost's substitutions reference`_ for more information on templates and | ||
batch send with SparkPost. If you need the special `"dynamic" keys for nested substitutions`_, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ | |
AnymailSerializationError, | ||
AnymailUnsupportedFeature, | ||
) | ||
from anymail.message import attach_inline_image_file | ||
from anymail.message import AnymailMessage, attach_inline_image_file | ||
|
||
from .mock_requests_backend import RequestsBackendMockAPITestCase | ||
from .utils import ( | ||
|
@@ -510,9 +510,7 @@ def test_tracking(self): | |
self.assertEqual(data["options"]["click_tracking"], True) | ||
|
||
def test_template_id(self): | ||
message = mail.EmailMultiAlternatives( | ||
from_email="[email protected]", to=["[email protected]"] | ||
) | ||
message = mail.EmailMultiAlternatives(to=["[email protected]"]) | ||
message.template_id = "welcome_template" | ||
message.send() | ||
data = self.get_api_call_json() | ||
|
@@ -522,6 +520,24 @@ def test_template_id(self): | |
self.assertNotIn("text", data["content"]) | ||
self.assertNotIn("html", data["content"]) | ||
|
||
def test_unsupported_content_with_template_id(self): | ||
# Make sure we raise an error for options that SparkPost | ||
# silently ignores when sending with a template_id | ||
message = AnymailMessage( | ||
to=["[email protected]"], | ||
from_email="[email protected]", | ||
reply_to=["[email protected]"], | ||
headers={"X-Custom": "header"}, | ||
template_id="welcome_template", | ||
) | ||
message.attach(filename="test.txt", content="attachment", mimetype="text/plain") | ||
with self.assertRaisesMessage( | ||
AnymailUnsupportedFeature, | ||
"template_id with attachments, extra headers and/or cc recipients," | ||
" from_email, reply_to", | ||
): | ||
message.send() | ||
|
||
def test_merge_data(self): | ||
self.set_mock_result(accepted=4) # two 'to' plus one 'cc' for each 'to' | ||
self.message.to = ["[email protected]", "Bob <[email protected]>"] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters