From 539dd36e9d30afa98abe8a4c01e257b26b64613e Mon Sep 17 00:00:00 2001
From: Wojciech Bartosiak
Date: Fri, 3 Aug 2018 17:45:46 +0200
Subject: [PATCH 1/8] adding dynamic template data
---
sendgrid/helpers/mail/personalization.py | 26 ++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/sendgrid/helpers/mail/personalization.py b/sendgrid/helpers/mail/personalization.py
index 8bb4bed0b..196a1203e 100644
--- a/sendgrid/helpers/mail/personalization.py
+++ b/sendgrid/helpers/mail/personalization.py
@@ -13,6 +13,7 @@ def __init__(self):
self._substitutions = []
self._custom_args = []
self._send_at = None
+ self._dynamic_template_data = list()
@property
def tos(self):
@@ -158,6 +159,25 @@ def send_at(self):
def send_at(self, value):
self._send_at = value
+ @property
+ def dynamic_template_data(self):
+ """The DynamicTemplateData that will be carried along with this Personalization.
+
+ :rtype: dict
+ """
+ return self._dynamic_template_data
+
+ @dynamic_template_data.setter
+ def dynamic_template_data(self, value):
+ self._dynamic_template_data = value
+
+ def add_dynamic_template_data(self, dynamic_template_data):
+ """Append item to DynamicTemplateData
+
+ :type dynamic_template_data: dict
+ """
+ self._dynamic_template_data.append(dynamic_template_data)
+
def get(self):
"""
Get a JSON-ready representation of this Personalization.
@@ -198,4 +218,10 @@ def get(self):
if self.send_at is not None:
personalization["send_at"] = self.send_at
+
+ if self.dynamic_template_data:
+ dynamic_template_data = dict()
+ for item in self.dynamic_template_data:
+ dynamic_template_data.update(item)
+ personalization['dynamic_template_data'] = dynamic_template_data
return personalization
From 18936d153c9adbf4fe570e6bc8d23684785ba915 Mon Sep 17 00:00:00 2001
From: Wojciech Bartosiak
Date: Fri, 3 Aug 2018 17:45:52 +0200
Subject: [PATCH 2/8] added tests
---
test/test_mail.py | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/test/test_mail.py b/test/test_mail.py
index 7721b5205..76e280b6c 100644
--- a/test/test_mail.py
+++ b/test/test_mail.py
@@ -562,3 +562,42 @@ def test_disable_tracking(self):
def test_directly_setting_substitutions(self):
personalization = Personalization()
personalization.substitutions = [{'a': 0}]
+
+ def test_simple_dynamic_template_data(self):
+ """Minimum required to send an email"""
+ mail = Mail()
+
+ mail.from_email = Email("test@example.com")
+
+ mail.subject = "Hello World from the SendGrid Python Library"
+
+ personalization = Personalization()
+ personalization.add_to(Email("test@example.com"))
+ personalization.add_dynamic_template_data({'foo': 'bar'})
+ mail.add_personalization(personalization)
+
+ mail.add_content(Content("text/plain", "some text here"))
+ mail.add_content(
+ Content(
+ "text/html",
+ "some text here"))
+
+ self.assertEqual(
+ json.dumps(
+ mail.get(),
+ sort_keys=True),
+ '{"content": [{"type": "text/plain", "value": "some text here"}, '
+ '{"type": "text/html", '
+ '"value": "some text here"}], '
+ '"from": {"email": "test@example.com"}, '
+ '"personalizations": [{'
+ '"dynamic_template_data": {"foo": "bar"}, '
+ '"to": [{"email": "test@example.com"}]'
+ '}], '
+ '"subject": "Hello World from the SendGrid Python Library"'
+ '}'
+ )
+
+ self.assertTrue(isinstance(str(mail), str))
+
+
From 7edd5db7d45327aedd7f0bcb48d39b4c622dc4f4 Mon Sep 17 00:00:00 2001
From: Wojciech Bartosiak
Date: Fri, 3 Aug 2018 18:09:08 +0200
Subject: [PATCH 3/8] adding dynamic tag
---
sendgrid/helpers/mail/__init__.py | 1 +
sendgrid/helpers/mail/dynamic_template_tag.py | 43 +++++++++++++++++++
sendgrid/helpers/mail/personalization.py | 4 +-
test/test_mail.py | 6 +--
4 files changed, 49 insertions(+), 5 deletions(-)
create mode 100644 sendgrid/helpers/mail/dynamic_template_tag.py
diff --git a/sendgrid/helpers/mail/__init__.py b/sendgrid/helpers/mail/__init__.py
index 1dd769e99..2b6fdc650 100644
--- a/sendgrid/helpers/mail/__init__.py
+++ b/sendgrid/helpers/mail/__init__.py
@@ -22,3 +22,4 @@
from .substitution import Substitution
from .tracking_settings import TrackingSettings
from .validators import ValidateAPIKey
+from .dynamic_template_tag import DynamicTemplateTag
diff --git a/sendgrid/helpers/mail/dynamic_template_tag.py b/sendgrid/helpers/mail/dynamic_template_tag.py
new file mode 100644
index 000000000..f17ed7289
--- /dev/null
+++ b/sendgrid/helpers/mail/dynamic_template_tag.py
@@ -0,0 +1,43 @@
+class DynamicTemplateTag(object):
+ """A dynamic template tag can be used to be applied to the text and HTML contents of
+ the body of your email, as well as in the Subject and Reply-To parameters.
+ """
+
+ def __init__(self, key=None, value=None):
+ """Create a DynamicTemplateTag with the given key and value.
+
+ :param key: Text to be replaced with "value" param
+ :type key: string, optional
+ :param value: Value to substitute into email, can be any JSON serializable object
+ :type value: any
+ """
+ self._key = key
+ self._value = value
+
+ @property
+ def key(self):
+ return self._key
+
+ @key.setter
+ def key(self, value):
+ self._key = value
+
+ @property
+ def value(self):
+ return self._value
+
+ @value.setter
+ def value(self, value):
+ self._value = value
+
+ def get(self):
+ """
+ Get a JSON-ready representation of this Substitution.
+
+ :returns: This DynamicTemplateTag, ready for use in a request body.
+ :rtype: dict
+ """
+ dynamic_template_tag = {}
+ if self.key is not None and self.value is not None:
+ dynamic_template_tag[self.key] = self.value
+ return dynamic_template_tag
diff --git a/sendgrid/helpers/mail/personalization.py b/sendgrid/helpers/mail/personalization.py
index 196a1203e..645e6ae52 100644
--- a/sendgrid/helpers/mail/personalization.py
+++ b/sendgrid/helpers/mail/personalization.py
@@ -174,9 +174,9 @@ def dynamic_template_data(self, value):
def add_dynamic_template_data(self, dynamic_template_data):
"""Append item to DynamicTemplateData
- :type dynamic_template_data: dict
+ :type dynamic_template_data: DynamicTemplateTag
"""
- self._dynamic_template_data.append(dynamic_template_data)
+ self._dynamic_template_data.append(dynamic_template_data.get())
def get(self):
"""
diff --git a/test/test_mail.py b/test/test_mail.py
index 76e280b6c..89ed0ba83 100644
--- a/test/test_mail.py
+++ b/test/test_mail.py
@@ -26,8 +26,8 @@
SubscriptionTracking,
Substitution,
TrackingSettings,
- ValidateAPIKey
-)
+ ValidateAPIKey,
+ DynamicTemplateTag)
try:
import unittest2 as unittest
@@ -573,7 +573,7 @@ def test_simple_dynamic_template_data(self):
personalization = Personalization()
personalization.add_to(Email("test@example.com"))
- personalization.add_dynamic_template_data({'foo': 'bar'})
+ personalization.add_dynamic_template_data(DynamicTemplateTag('foo', 'bar'))
mail.add_personalization(personalization)
mail.add_content(Content("text/plain", "some text here"))
From d83b3f70c8044c2af490f02e5f40eafdad6c9b53 Mon Sep 17 00:00:00 2001
From: Wojciech Bartosiak
Date: Fri, 3 Aug 2018 18:09:22 +0200
Subject: [PATCH 4/8] added documentation
---
use_cases/dynamic_templates.md | 132 +++++++++++++++++++++++++++++++++
1 file changed, 132 insertions(+)
create mode 100644 use_cases/dynamic_templates.md
diff --git a/use_cases/dynamic_templates.md b/use_cases/dynamic_templates.md
new file mode 100644
index 000000000..cecc71457
--- /dev/null
+++ b/use_cases/dynamic_templates.md
@@ -0,0 +1,132 @@
+# Dynamic Transactional Templates
+
+For this example, we assume you have created a [dynamic transactional template](https://sendgrid.com/docs/User_Guide/Transactional_Templates/Create_and_edit_dynamic_transactional_templates.html). Following is the template content we used for testing.
+
+Template ID (replace with your own):
+
+```text
+13b8f94f-bcae-4ec6-b752-70d6cb59f932
+```
+
+Email Subject:
+
+```text
+{{subject}}
+```
+
+Template Body:
+
+```html
+
+
+
+
+
+Hello {{name}},
+
+I'm glad you are trying out the dynamic template feature!
+
+
+
+
+
+ Values provided
+ |
+
+ {{#each this}}
+
+ {{@key}} |
+ {{this}} |
+
+ {{/each}}
+
+
+
+I hope you are having a great day :)
+
+
+
+```
+
+## With Mail Helper Class
+
+```python
+import sendgrid
+import os
+from sendgrid.helpers.mail import Email, Content, DynamicTemplateTag, Mail
+try:
+ # Python 3
+ import urllib.request as urllib
+except ImportError:
+ # Python 2
+ import urllib2 as urllib
+
+sg = sendgrid.SendGridAPIClient(apikey=os.environ.get('SENDGRID_API_KEY'))
+from_email = Email("test@example.com")
+subject = "I'm replacing the subject tag"
+to_email = Email("test@example.com")
+content = Content("text/html", "I'm replacing the body tag")
+mail = Mail(from_email, subject, to_email, content)
+mail.personalizations[0].add_dynamic_template_data(DynamicTemplateTag("name", "Example User"))
+mail.personalizations[0].add_dynamic_template_data(DynamicTemplateTag("foo", "bar"))
+mail.personalizations[0].add_dynamic_template_data(DynamicTemplateTag("extra", "SG rocks!"))
+mail.template_id = "13b8f94f-bcae-4ec6-b752-70d6cb59f932"
+try:
+ response = sg.client.mail.send.post(request_body=mail.get())
+except urllib.HTTPError as e:
+ print (e.read())
+ exit()
+print(response.status_code)
+print(response.body)
+print(response.headers)
+```
+
+## Without Mail Helper Class
+
+```python
+import sendgrid
+import os
+try:
+ # Python 3
+ import urllib.request as urllib
+except ImportError:
+ # Python 2
+ import urllib2 as urllib
+
+sg = sendgrid.SendGridAPIClient(apikey=os.environ.get('SENDGRID_API_KEY'))
+data = {
+ "personalizations": [
+ {
+ "to": [
+ {
+ "email": "test@example.com"
+ }
+ ],
+ "substitutions": {
+ "-name-": "Example User",
+ "-city-": "Denver"
+ },
+ "subject": "I'm replacing the subject tag"
+ },
+ ],
+ "from": {
+ "email": "test@example.com"
+ },
+ "content": [
+ {
+ "type": "text/html",
+ "value": "I'm replacing the body tag"
+ }
+ ],
+ "template_id": "13b8f94f-bcae-4ec6-b752-70d6cb59f932"
+}
+try:
+ response = sg.client.mail.send.post(request_body=data)
+except urllib.HTTPError as e:
+ print (e.read())
+ exit()
+print(response.status_code)
+print(response.body)
+print(response.headers)
+```
+
From 90ea913cb924a21e71f32a52c45a509d461de39e Mon Sep 17 00:00:00 2001
From: Wojciech Bartosiak
Date: Fri, 3 Aug 2018 18:10:50 +0200
Subject: [PATCH 5/8] included docs
---
use_cases/README.md | 1 +
.../{dynamic_templates.md => dynamic_transactional_templates.md} | 0
2 files changed, 1 insertion(+)
rename use_cases/{dynamic_templates.md => dynamic_transactional_templates.md} (100%)
diff --git a/use_cases/README.md b/use_cases/README.md
index 188464d09..1f6c64fc0 100644
--- a/use_cases/README.md
+++ b/use_cases/README.md
@@ -15,6 +15,7 @@ This directory provides examples for specific use cases of this library. Please
* [Asynchronous Mail Send](asynchronous_mail_send.md)
* [Attachment](attachment.md)
* [Transactional Templates](transational_templates.md)
+* [Dynamic Transactional Templates](dynamic_transactional_templates.md)
### Library Features
* [Error Handling](error_handling.md)
\ No newline at end of file
diff --git a/use_cases/dynamic_templates.md b/use_cases/dynamic_transactional_templates.md
similarity index 100%
rename from use_cases/dynamic_templates.md
rename to use_cases/dynamic_transactional_templates.md
From 80c7c54bff62936b203c096dace9e4de939bdfd7 Mon Sep 17 00:00:00 2001
From: Wojciech Bartosiak
Date: Fri, 3 Aug 2018 18:24:18 +0200
Subject: [PATCH 6/8] improved docs when not using helper class
---
use_cases/dynamic_transactional_templates.md | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/use_cases/dynamic_transactional_templates.md b/use_cases/dynamic_transactional_templates.md
index cecc71457..0d8057532 100644
--- a/use_cases/dynamic_transactional_templates.md
+++ b/use_cases/dynamic_transactional_templates.md
@@ -102,10 +102,7 @@ data = {
"email": "test@example.com"
}
],
- "substitutions": {
- "-name-": "Example User",
- "-city-": "Denver"
- },
+ "dynamic_template_data": {"extra": "SG rocks!", "foo": "bar", "name": "Example User"},
"subject": "I'm replacing the subject tag"
},
],
From 30a6be7329d777995ac0b34c538acb99d00ad4a9 Mon Sep 17 00:00:00 2001
From: af4ro <1997anshul@gmail.com>
Date: Fri, 10 Aug 2018 10:37:40 -0700
Subject: [PATCH 7/8] Changed defaults, code cleanup and added an extensive
test
---
sendgrid/helpers/mail/dynamic_template_tag.py | 2 +-
sendgrid/helpers/mail/personalization.py | 12 ++++++------
test/test_mail.py | 11 +++++++----
3 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/sendgrid/helpers/mail/dynamic_template_tag.py b/sendgrid/helpers/mail/dynamic_template_tag.py
index f17ed7289..fad5baf52 100644
--- a/sendgrid/helpers/mail/dynamic_template_tag.py
+++ b/sendgrid/helpers/mail/dynamic_template_tag.py
@@ -37,7 +37,7 @@ def get(self):
:returns: This DynamicTemplateTag, ready for use in a request body.
:rtype: dict
"""
- dynamic_template_tag = {}
+ dynamic_template_tag = dict()
if self.key is not None and self.value is not None:
dynamic_template_tag[self.key] = self.value
return dynamic_template_tag
diff --git a/sendgrid/helpers/mail/personalization.py b/sendgrid/helpers/mail/personalization.py
index 645e6ae52..caea36da7 100644
--- a/sendgrid/helpers/mail/personalization.py
+++ b/sendgrid/helpers/mail/personalization.py
@@ -1,3 +1,5 @@
+from copy import deepcopy
+
class Personalization(object):
"""A Personalization defines who should receive an individual message and
how that message should be handled.
@@ -13,7 +15,7 @@ def __init__(self):
self._substitutions = []
self._custom_args = []
self._send_at = None
- self._dynamic_template_data = list()
+ self._dynamic_template_data = dict()
@property
def tos(self):
@@ -176,7 +178,7 @@ def add_dynamic_template_data(self, dynamic_template_data):
:type dynamic_template_data: DynamicTemplateTag
"""
- self._dynamic_template_data.append(dynamic_template_data.get())
+ self._dynamic_template_data.update(dynamic_template_data.get())
def get(self):
"""
@@ -220,8 +222,6 @@ def get(self):
personalization["send_at"] = self.send_at
if self.dynamic_template_data:
- dynamic_template_data = dict()
- for item in self.dynamic_template_data:
- dynamic_template_data.update(item)
- personalization['dynamic_template_data'] = dynamic_template_data
+ personalization['dynamic_template_data'] = deepcopy(self.dynamic_template_data)
+
return personalization
diff --git a/test/test_mail.py b/test/test_mail.py
index 89ed0ba83..1c18306ee 100644
--- a/test/test_mail.py
+++ b/test/test_mail.py
@@ -73,7 +73,7 @@ def test_sendgridAPIKey(self):
)
#Exception should be thrown
- except Exception as e:
+ except Exception:
pass
#Exception not thrown
@@ -563,8 +563,8 @@ def test_directly_setting_substitutions(self):
personalization = Personalization()
personalization.substitutions = [{'a': 0}]
- def test_simple_dynamic_template_data(self):
- """Minimum required to send an email"""
+ def test_dynamic_template_data(self):
+ """Test for minimum requirements, redundancy and nested items"""
mail = Mail()
mail.from_email = Email("test@example.com")
@@ -574,6 +574,9 @@ def test_simple_dynamic_template_data(self):
personalization = Personalization()
personalization.add_to(Email("test@example.com"))
personalization.add_dynamic_template_data(DynamicTemplateTag('foo', 'bar'))
+ personalization.add_dynamic_template_data(DynamicTemplateTag('one', 'more'))
+ personalization.add_dynamic_template_data(DynamicTemplateTag('foo', 'bar1'))
+ personalization.add_dynamic_template_data(DynamicTemplateTag('items', [{"total": "100"}, {"more": "things"}]))
mail.add_personalization(personalization)
mail.add_content(Content("text/plain", "some text here"))
@@ -591,7 +594,7 @@ def test_simple_dynamic_template_data(self):
'"value": "some text here"}], '
'"from": {"email": "test@example.com"}, '
'"personalizations": [{'
- '"dynamic_template_data": {"foo": "bar"}, '
+ '"dynamic_template_data": {"foo": "bar1", "items": [{"total": "100"}, {"more": "things"}], "one": "more"}, '
'"to": [{"email": "test@example.com"}]'
'}], '
'"subject": "Hello World from the SendGrid Python Library"'
From 6671e9546ee9cf374adb49bf82eb42ba8ae9d3cd Mon Sep 17 00:00:00 2001
From: af4ro <1997anshul@gmail.com>
Date: Fri, 10 Aug 2018 14:53:44 -0700
Subject: [PATCH 8/8] Example and usage updates
---
examples/helpers/mail/mail_example.py | 28 ++++++++++++++++++++
use_cases/dynamic_transactional_templates.md | 10 ++++---
2 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/examples/helpers/mail/mail_example.py b/examples/helpers/mail/mail_example.py
index b2de7f0a0..42a50b028 100644
--- a/examples/helpers/mail/mail_example.py
+++ b/examples/helpers/mail/mail_example.py
@@ -212,6 +212,34 @@ def send_kitchen_sink():
print(response.body)
+def dynamic_template_usage():
+ """
+ Sample usage of dynamic (handlebars) transactional templates.
+ To make this work, you should have dynamic template created within your
+ SendGrid account.
+ In this example the template may look like:
+ Hello {{name}}! Here is {{foo}} and also {{extra}}!
+ """
+ sg = SendGridAPIClient(apikey=os.environ.get('SENDGRID_API_KEY'))
+ from_email = Email("test@example.com")
+ subject = "I'm replacing the subject tag"
+ to_email = Email("test@example.com")
+ content = Content("text/html", "I'm replacing the body tag")
+ mail = Mail(from_email, subject, to_email, content)
+
+ p = Personalization()
+ p.add_dynamic_template_data(DynamicTemplateTag("name", "Example User"))
+ p.add_dynamic_template_data(DynamicTemplateTag("foo", "bar"))
+ p.add_dynamic_template_data(DynamicTemplateTag("extra", "SG rocks!"))
+ mail.template_id = "13b8f94f-bcae-4ec6-b752-70d6cb59f932"
+ mail.add_personalization(p)
+
+ response = sg.client.mail.send.post(request_body=mail.get())
+ print(response.status_code)
+ print(response.body)
+ print(response.headers)
+
+
# this will actually send an email
send_hello_email()
diff --git a/use_cases/dynamic_transactional_templates.md b/use_cases/dynamic_transactional_templates.md
index 0d8057532..e8bf8329d 100644
--- a/use_cases/dynamic_transactional_templates.md
+++ b/use_cases/dynamic_transactional_templates.md
@@ -67,10 +67,14 @@ subject = "I'm replacing the subject tag"
to_email = Email("test@example.com")
content = Content("text/html", "I'm replacing the body tag")
mail = Mail(from_email, subject, to_email, content)
-mail.personalizations[0].add_dynamic_template_data(DynamicTemplateTag("name", "Example User"))
-mail.personalizations[0].add_dynamic_template_data(DynamicTemplateTag("foo", "bar"))
-mail.personalizations[0].add_dynamic_template_data(DynamicTemplateTag("extra", "SG rocks!"))
+
+p = Personalization()
+p.add_dynamic_template_data(DynamicTemplateTag("name", "Example User"))
+p.add_dynamic_template_data(DynamicTemplateTag("foo", "bar"))
+p.add_dynamic_template_data(DynamicTemplateTag("extra", "SG rocks!"))
mail.template_id = "13b8f94f-bcae-4ec6-b752-70d6cb59f932"
+mail.add_personalization(p)
+
try:
response = sg.client.mail.send.post(request_body=mail.get())
except urllib.HTTPError as e: