diff --git a/sendgrid/helpers/mail/__init__.py b/sendgrid/helpers/mail/__init__.py
index 15cc1cc7e..28d80ac18 100644
--- a/sendgrid/helpers/mail/__init__.py
+++ b/sendgrid/helpers/mail/__init__.py
@@ -27,6 +27,7 @@
from .groups_to_display import GroupsToDisplay
from .header import Header
from .html_content import HtmlContent
+from .amp_html_content import AmpHtmlContent
from .ip_pool_name import IpPoolName
from .mail_settings import MailSettings
from .mail import Mail
diff --git a/sendgrid/helpers/mail/amp_html_content.py b/sendgrid/helpers/mail/amp_html_content.py
new file mode 100644
index 000000000..1a282053f
--- /dev/null
+++ b/sendgrid/helpers/mail/amp_html_content.py
@@ -0,0 +1,59 @@
+from .content import Content
+from .validators import ValidateApiKey
+
+
+class AmpHtmlContent(Content):
+ """AMP HTML content to be included in your email."""
+
+ def __init__(self, content):
+ """Create an AMP HTML Content with the specified MIME type and content.
+
+ :param content: The AMP HTML content.
+ :type content: string
+ """
+ self._content = None
+ self._validator = ValidateApiKey()
+
+ if content is not None:
+ self.content = content
+
+ @property
+ def mime_type(self):
+ """The MIME type for AMP HTML content.
+
+ :rtype: string
+ """
+ return "text/x-amp-html"
+
+ @property
+ def content(self):
+ """The actual AMP HTML content.
+
+ :rtype: string
+ """
+ return self._content
+
+ @content.setter
+ def content(self, value):
+ """The actual AMP HTML content.
+
+ :param value: The actual AMP HTML content.
+ :type value: string
+ """
+ self._validator.validate_message_dict(value)
+ self._content = value
+
+ def get(self):
+ """
+ Get a JSON-ready representation of this AmpContent.
+
+ :returns: This AmpContent, ready for use in a request body.
+ :rtype: dict
+ """
+ content = {}
+ if self.mime_type is not None:
+ content["type"] = self.mime_type
+
+ if self.content is not None:
+ content["value"] = self.content
+ return content
diff --git a/sendgrid/helpers/mail/content.py b/sendgrid/helpers/mail/content.py
index 73bf9f64d..618eee917 100644
--- a/sendgrid/helpers/mail/content.py
+++ b/sendgrid/helpers/mail/content.py
@@ -29,7 +29,7 @@ def __init__(self, mime_type, content):
@property
def mime_type(self):
"""The MIME type of the content you are including in your email.
- For example, "text/plain" or "text/html".
+ For example, "text/plain" or "text/html" or "text/x-amp-html".
:rtype: string
"""
@@ -38,11 +38,11 @@ def mime_type(self):
@mime_type.setter
def mime_type(self, value):
"""The MIME type of the content you are including in your email.
- For example, "text/plain" or "text/html".
+ For example, "text/plain" or "text/html" or "text/x-amp-html".
:param value: The MIME type of the content you are including in your
email.
- For example, "text/plain" or "text/html".
+ For example, "text/plain" or "text/html" or "text/x-amp-html".
:type value: string
"""
self._mime_type = value
diff --git a/sendgrid/helpers/mail/mail.py b/sendgrid/helpers/mail/mail.py
index db2399310..0069a3f7d 100644
--- a/sendgrid/helpers/mail/mail.py
+++ b/sendgrid/helpers/mail/mail.py
@@ -27,6 +27,7 @@ def __init__(
subject=None,
plain_text_content=None,
html_content=None,
+ amp_html_content=None,
global_substitutions=None,
is_multiple=False):
"""
@@ -43,6 +44,8 @@ def __init__(
:type plain_text_content: string, optional
:param html_content: The html body of the email
:type html_content: string, optional
+ :param amp_html_content: The amp-html body of the email
+ :type amp_html_content: string, optional
"""
self._attachments = None
self._categories = None
@@ -71,6 +74,8 @@ def __init__(
self.subject = subject
if plain_text_content is not None:
self.add_content(plain_text_content, MimeType.text)
+ if amp_html_content is not None:
+ self.add_content(amp_html_content, MimeType.amp)
if html_content is not None:
self.add_content(html_content, MimeType.html)
@@ -725,9 +730,23 @@ def add_content(self, content, mime_type=None):
"""
if isinstance(content, str):
content = Content(mime_type, content)
- # Content of mime type text/plain must always come first
- if content.mime_type == "text/plain":
+ # Content of mime type text/plain must always come first, followed by text/x-amp-html and then text/html
+ if content.mime_type == MimeType.text:
self._contents = self._ensure_insert(content, self._contents)
+ elif content.mime_type == MimeType.amp:
+ if self._contents:
+ for _content in self._contents:
+ # this is written in the context that plain text content will always come earlier than the html content
+ if _content.mime_type == MimeType.text:
+ index = 1
+ break
+ elif _content.mime_type == MimeType.html:
+ index = 0
+ break
+ else:
+ index = 0
+ self._contents = self._ensure_append(
+ content, self._contents, index=index)
else:
if self._contents:
index = len(self._contents)
diff --git a/sendgrid/helpers/mail/mime_type.py b/sendgrid/helpers/mail/mime_type.py
index 0d0c9b3b3..a2f88c5af 100644
--- a/sendgrid/helpers/mail/mime_type.py
+++ b/sendgrid/helpers/mail/mime_type.py
@@ -3,3 +3,4 @@ class MimeType(object):
"""
text = "text/plain"
html = "text/html"
+ amp = "text/x-amp-html"
diff --git a/test/test_mail_helpers.py b/test/test_mail_helpers.py
index 202d3948b..d0d09c9d3 100644
--- a/test/test_mail_helpers.py
+++ b/test/test_mail_helpers.py
@@ -17,6 +17,40 @@
Subject, Substitution, To, Cc, Bcc, TrackingSettings
)
+# The below amp html email content is taken from [Google AMP Hello World Email](https://amp.dev/documentation/examples/introduction/hello_world_email/)
+amp_html_content = '''
'''
+
+response_content_with_all_three_mime_contents = json.dumps({
+ "content": [
+ {
+ "type": "text/plain",
+ "value": "and easy to do anywhere, even with Python"
+ },
+ {
+ "type": "text/x-amp-html",
+ "value": amp_html_content
+ },
+ {
+ "type": "text/html",
+ "value": "and easy to do anywhere, even with Python"
+ }
+ ],
+ "from": {
+ "email": "test+from@example.com",
+ "name": "Example From Name"
+ },
+ "personalizations": [
+ {
+ "to": [
+ {
+ "email": "test+to@example.com",
+ "name": "Example To Name"
+ }
+ ]
+ }
+ ],
+ "subject": "Sending with SendGrid is Fun"
+})
class UnitTests(unittest.TestCase):
@@ -284,6 +318,239 @@ def test_multiple_emails_to_multiple_recipients(self):
}''')
)
+ def test_single_email_with_all_three_email_contents_to_single_recipient(self):
+ from sendgrid.helpers.mail import (Mail, From, To, Subject,
+ PlainTextContent, HtmlContent, AmpHtmlContent)
+ self.maxDiff = None
+ message = Mail(
+ from_email=From('test+from@example.com', 'Example From Name'),
+ to_emails=To('test+to@example.com', 'Example To Name'),
+ subject=Subject('Sending with SendGrid is Fun'),
+ plain_text_content=PlainTextContent(
+ 'and easy to do anywhere, even with Python'),
+ amp_html_content=AmpHtmlContent(amp_html_content),
+ html_content=HtmlContent(
+ 'and easy to do anywhere, even with Python')
+ )
+
+ self.assertEqual(
+ message.get(),
+ json.loads(response_content_with_all_three_mime_contents)
+ )
+
+ def test_single_email_with_amp_and_html_contents_to_single_recipient(self):
+ from sendgrid.helpers.mail import (Mail, From, To, Subject,
+ PlainTextContent, HtmlContent, AmpHtmlContent)
+ self.maxDiff = None
+ message = Mail(
+ from_email=From('test+from@example.com', 'Example From Name'),
+ to_emails=To('test+to@example.com', 'Example To Name'),
+ subject=Subject('Sending with SendGrid is Fun'),
+ amp_html_content=AmpHtmlContent(amp_html_content),
+ html_content=HtmlContent(
+ 'and easy to do anywhere, even with Python')
+ )
+
+ response_content = json.dumps({
+ "content": [
+ {
+ "type": "text/x-amp-html",
+ "value": amp_html_content
+ },
+ {
+ "type": "text/html",
+ "value": "and easy to do anywhere, even with Python"
+ }
+ ],
+ "from": {
+ "email": "test+from@example.com",
+ "name": "Example From Name"
+ },
+ "personalizations": [
+ {
+ "to": [
+ {
+ "email": "test+to@example.com",
+ "name": "Example To Name"
+ }
+ ]
+ }
+ ],
+ "subject": "Sending with SendGrid is Fun"
+ })
+ self.assertEqual(
+ message.get(),
+ json.loads(response_content)
+ )
+
+ def test_single_email_with_amp_and_plain_contents_to_single_recipient(self):
+ from sendgrid.helpers.mail import (Mail, From, To, Subject,
+ PlainTextContent, HtmlContent, AmpHtmlContent)
+ self.maxDiff = None
+ message = Mail(
+ from_email=From('test+from@example.com', 'Example From Name'),
+ to_emails=To('test+to@example.com', 'Example To Name'),
+ subject=Subject('Sending with SendGrid is Fun'),
+ plain_text_content=PlainTextContent(
+ 'and easy to do anywhere, even with Python'),
+ amp_html_content=AmpHtmlContent(amp_html_content)
+ )
+
+ response_content = json.dumps({
+ "content": [
+ {
+ "type": "text/plain",
+ "value": "and easy to do anywhere, even with Python"
+ },
+ {
+ "type": "text/x-amp-html",
+ "value": amp_html_content
+ }
+ ],
+ "from": {
+ "email": "test+from@example.com",
+ "name": "Example From Name"
+ },
+ "personalizations": [
+ {
+ "to": [
+ {
+ "email": "test+to@example.com",
+ "name": "Example To Name"
+ }
+ ]
+ }
+ ],
+ "subject": "Sending with SendGrid is Fun"
+ })
+ self.assertEqual(
+ message.get(),
+ json.loads(response_content)
+ )
+
+ ## Check ordering of MIME types in different variants - start
+ def test_single_email_with_all_three_contents_in_collapsed_order_of_plain_amp_html_content_single_recipient(self):
+ from sendgrid.helpers.mail import (Mail, From, To, Subject,
+ PlainTextContent, HtmlContent, AmpHtmlContent)
+ self.maxDiff = None
+ message = Mail(
+ from_email=From('test+from@example.com', 'Example From Name'),
+ to_emails=To('test+to@example.com', 'Example To Name'),
+ subject=Subject('Sending with SendGrid is Fun')
+ )
+ message.content = PlainTextContent(
+ 'and easy to do anywhere, even with Python')
+ message.content = AmpHtmlContent(amp_html_content)
+ message.content = HtmlContent(
+ 'and easy to do anywhere, even with Python')
+
+ self.assertEqual(
+ message.get(),
+ json.loads(response_content_with_all_three_mime_contents)
+ )
+
+ def test_single_email_with_all_three_contents_in_collapsed_order_of_plain_html_amp_content_single_recipient(self):
+ from sendgrid.helpers.mail import (Mail, From, To, Subject,
+ PlainTextContent, HtmlContent, AmpHtmlContent)
+ self.maxDiff = None
+ message = Mail(
+ from_email=From('test+from@example.com', 'Example From Name'),
+ to_emails=To('test+to@example.com', 'Example To Name'),
+ subject=Subject('Sending with SendGrid is Fun')
+ )
+ message.content = PlainTextContent(
+ 'and easy to do anywhere, even with Python')
+ message.content = HtmlContent(
+ 'and easy to do anywhere, even with Python')
+ message.content = AmpHtmlContent(amp_html_content)
+
+ self.assertEqual(
+ message.get(),
+ json.loads(response_content_with_all_three_mime_contents)
+ )
+
+ def test_single_email_with_all_three_contents_in_collapsed_order_of_html_plain_amp_content_single_recipient(self):
+ from sendgrid.helpers.mail import (Mail, From, To, Subject,
+ PlainTextContent, HtmlContent, AmpHtmlContent)
+ self.maxDiff = None
+ message = Mail(
+ from_email=From('test+from@example.com', 'Example From Name'),
+ to_emails=To('test+to@example.com', 'Example To Name'),
+ subject=Subject('Sending with SendGrid is Fun')
+ )
+ message.content = HtmlContent(
+ 'and easy to do anywhere, even with Python')
+ message.content = PlainTextContent(
+ 'and easy to do anywhere, even with Python')
+ message.content = AmpHtmlContent(amp_html_content)
+
+ self.assertEqual(
+ message.get(),
+ json.loads(response_content_with_all_three_mime_contents)
+ )
+
+ def test_single_email_with_all_three_contents_in_collapsed_order_of_html_amp_plain_content_single_recipient(self):
+ from sendgrid.helpers.mail import (Mail, From, To, Subject,
+ PlainTextContent, HtmlContent, AmpHtmlContent)
+ self.maxDiff = None
+ message = Mail(
+ from_email=From('test+from@example.com', 'Example From Name'),
+ to_emails=To('test+to@example.com', 'Example To Name'),
+ subject=Subject('Sending with SendGrid is Fun')
+ )
+ message.content = HtmlContent(
+ 'and easy to do anywhere, even with Python')
+ message.content = AmpHtmlContent(amp_html_content)
+ message.content = PlainTextContent(
+ 'and easy to do anywhere, even with Python')
+
+ self.assertEqual(
+ message.get(),
+ json.loads(response_content_with_all_three_mime_contents)
+ )
+
+ def test_single_email_with_all_three_contents_in_collapsed_order_of_amp_html_plain_content_single_recipient(self):
+ from sendgrid.helpers.mail import (Mail, From, To, Subject,
+ PlainTextContent, HtmlContent, AmpHtmlContent)
+ self.maxDiff = None
+ message = Mail(
+ from_email=From('test+from@example.com', 'Example From Name'),
+ to_emails=To('test+to@example.com', 'Example To Name'),
+ subject=Subject('Sending with SendGrid is Fun')
+ )
+ message.content = AmpHtmlContent(amp_html_content)
+ message.content = HtmlContent(
+ 'and easy to do anywhere, even with Python')
+ message.content = PlainTextContent(
+ 'and easy to do anywhere, even with Python')
+
+ self.assertEqual(
+ message.get(),
+ json.loads(response_content_with_all_three_mime_contents)
+ )
+
+ def test_single_email_with_all_three_contents_in_collapsed_order_of_amp_plain_html_content_single_recipient(self):
+ from sendgrid.helpers.mail import (Mail, From, To, Subject,
+ PlainTextContent, HtmlContent, AmpHtmlContent)
+ self.maxDiff = None
+ message = Mail(
+ from_email=From('test+from@example.com', 'Example From Name'),
+ to_emails=To('test+to@example.com', 'Example To Name'),
+ subject=Subject('Sending with SendGrid is Fun')
+ )
+ message.content = AmpHtmlContent(amp_html_content)
+ message.content = PlainTextContent(
+ 'and easy to do anywhere, even with Python')
+ message.content = HtmlContent(
+ 'and easy to do anywhere, even with Python')
+
+ self.assertEqual(
+ message.get(),
+ json.loads(response_content_with_all_three_mime_contents)
+ )
+
+ ## end
+
def test_value_error_is_raised_on_to_emails_set_to_list_of_lists(self):
from sendgrid.helpers.mail import (PlainTextContent, HtmlContent)
self.maxDiff = None
diff --git a/use_cases/sending_amp_html_content.md b/use_cases/sending_amp_html_content.md
new file mode 100644
index 000000000..616b52039
--- /dev/null
+++ b/use_cases/sending_amp_html_content.md
@@ -0,0 +1,102 @@
+# Sending AMP-HTML Email
+
+Following is an example on how to send an AMP HTML Email.
+Currently, we require AMP HTML and any one of HTML or Plain Text content (preferrably both) for improved deliverability or fallback for AMP HTML Email for supporting older clients and showing alternate content after 30 days.
+
+For more information on AMP emails pls check the [official AMP email page](https://amp.dev/about/email/)
+
+```python
+import os
+from sendgrid import SendGridAPIClient
+from sendgrid.helpers.mail import Mail
+
+# The below amp html email is taken from [Google AMP Hello World Email](https://amp.dev/documentation/examples/introduction/hello_world_email/)
+amp_html_content = '''
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Hello!
+
+
+
+
+
+
+
+
+
+
+
+'''
+
+message = Mail(
+ from_email='example@example.com',
+ to_emails='example@example.com',
+ subject='Sending with Twilio SendGrid is Fun',
+ html_content='and easy to do anywhere, even with Python',
+ amp_html_content=amp_html_content)
+try:
+ sg = SendGridAPIClient(api_key=os.environ.get('SENDGRID_API_KEY'))
+ response = sg.send(message)
+ print(response.status_code)
+ print(response.body)
+ print(response.headers)
+except Exception as e:
+ print(e.message)
+```
\ No newline at end of file