From aed430ae28b17d0b60e000e4f2345a564390ccbb Mon Sep 17 00:00:00 2001 From: Arun Tvs Date: Thu, 29 Oct 2020 10:36:32 +0530 Subject: [PATCH 01/10] Support for AMP HTML Email --- sendgrid/helpers/mail/amp_html_content.py | 59 ++++++++++++++ sendgrid/helpers/mail/content.py | 6 +- sendgrid/helpers/mail/mail.py | 14 +++- sendgrid/helpers/mail/mime_type.py | 1 + use_cases/sending_amp_html_content.py | 99 +++++++++++++++++++++++ 5 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 sendgrid/helpers/mail/amp_html_content.py create mode 100644 use_cases/sending_amp_html_content.py diff --git a/sendgrid/helpers/mail/amp_html_content.py b/sendgrid/helpers/mail/amp_html_content.py new file mode 100644 index 000000000..a9775fa5c --- /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/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..1100b26db 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,16 @@ 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 + # Content of mime type text/plain must always come first, followed by text/x-amp-html and then text/html if content.mime_type == "text/plain": self._contents = self._ensure_insert(content, self._contents) + elif content.mime_type == "text/x-amp-html": + if self._contents: + index = len(self._contents) + 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/use_cases/sending_amp_html_content.py b/use_cases/sending_amp_html_content.py new file mode 100644 index 000000000..88615dc19 --- /dev/null +++ b/use_cases/sending_amp_html_content.py @@ -0,0 +1,99 @@ +# Sending AMP-HTML Email + + +Currently, we require AMP HTML and any one of HTML or Plain Text content for improved deliverability or fallback for AMP HTML Email for supporting older clients and showing alternate content after 30 days. In some cases, only HTML may be available. The below example shows how to obtain the Plain Text equivalent of the HTML content. + +```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='arun@raneesarees.in', + to_emails='aruntvs227@gmail.com', + subject='Sending with Twilio SendGrid is Fun', + html_content='and easy to do anywhere, even with Python') +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 From 019ecb9f2b24a1ed9ceb78dc3450a62ec79baa41 Mon Sep 17 00:00:00 2001 From: modernwarfareuplink Date: Thu, 31 Dec 2020 08:53:04 +0530 Subject: [PATCH 02/10] squash merged main --- CHANGELOG.md | 6 ++++++ sendgrid/helpers/mail/file_content.py | 2 +- sendgrid/version.py | 2 +- use_cases/sending_html_content.md | 5 ++--- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c8128f10..275cdcbc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Change Log All notable changes to this project will be documented in this file. +[2020-12-02] Version 6.4.8 +-------------------------- +**Library - Docs** +- [PR #955](https://github.com/sendgrid/sendgrid-python/pull/955): fixed typo in sendgrid/helpers/mail/file_content.py. Thanks to [@razvandimescu](https://github.com/razvandimescu)! + + [2020-09-16] Version 6.4.7 -------------------------- **Library - Docs** diff --git a/sendgrid/helpers/mail/file_content.py b/sendgrid/helpers/mail/file_content.py index c5c0d6995..c1eb81fc6 100644 --- a/sendgrid/helpers/mail/file_content.py +++ b/sendgrid/helpers/mail/file_content.py @@ -31,7 +31,7 @@ def file_content(self, value): def get(self): """ - Get a JSON-ready representation of this FileContente. + Get a JSON-ready representation of this FileContent. :returns: This FileContent, ready for use in a request body. :rtype: string diff --git a/sendgrid/version.py b/sendgrid/version.py index 63521b92e..bec64b5d2 100644 --- a/sendgrid/version.py +++ b/sendgrid/version.py @@ -1 +1 @@ -__version__ = '6.4.7' +__version__ = '6.4.8' diff --git a/use_cases/sending_html_content.md b/use_cases/sending_html_content.md index ba38b19aa..4a828e737 100644 --- a/use_cases/sending_html_content.md +++ b/use_cases/sending_html_content.md @@ -35,14 +35,13 @@ html_text = """ sendgrid_client = SendGridAPIClient(api_key=os.environ.get('SENDGRID_API_KEY')) from_email = From("from_email@exmaple.com") -to_email = Email("to_email@example.com") +to_email = To("to_email@example.com") subject = Subject("Test Subject") html_content = HtmlContent(html_text) soup = BeautifulSoup(html_text) plain_text = soup.get_text() plain_text_content = Content("text/plain", plain_text) -mail.add_content(plain_content) message = Mail(from_email, to_email, subject, plain_text_content, html_content) @@ -54,4 +53,4 @@ try: except urllib.HTTPError as e: print(e.read()) exit() -``` \ No newline at end of file +``` From 73de79724e221c163a6f98cef04e7af5ebacb167 Mon Sep 17 00:00:00 2001 From: modernwarfareuplink Date: Thu, 31 Dec 2020 09:10:47 +0530 Subject: [PATCH 03/10] Updated use_cases on sending amp email --- ...mp_html_content.py => sending_amp_html_content.md} | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) rename use_cases/{sending_amp_html_content.py => sending_amp_html_content.md} (92%) diff --git a/use_cases/sending_amp_html_content.py b/use_cases/sending_amp_html_content.md similarity index 92% rename from use_cases/sending_amp_html_content.py rename to use_cases/sending_amp_html_content.md index 88615dc19..99c5635ef 100644 --- a/use_cases/sending_amp_html_content.py +++ b/use_cases/sending_amp_html_content.md @@ -1,7 +1,9 @@ # 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 for improved deliverability or fallback for AMP HTML Email for supporting older clients and showing alternate content after 30 days. -Currently, we require AMP HTML and any one of HTML or Plain Text content for improved deliverability or fallback for AMP HTML Email for supporting older clients and showing alternate content after 30 days. In some cases, only HTML may be available. The below example shows how to obtain the Plain Text equivalent of the HTML content. +For more information on AMP emails pls check the [official AMP email page](https://amp.dev/about/email/) ```python import os @@ -84,10 +86,11 @@ ''' message = Mail( - from_email='arun@raneesarees.in', - to_emails='aruntvs227@gmail.com', + 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') + 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) From 4d5aaded4df4c0c581e1296f44fb357e3e96b25a Mon Sep 17 00:00:00 2001 From: modernwarfareuplink Date: Fri, 1 Jan 2021 18:32:27 +0530 Subject: [PATCH 04/10] Updated test cases for AMP Emails and made few fixes for proper functioning --- sendgrid/helpers/mail/__init__.py | 1 + sendgrid/helpers/mail/amp_html_content.py | 2 +- test/test_mail_helpers.py | 403 ++++++++++++++++++++++ use_cases/sending_amp_html_content.md | 2 +- 4 files changed, 406 insertions(+), 2 deletions(-) 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 index a9775fa5c..1a282053f 100644 --- a/sendgrid/helpers/mail/amp_html_content.py +++ b/sendgrid/helpers/mail/amp_html_content.py @@ -23,7 +23,7 @@ def mime_type(self): :rtype: string """ - return "text/html" + return "text/x-amp-html" @property def content(self): diff --git a/test/test_mail_helpers.py b/test/test_mail_helpers.py index 202d3948b..4861848d5 100644 --- a/test/test_mail_helpers.py +++ b/test/test_mail_helpers.py @@ -17,6 +17,8 @@ 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 = '''

