SparkPost: remove empty content params with template_id

When using a stored template, SparkPost disallows
subject, text, and html. Django's EmailMessage default
empty strings are enough to provoke "Both content
object and template_id are specified" from SparkPost,
so remove them (if empty) when using stored templates.

Update docs and tests; add integration test for template_id.

Fixes #24
This commit is contained in:
medmunds
2016-06-24 12:13:32 -07:00
parent 0c5911ca34
commit f95be248ec
4 changed files with 38 additions and 4 deletions

View File

@@ -104,6 +104,15 @@ class SparkPostPayload(BasePayload):
if recipients: if recipients:
self.params['recipients'] = recipients self.params['recipients'] = recipients
# Must remove empty string "content" params when using stored template
if self.params.get('template', None):
for content_param in ['subject', 'text', 'html']:
try:
if not self.params[content_param]:
del self.params[content_param]
except KeyError:
pass
return self.params return self.params
def set_from_email(self, email): def set_from_email(self, email):

View File

@@ -140,8 +140,11 @@ and :ref:`batch sending <batch-send>` with per-recipient merge data.
You can use a SparkPost stored template by setting a message's You can use a SparkPost stored template by setting a message's
:attr:`~anymail.message.AnymailMessage.template_id` to the :attr:`~anymail.message.AnymailMessage.template_id` to the
template's unique id. Alternatively, you can refer to merge fields template's unique id. (When using a stored template, SparkPost prohibits
directly in an EmailMessage---the message itself is used as an setting the EmailMessage's subject, text body, or html body.)
Alternatively, you can refer to merge fields directly in an EmailMessage's
subject, body, and other fields---the message itself is used as an
on-the-fly template. on-the-fly template.
In either case, supply the merge data values with Anymail's In either case, supply the merge data values with Anymail's

View File

@@ -390,10 +390,15 @@ class SparkPostBackendAnymailFeatureTests(SparkPostBackendMockAPITestCase):
self.assertEqual(params['track_clicks'], True) self.assertEqual(params['track_clicks'], True)
def test_template_id(self): def test_template_id(self):
self.message.template_id = "welcome_template" message = mail.EmailMultiAlternatives(from_email='from@example.com', to=['to@example.com'])
self.message.send() message.template_id = "welcome_template"
message.send()
params = self.get_send_params() params = self.get_send_params()
self.assertEqual(params['template'], "welcome_template") self.assertEqual(params['template'], "welcome_template")
# SparkPost disallows all content (even empty strings) with stored template:
self.assertNotIn('subject', params)
self.assertNotIn('text', params)
self.assertNotIn('html', params)
def test_merge_data(self): def test_merge_data(self):
self.set_mock_response(accepted=2) self.set_mock_response(accepted=2)

View File

@@ -107,6 +107,23 @@ class SparkPostBackendIntegrationTests(SimpleTestCase, AnymailTestMixin):
self.assertEqual(recipient_status['to1@test.sink.sparkpostmail.com'].status, 'queued') self.assertEqual(recipient_status['to1@test.sink.sparkpostmail.com'].status, 'queued')
self.assertEqual(recipient_status['to2@test.sink.sparkpostmail.com'].status, 'queued') self.assertEqual(recipient_status['to2@test.sink.sparkpostmail.com'].status, 'queued')
def test_stored_template(self):
message = AnymailMessage(
template_id='test-template', # a real template in our SparkPost test account
to=["to1@test.sink.sparkpostmail.com"],
merge_data={
'to1@test.sink.sparkpostmail.com': {
'name': "Test Recipient",
}
},
merge_global_data={
'order': '12345',
},
)
message.send()
recipient_status = message.anymail_status.recipients
self.assertEqual(recipient_status['to1@test.sink.sparkpostmail.com'].status, 'queued')
@override_settings(ANYMAIL_SPARKPOST_API_KEY="Hey, that's not an API key!") @override_settings(ANYMAIL_SPARKPOST_API_KEY="Hey, that's not an API key!")
def test_invalid_api_key(self): def test_invalid_api_key(self):
with self.assertRaises(AnymailAPIError) as cm: with self.assertRaises(AnymailAPIError) as cm: