Ver Fonte

Merge pull request #75 from Waghabond/master

Alter Email Message Default Policy to Comply With RFC 5322
Mikael Koli há 3 anos atrás
pai
commit
8511afc416

+ 1 - 0
docs/versions.rst

@@ -6,6 +6,7 @@ Version history
 
 - ``0.6.0``
 
+    - Fix: Line breaks according to RFC 5322 (credit Waghabond)
     - Add: Support for Pandas styler (thanks ejbills!)
 
 - ``0.5.0``

+ 5 - 1
redmail/email/sender.py

@@ -1,5 +1,6 @@
 
 from copy import copy
+import email.policy
 from email.message import EmailMessage
 from email.utils import make_msgid, formatdate
 from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Union
@@ -429,7 +430,10 @@ class EmailSender:
         return make_msgid(domain=self.domain)
 
     def _create_body(self, subject, sender, receivers=None, cc=None, bcc=None, headers=None) -> EmailMessage:
-        msg = EmailMessage()
+        # Python's default email policy follows the Internet mail standards (RFC 5322) EXCEPT for line endings.
+        # For line endings the default policy  uses python's default LF instead of CRLF as mandated by RFC 5322.
+        # So we can manually edit this to to comply with the internet standards.
+        msg = EmailMessage(email.policy.default.clone(linesep="\r\n"))
 
         email_headers = {
             "From": sender,

+ 5 - 5
redmail/test/email/test_body.py

@@ -39,7 +39,7 @@ def test_text_message():
     MIME-Version: 1.0
 
     Hi, nice to meet you.
-    """)[1:]
+    """)[1:].replace('\n', '\r\n')
 
 
 def test_html_message():
@@ -80,7 +80,7 @@ def test_html_message():
     --===============<ID>==--
 
     --===============<ID>==--
-    """)[1:]
+    """)[1:].replace('\n', '\r\n')
 
 
 def test_text_and_html_message():
@@ -129,7 +129,7 @@ def test_text_and_html_message():
     --===============<ID>==--
 
     --===============<ID>==--
-    """)[1:]
+    """)[1:].replace('\n', '\r\n')
 
 
 @pytest.mark.parametrize(
@@ -246,9 +246,9 @@ def test_without_jinja(use_jinja_obj, use_jinja):
     --===============<ID>==--
 
     --===============<ID>==--
-    """)[1:]
+    """)[1:].replace('\n', '\r\n')
     if IS_PY37:
-        expected = expected.replace('sender.full_n=\n', 'sender.full_n')
+        expected = expected.replace('sender.full_n=\r\n', 'sender.full_n')
     msg = prune_generated_headers(str(msg))
     assert remove_email_content_id(msg) == expected
 

+ 1 - 1
redmail/test/email/test_cookbook.py

@@ -56,4 +56,4 @@ def test_distributions():
     Message-ID: <<message_id>>
     Date: <date>
     
-    """)[1:]
+    """)[1:].replace('\n', '\r\n')

+ 11 - 11
redmail/test/email/test_headers.py

@@ -21,10 +21,10 @@ def test_date():
     before = datetime.datetime.now(datetime.timezone.utc)
     msg = email.get_message(sender="me@example.com", subject="Some email")
     after = datetime.datetime.now(datetime.timezone.utc)
-    date_strings = re.findall(r'(?<=Date: ).+', str(msg))
+    date_strings = re.findall(r'(?<=Date: )[^\r\n]+', str(msg))
     assert len(date_strings) == 1
     for dt_string in date_strings:
-    
+
         # Validate the Date fits to the format
         datetime.datetime.strptime(dt_string, format)
 
@@ -45,7 +45,7 @@ def test_message_id():
     msg = email.get_message(sender="me@example.com", subject="Some email")
     msg2 = email.get_message(sender="me@example.com", subject="Some email")
 
-    message_ids = re.findall(r'(?<=Message-ID: ).+', str(msg))
+    message_ids = re.findall(r'(?<=Message-ID: )[^\r\n]+', str(msg))
     assert len(message_ids) == 1
     message_id = message_ids[0]
 
@@ -53,7 +53,7 @@ def test_message_id():
     assert bool(re.search(fr'<[0-9.]+@{domain}>', message_id))
 
     # Check another email has not the same Message-ID
-    message_id_2 = re.findall(r'(?<=Message-ID: ).+', str(msg2))[0]
+    message_id_2 = re.findall(r'(?<=Message-ID: )[^\r\n]+', str(msg2))[0]
     assert message_id != message_id_2
 
 def test_cc_bcc():
@@ -73,7 +73,7 @@ def test_cc_bcc():
     Message-ID: <<message_id>>
     Date: <date>
 
-    """)[1:]
+    """)[1:].replace('\n', '\r\n')
 
 @pytest.mark.parametrize("how", ["instance", "email"])
 def test_custom_headers(how):
@@ -89,14 +89,14 @@ def test_custom_headers(how):
 
     if how == "email":
         msg = email.get_message(
-            sender="me@example.com", 
-            subject="Some email", 
+            sender="me@example.com",
+            subject="Some email",
             headers=headers
         )
     elif how == "instance":
         email.headers = headers
         msg = email.get_message(
-            sender="me@example.com", 
+            sender="me@example.com",
             subject="Some email",
         )
     msg = prune_generated_headers(str(msg))
@@ -107,7 +107,7 @@ def test_custom_headers(how):
     Date: <date>
     Importance: high
 
-    """)[1:]
+    """)[1:].replace('\n', '\r\n')
 
 @pytest.mark.parametrize("how", ["instance", "email"])
 def test_custom_headers_override(how):
@@ -119,7 +119,7 @@ def test_custom_headers_override(how):
 
     if how == "email":
         msg = email.get_message(
-            sender="me@example.com", 
+            sender="me@example.com",
             subject="Some email",
             headers=headers
         )
@@ -135,4 +135,4 @@ def test_custom_headers_override(how):
     Message-ID: <167294165062.31860.1664530310632362057@LAPTOP-1234GML0>
     Date: Sun, 31 Jan 2021 06:56:46 +0000
 
-    """)[1:]
+    """)[1:].replace('\n', '\r\n')

+ 1 - 1
redmail/test/email/test_template.py

@@ -103,7 +103,7 @@ def test_jinja_env(tmpdir):
     --===============<ID>==--
 
     --===============<ID>==--
-    """)[1:]
+    """)[1:].replace('\n', '\r\n')
 
 def test_body_and_template_error(tmpdir):