Hello!

''' class UnitTests(unittest.TestCase): @@ -284,6 +286,404 @@ 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') + ) + + response_content = { + "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" + } + self.assertEqual( + message.get(), + json.loads(json.dumps(response_content)) + ) + + 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 = { + "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(json.dumps(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 = { + "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(json.dumps(response_content)) + ) + + ## Check ordering of MIME types in different variants - start + 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'), + plain_text_content=PlainTextContent( + 'and easy to do anywhere, even with Python'), + html_content=HtmlContent( + 'and easy to do anywhere, even with Python'), + amp_html_content=AmpHtmlContent(amp_html_content) + ) + + response_content = { + "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" + } + self.assertEqual( + message.get(), + json.loads(json.dumps(response_content)) + ) + + 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'), + html_content=HtmlContent( + 'and easy to do anywhere, even with Python'), + plain_text_content=PlainTextContent( + 'and easy to do anywhere, even with Python'), + amp_html_content=AmpHtmlContent(amp_html_content) + ) + + response_content = { + "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" + } + self.assertEqual( + message.get(), + json.loads(json.dumps(response_content)) + ) + + 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'), + html_content=HtmlContent( + 'and easy to do anywhere, even with Python'), + amp_html_content=AmpHtmlContent(amp_html_content), + plain_text_content=PlainTextContent( + 'and easy to do anywhere, even with Python') + ) + + response_content = { + "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" + } + self.assertEqual( + message.get(), + json.loads(json.dumps(response_content)) + ) + + 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'), + amp_html_content=AmpHtmlContent(amp_html_content), + html_content=HtmlContent( + 'and easy to do anywhere, even with Python'), + plain_text_content=PlainTextContent( + 'and easy to do anywhere, even with Python') + ) + + response_content = { + "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" + } + self.assertEqual( + message.get(), + json.loads(json.dumps(response_content)) + ) + + 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'), + 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') + ) + + response_content = { + "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" + } + self.assertEqual( + message.get(), + json.loads(json.dumps(response_content)) + ) + ## 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 @@ -1128,3 +1528,6 @@ def test_disable_tracking(self): tracking_settings.get(), {'click_tracking': {'enable': False, 'enable_text': False}} ) + + +unittest.main() \ No newline at end of file diff --git a/use_cases/sending_amp_html_content.md b/use_cases/sending_amp_html_content.md index 99c5635ef..616b52039 100644 --- a/use_cases/sending_amp_html_content.md +++ b/use_cases/sending_amp_html_content.md @@ -1,7 +1,7 @@ # 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 for improved deliverability or fallback for AMP HTML Email for supporting older clients and showing alternate content after 30 days. +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/) From 196652657d3f8ea2b8ea382d76d6c37260b78627 Mon Sep 17 00:00:00 2001 From: modernwarfareuplink Date: Fri, 1 Jan 2021 18:42:57 +0530 Subject: [PATCH 05/10] Removed calling unittest from test_mail_helpers.py --- test/test_mail_helpers.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/test_mail_helpers.py b/test/test_mail_helpers.py index 4861848d5..e3f3bc3ff 100644 --- a/test/test_mail_helpers.py +++ b/test/test_mail_helpers.py @@ -1528,6 +1528,3 @@ def test_disable_tracking(self): tracking_settings.get(), {'click_tracking': {'enable': False, 'enable_text': False}} ) - - -unittest.main() \ No newline at end of file From 3365a5f5cb8e422e558b5d95d996147570722655 Mon Sep 17 00:00:00 2001 From: modernwarfareuplink Date: Fri, 1 Jan 2021 18:50:23 +0530 Subject: [PATCH 06/10] Updated the year in LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 29aba592a..e5439a92d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (C) 2020, Twilio SendGrid, Inc. +Copyright (C) 2021, Twilio SendGrid, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in From dd644c3cf8ff67e1b29b6bbcd024dba69b6a85a1 Mon Sep 17 00:00:00 2001 From: modernwarfareuplink Date: Fri, 1 Jan 2021 19:05:23 +0530 Subject: [PATCH 07/10] Wrapping up duplicate constants to global --- test/test_mail_helpers.py | 234 +++++++------------------------------- 1 file changed, 40 insertions(+), 194 deletions(-) diff --git a/test/test_mail_helpers.py b/test/test_mail_helpers.py index e3f3bc3ff..963c79cc5 100644 --- a/test/test_mail_helpers.py +++ b/test/test_mail_helpers.py @@ -20,6 +20,38 @@ # 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 = '''

