Postmark: Fix sending templated email to a single recipient

Fix a bug where sending an email with a template_id and a single to address
would cause a Postmark API error.

Thanks @jc-ee for finding and fixing.
This commit is contained in:
jc-ee
2020-04-13 21:48:37 +01:00
committed by GitHub
parent 920d8dd70f
commit 2a36da54e6
3 changed files with 40 additions and 2 deletions

View File

@@ -33,6 +33,8 @@ vNext
Fixes Fixes
~~~~~ ~~~~~
* **Postmark:** Fix API error when sending with template to single recipient.
(Thanks to `@jc-ee`_ for finding and fixing the issue.)
* **SendGrid:** Allow non-batch template send to multiple recipients when * **SendGrid:** Allow non-batch template send to multiple recipients when
`merge_global_data` is set without `merge_data`. (Broken in v6.0. Thanks to `merge_global_data` is set without `merge_data`. (Broken in v6.0. Thanks to
`@vgrebenschikov`_ for the bug report.) `@vgrebenschikov`_ for the bug report.)
@@ -1026,6 +1028,7 @@ Features
.. _@ewingrj: https://github.com/ewingrj .. _@ewingrj: https://github.com/ewingrj
.. _@fdemmer: https://github.com/fdemmer .. _@fdemmer: https://github.com/fdemmer
.. _@janneThoft: https://github.com/janneThoft .. _@janneThoft: https://github.com/janneThoft
.. _@jc-ee: https://github.com/jc-ee
.. _@joshkersey: https://github.com/joshkersey .. _@joshkersey: https://github.com/joshkersey
.. _@Lekensteyn: https://github.com/Lekensteyn .. _@Lekensteyn: https://github.com/Lekensteyn
.. _@lewistaylor: https://github.com/lewistaylor .. _@lewistaylor: https://github.com/lewistaylor

View File

@@ -179,12 +179,19 @@ class PostmarkPayload(RequestsPayload):
return params return params
def serialize_data(self): def serialize_data(self):
data = self.data
api_endpoint = self.get_api_endpoint() api_endpoint = self.get_api_endpoint()
if api_endpoint == "email/batchWithTemplates": if api_endpoint == "email":
data = self.data
elif api_endpoint == "email/batchWithTemplates":
data = {"Messages": [self.data_for_recipient(to) for to in self.to_emails]} data = {"Messages": [self.data_for_recipient(to) for to in self.to_emails]}
elif api_endpoint == "email/batch": elif api_endpoint == "email/batch":
data = [self.data_for_recipient(to) for to in self.to_emails] data = [self.data_for_recipient(to) for to in self.to_emails]
elif api_endpoint == "email/withTemplate/":
assert len(self.to_emails) == 1
data = self.data_for_recipient(self.to_emails[0])
else:
raise AssertionError("PostmarkPayload.serialize_data missing"
" case for api_endpoint %r" % api_endpoint)
return self.serialize_json(data) return self.serialize_json(data)
def data_for_recipient(self, to): def data_for_recipient(self, to):

View File

@@ -450,6 +450,34 @@ class PostmarkBackendAnymailFeatureTests(PostmarkBackendMockAPITestCase):
self.assertEqual(recipients['bob@example.com'].status, 'sent') self.assertEqual(recipients['bob@example.com'].status, 'sent')
self.assertEqual(recipients['bob@example.com'].message_id, 'e2ecbbfc-fe12-463d-b933-9fe22915106d') self.assertEqual(recipients['bob@example.com'].message_id, 'e2ecbbfc-fe12-463d-b933-9fe22915106d')
def test_merge_data_single_recipient(self):
self.set_mock_response(raw=self._mock_batch_response)
message = AnymailMessage(
from_email='from@example.com',
template_id=1234567, # Postmark only supports merge_data content in a template
to=['alice@example.com'],
merge_data={
'alice@example.com': {'name': "Alice", 'group': "Developers"},
'nobody@example.com': {'name': "Not a recipient for this message"},
},
merge_global_data={'group': "Users", 'site': "ExampleCo"}
)
message.send()
self.assert_esp_called('/email/withTemplate/')
data = self.get_api_call_json()
self.assertEqual(data, {
"From": "from@example.com",
"To": "alice@example.com",
"TemplateId": 1234567,
"TemplateModel": {"name": "Alice", "group": "Developers", "site": "ExampleCo"},
})
recipients = message.anymail_status.recipients
self.assertEqual(recipients['alice@example.com'].status, 'sent')
self.assertEqual(recipients['alice@example.com'].message_id, 'b7bc2f4a-e38e-4336-af7d-e6c392c2f817')
def test_merge_data_no_template(self): def test_merge_data_no_template(self):
# merge_data={} can be used to force batch sending without a template # merge_data={} can be used to force batch sending without a template
self.set_mock_response(raw=self._mock_batch_response) self.set_mock_response(raw=self._mock_batch_response)