SendGrid: force empty text and html to " " with template_id

Work around an unexpected limitation in SendGrid template
rendering, where template text or html bodies are omitted
if the supplied message text or html is "". Changing empty
string to " " works around the issue.

https://sendgrid.com/docs/API_Reference/Web_API_v3/Transactional_Templates/smtpapi.html#-Text-or-HTML-Templates

Closes #32
This commit is contained in:
medmunds
2016-10-13 15:15:37 -07:00
parent 771ed513b2
commit a1380b82f3
3 changed files with 27 additions and 0 deletions

View File

@@ -290,6 +290,12 @@ class SendGridPayload(RequestsPayload):
def set_template_id(self, template_id):
self.add_filter('templates', 'enable', 1)
self.add_filter('templates', 'template_id', template_id)
# Must ensure text and html are non-empty, or template parts won't render.
# https://sendgrid.com/docs/API_Reference/Web_API_v3/Transactional_Templates/smtpapi.html#-Text-or-HTML-Templates
if not self.data.get("text", ""):
self.data["text"] = " "
if not self.data.get("html", ""):
self.data["html"] = " "
def set_merge_data(self, merge_data):
# Becomes smtpapi['sub'] in build_merge_data, after we know recipients and merge_field_format.

View File

@@ -282,6 +282,11 @@ your SendGrid template definition where you want the message-specific versions
to appear). If you don't want to supply any additional subject or body content
from your Django app, set those EmailMessage attributes to empty strings.
(Anymail will convert empty text and HTML bodies to single spaces whenever
:attr:`~anymail.message.AnymailMessage.template_id` is set, to ensure the
plaintext and HTML from your template are present in your outgoing email.
This works around a `limitation in SendGrid's template rendering`_.)
See the `SendGrid's template overview`_ and `transactional template docs`_
for more information.
@@ -289,6 +294,8 @@ for more information.
https://sendgrid.com/docs/User_Guide/Transactional_Templates/index.html
.. _transactional template docs:
https://sendgrid.com/docs/API_Reference/Web_API_v3/Transactional_Templates/smtpapi.html
.. _limitation in SendGrid's template rendering:
https://sendgrid.com/docs/API_Reference/Web_API_v3/Transactional_Templates/smtpapi.html#-Text-or-HTML-Templates
.. _sendgrid-webhooks:

View File

@@ -400,6 +400,7 @@ class SendGridBackendAnymailFeatureTests(SendGridBackendMockAPITestCase):
self.assertEqual(smtpapi['filters']['opentrack'], {'settings': {'enable': 0}})
def test_template_id(self):
self.message.attach_alternative("HTML Body", "text/html")
self.message.template_id = "5997fcf6-2b9f-484d-acd5-7e9a99f0dc1f"
self.message.send()
smtpapi = self.get_smtpapi()
@@ -407,6 +408,19 @@ class SendGridBackendAnymailFeatureTests(SendGridBackendMockAPITestCase):
'settings': {'enable': 1,
'template_id': "5997fcf6-2b9f-484d-acd5-7e9a99f0dc1f"}
})
data = self.get_api_call_data()
self.assertEqual(data['text'], "Text Body")
self.assertEqual(data['html'], "HTML Body")
def test_template_id_with_empty_body(self):
# Text and html must be present (and non-empty-string), or the corresponding
# part will not render from the template. Make sure we fill in strings:
message = mail.EmailMessage(from_email='from@example.com', to=['to@example.com'])
message.template_id = "5997fcf6-2b9f-484d-acd5-7e9a99f0dc1f"
message.send()
data = self.get_api_call_data()
self.assertEqual(data['text'], " ") # single space is sufficient
self.assertEqual(data['html'], " ")
def test_merge_data(self):
self.message.from_email = 'from@example.com'