Hello!

''' +response_content_with_all_three_mime_contents = { + "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): def test_asm(self): @@ -300,41 +332,10 @@ def test_single_email_with_all_three_email_contents_to_single_recipient(self): html_content=HtmlContent( 'and easy to do anywhere, even with Python') ) - - response_content = { - "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" - } + self.assertEqual( message.get(), - json.loads(json.dumps(response_content)) + json.loads(json.dumps(response_content_with_all_three_mime_contents)) ) def test_single_email_with_amp_and_html_contents_to_single_recipient(self): @@ -443,40 +444,9 @@ def test_single_email_with_all_three_contents_in_collapsed_order_of_plain_html_a amp_html_content=AmpHtmlContent(amp_html_content) ) - response_content = { - "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" - } self.assertEqual( message.get(), - json.loads(json.dumps(response_content)) + json.loads(json.dumps(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): @@ -494,40 +464,9 @@ def test_single_email_with_all_three_contents_in_collapsed_order_of_html_plain_a amp_html_content=AmpHtmlContent(amp_html_content) ) - response_content = { - "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" - } self.assertEqual( message.get(), - json.loads(json.dumps(response_content)) + json.loads(json.dumps(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): @@ -545,40 +484,9 @@ def test_single_email_with_all_three_contents_in_collapsed_order_of_html_amp_pla 'and easy to do anywhere, even with Python') ) - response_content = { - "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" - } self.assertEqual( message.get(), - json.loads(json.dumps(response_content)) + json.loads(json.dumps(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): @@ -596,40 +504,9 @@ def test_single_email_with_all_three_contents_in_collapsed_order_of_amp_html_pla 'and easy to do anywhere, even with Python') ) - response_content = { - "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" - } self.assertEqual( message.get(), - json.loads(json.dumps(response_content)) + json.loads(json.dumps(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): @@ -646,41 +523,10 @@ def test_single_email_with_all_three_contents_in_collapsed_order_of_amp_plain_ht html_content=HtmlContent( 'and easy to do anywhere, even with Python') ) - - response_content = { - "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" - } + self.assertEqual( message.get(), - json.loads(json.dumps(response_content)) + json.loads(json.dumps(response_content_with_all_three_mime_contents)) ) ## end From 68c5188cc0f0ab5c793648efc60e69bd61a81d48 Mon Sep 17 00:00:00 2001 From: modernwarfareuplink Date: Fri, 1 Jan 2021 21:34:07 +0530 Subject: [PATCH 08/10] temp --- sendgrid/helpers/mail/mail.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sendgrid/helpers/mail/mail.py b/sendgrid/helpers/mail/mail.py index 1100b26db..b92eef343 100644 --- a/sendgrid/helpers/mail/mail.py +++ b/sendgrid/helpers/mail/mail.py @@ -735,7 +735,14 @@ def add_content(self, content, mime_type=None): self._contents = self._ensure_insert(content, self._contents) elif content.mime_type == "text/x-amp-html": if self._contents: - index = len(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 == "text/plain": + index = 1 + break + elif _content.mime_type == "text/html": + index = 0 + break else: index = 0 self._contents = self._ensure_append( From 11ea0e4d66ee81cbd45ef2ef0eab3180ebf6fa5b Mon Sep 17 00:00:00 2001 From: modernwarfareuplink Date: Fri, 1 Jan 2021 23:24:38 +0530 Subject: [PATCH 09/10] Rectify issues with tests and updated mail order logic --- sendgrid/helpers/mail/mail.py | 8 ++-- test/test_mail_helpers.py | 83 ++++++++++++++++++++++------------- 2 files changed, 56 insertions(+), 35 deletions(-) diff --git a/sendgrid/helpers/mail/mail.py b/sendgrid/helpers/mail/mail.py index b92eef343..0069a3f7d 100644 --- a/sendgrid/helpers/mail/mail.py +++ b/sendgrid/helpers/mail/mail.py @@ -731,16 +731,16 @@ 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, followed by text/x-amp-html and then text/html - if content.mime_type == "text/plain": + if content.mime_type == MimeType.text: self._contents = self._ensure_insert(content, self._contents) - elif content.mime_type == "text/x-amp-html": + 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 == "text/plain": + if _content.mime_type == MimeType.text: index = 1 break - elif _content.mime_type == "text/html": + elif _content.mime_type == MimeType.html: index = 0 break else: diff --git a/test/test_mail_helpers.py b/test/test_mail_helpers.py index 963c79cc5..26c36d225 100644 --- a/test/test_mail_helpers.py +++ b/test/test_mail_helpers.py @@ -429,6 +429,26 @@ def test_single_email_with_amp_and_plain_contents_to_single_recipient(self): ) ## 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(json.dumps(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) @@ -436,13 +456,13 @@ def test_single_email_with_all_three_contents_in_collapsed_order_of_plain_html_a 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'), - html_content=HtmlContent( - 'and easy to do anywhere, even with Python'), - amp_html_content=AmpHtmlContent(amp_html_content) + 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(), @@ -456,13 +476,13 @@ def test_single_email_with_all_three_contents_in_collapsed_order_of_html_plain_a 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'), - html_content=HtmlContent( - 'and easy to do anywhere, even with Python'), - plain_text_content=PlainTextContent( - 'and easy to do anywhere, even with Python'), - amp_html_content=AmpHtmlContent(amp_html_content) + 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(), @@ -476,13 +496,13 @@ def test_single_email_with_all_three_contents_in_collapsed_order_of_html_amp_pla 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'), - html_content=HtmlContent( - 'and easy to do anywhere, even with Python'), - amp_html_content=AmpHtmlContent(amp_html_content), - plain_text_content=PlainTextContent( - 'and easy to do anywhere, even with Python') + 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(), @@ -496,13 +516,13 @@ def test_single_email_with_all_three_contents_in_collapsed_order_of_amp_html_pla 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'), - plain_text_content=PlainTextContent( - 'and easy to do anywhere, even with Python') + 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(), @@ -516,18 +536,19 @@ def test_single_email_with_all_three_contents_in_collapsed_order_of_amp_plain_ht 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') + 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(json.dumps(response_content_with_all_three_mime_contents)) ) + ## end def test_value_error_is_raised_on_to_emails_set_to_list_of_lists(self): From a9a60564faaac5b1e2ee6dcd4f8ab445491f04a3 Mon Sep 17 00:00:00 2001 From: modernwarfareuplink Date: Sat, 9 Jan 2021 02:36:38 +0530 Subject: [PATCH 10/10] Resolved comments in test/test_mail_helpers.py --- test/test_mail_helpers.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/test/test_mail_helpers.py b/test/test_mail_helpers.py index 26c36d225..d0d09c9d3 100644 --- a/test/test_mail_helpers.py +++ b/test/test_mail_helpers.py @@ -20,7 +20,7 @@ # 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 = '''

