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.
This commit is contained in:
medmunds
2016-05-03 18:25:37 -07:00
parent 271eb5c926
commit 75730e8219
20 changed files with 882 additions and 245 deletions

View File

@@ -332,6 +332,34 @@ class PostmarkBackendAnymailFeatureTests(PostmarkBackendMockAPITestCase):
with self.assertRaisesMessage(AnymailUnsupportedFeature, 'track_clicks'):
self.message.send()
def test_template(self):
self.message.template_id = 1234567
# Postmark doesn't support per-recipient merge_data
self.message.merge_global_data = {'name': "Alice", 'group': "Developers"}
self.message.send()
self.assert_esp_called('/email/withTemplate/')
data = self.get_api_call_json()
self.assertEqual(data['TemplateId'], 1234567)
self.assertEqual(data['TemplateModel'], {'name': "Alice", 'group': "Developers"})
def test_merge_data(self):
self.message.merge_data = {
'alice@example.com': {'name': "Alice", 'group': "Developers"},
}
with self.assertRaisesMessage(AnymailUnsupportedFeature, 'merge_data'):
self.message.send()
def test_missing_subject(self):
"""Make sure a missing subject omits Subject from API call.
(Allows use of template subject)
"""
self.message.template_id = 1234567
self.message.subject = None
self.message.send()
data = self.get_api_call_json()
self.assertNotIn('Subject', data)
def test_default_omits_options(self):
"""Make sure by default we don't send any ESP-specific options.
@@ -342,6 +370,8 @@ class PostmarkBackendAnymailFeatureTests(PostmarkBackendMockAPITestCase):
self.message.send()
data = self.get_api_call_json()
self.assertNotIn('Tag', data)
self.assertNotIn('TemplateId', data)
self.assertNotIn('TemplateModel', data)
self.assertNotIn('TrackOpens', data)
def test_esp_extra(self):