Hello!

''' -response_content_with_all_three_mime_contents = { +response_content_with_all_three_mime_contents = json.dumps({ "content": [ { "type": "text/plain", @@ -50,7 +50,7 @@ } ], "subject": "Sending with SendGrid is Fun" -} +}) class UnitTests(unittest.TestCase): @@ -332,10 +332,10 @@ def test_single_email_with_all_three_email_contents_to_single_recipient(self): html_content=HtmlContent( 'and easy to do anywhere, even with Python') ) - + self.assertEqual( message.get(), - json.loads(json.dumps(response_content_with_all_three_mime_contents)) + json.loads(response_content_with_all_three_mime_contents) ) def test_single_email_with_amp_and_html_contents_to_single_recipient(self): @@ -351,7 +351,7 @@ def test_single_email_with_amp_and_html_contents_to_single_recipient(self): 'and easy to do anywhere, even with Python') ) - response_content = { + response_content = json.dumps({ "content": [ { "type": "text/x-amp-html", @@ -377,10 +377,10 @@ def test_single_email_with_amp_and_html_contents_to_single_recipient(self): } ], "subject": "Sending with SendGrid is Fun" - } + }) self.assertEqual( message.get(), - json.loads(json.dumps(response_content)) + json.loads(response_content) ) def test_single_email_with_amp_and_plain_contents_to_single_recipient(self): @@ -396,7 +396,7 @@ def test_single_email_with_amp_and_plain_contents_to_single_recipient(self): amp_html_content=AmpHtmlContent(amp_html_content) ) - response_content = { + response_content = json.dumps({ "content": [ { "type": "text/plain", @@ -422,10 +422,10 @@ def test_single_email_with_amp_and_plain_contents_to_single_recipient(self): } ], "subject": "Sending with SendGrid is Fun" - } + }) self.assertEqual( message.get(), - json.loads(json.dumps(response_content)) + json.loads(response_content) ) ## Check ordering of MIME types in different variants - start @@ -446,7 +446,7 @@ def test_single_email_with_all_three_contents_in_collapsed_order_of_plain_amp_ht self.assertEqual( message.get(), - json.loads(json.dumps(response_content_with_all_three_mime_contents)) + 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): @@ -466,7 +466,7 @@ def test_single_email_with_all_three_contents_in_collapsed_order_of_plain_html_a self.assertEqual( message.get(), - json.loads(json.dumps(response_content_with_all_three_mime_contents)) + 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): @@ -486,7 +486,7 @@ def test_single_email_with_all_three_contents_in_collapsed_order_of_html_plain_a self.assertEqual( message.get(), - json.loads(json.dumps(response_content_with_all_three_mime_contents)) + 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): @@ -506,7 +506,7 @@ def test_single_email_with_all_three_contents_in_collapsed_order_of_html_amp_pla self.assertEqual( message.get(), - json.loads(json.dumps(response_content_with_all_three_mime_contents)) + 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): @@ -526,7 +526,7 @@ def test_single_email_with_all_three_contents_in_collapsed_order_of_amp_html_pla self.assertEqual( message.get(), - json.loads(json.dumps(response_content_with_all_three_mime_contents)) + 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): @@ -546,7 +546,7 @@ def test_single_email_with_all_three_contents_in_collapsed_order_of_amp_plain_ht self.assertEqual( message.get(), - json.loads(json.dumps(response_content_with_all_three_mime_contents)) + json.loads(response_content_with_all_three_mime_contents) ) ## end