Prechádzať zdrojové kódy

Merge pull request #24 from Miksus/23-fix-contenttype-attachment

23 fix content type issue with attachment and content type text/plain
Mikael Koli 4 rokov pred
rodič
commit
0a69f48e39

+ 6 - 0
redmail/email/attachment.py

@@ -18,6 +18,12 @@ class Attachments:
         self.encoding = encoding
 
     def attach(self, msg:EmailMessage):
+        if msg.get_content_type() == "text/plain":
+            # We need to change the content type
+            # This occurs if no body is defined or only text is defined
+            # The content type is therefore changed to multipart/mixed
+            # See issue #23
+            msg.make_mixed()
         for part in self._get_parts():
             msg.attach(part)
 

+ 112 - 5
redmail/test/email/test_attachments.py

@@ -13,6 +13,98 @@ def to_encoded(s:str):
     return str(base64.b64encode(s.encode()), 'ascii')
 
 
+def test_with_text():
+
+    sender = EmailSender(host=None, port=1234)
+    msg = sender.get_message(
+        sender="me@gmail.com",
+        receivers="you@gmail.com",
+        subject="Some news",
+        text="Hi, this is an email",
+        attachments={'data.txt': "Some content"}
+    )
+    assert msg.get_content_type() == "multipart/mixed"
+
+    text, attachment = msg.get_payload()
+    assert text.get_content_type() == 'text/plain'
+    assert attachment.get_content_type() == 'application/octet-stream'
+    assert text.get_payload() == "Hi, this is an email\n"
+
+    filename = attachment.get_filename()
+    data = attachment.get_payload()
+    assert filename == 'data.txt'
+    assert to_encoded("Some content") == data.replace('\n', '')
+
+def test_with_html():
+
+    sender = EmailSender(host=None, port=1234)
+    msg = sender.get_message(
+        sender="me@gmail.com",
+        receivers="you@gmail.com",
+        subject="Some news",
+        html="<h1>Hi, this is an email.</h1>",
+        attachments={'data.txt': "Some content"}
+    )
+    assert msg.get_content_type() == "multipart/alternative"
+
+    html, attachment = msg.get_payload()
+    assert html.get_content_type() == 'text/html'
+    assert attachment.get_content_type() == 'application/octet-stream'
+
+    assert html.get_payload() == "<h1>Hi, this is an email.</h1>\n"
+
+    filename = attachment.get_filename()
+    data = attachment.get_payload()
+    assert attachment.get_content_type() == 'application/octet-stream'
+    assert filename == 'data.txt'
+    assert to_encoded("Some content") == data.replace('\n', '')
+
+def test_with_text_and_html():
+
+    sender = EmailSender(host=None, port=1234)
+    msg = sender.get_message(
+        sender="me@gmail.com",
+        receivers="you@gmail.com",
+        subject="Some news",
+        text="Hi, this is an email.",
+        html="<h1>Hi, this is an email.</h1>",
+        attachments={'data.txt': "Some content"}
+    )
+    assert msg.get_content_type() == "multipart/alternative"
+
+    text, html, attachment = msg.get_payload()
+    assert text.get_content_type() == "text/plain"
+    assert html.get_content_type() == "text/html"
+    assert attachment.get_content_type() == 'application/octet-stream'
+
+    assert text.get_payload() == 'Hi, this is an email.\n'
+    assert html.get_payload() == '<h1>Hi, this is an email.</h1>\n'
+
+    filename = attachment.get_filename()
+    data = attachment.get_payload()
+    assert filename == 'data.txt'
+    assert to_encoded("Some content") == data.replace('\n', '')
+
+def test_no_body():
+
+    sender = EmailSender(host=None, port=1234)
+    msg = sender.get_message(
+        sender="me@gmail.com",
+        receivers="you@gmail.com",
+        subject="Some news",
+        attachments={'data.txt': 'Some content'}
+    )
+    assert msg.get_content_type() == "multipart/mixed"
+    assert len(msg.get_payload()) == 1
+
+    attachment = msg.get_payload(0)
+    assert attachment.get_content_type() == 'application/octet-stream'
+
+    filename = attachment.get_filename()
+    data = attachment.get_payload()
+    assert filename == 'data.txt'
+    assert to_encoded("Some content") == data.replace('\n', '')
+
 def test_dict_string():
 
     sender = EmailSender(host=None, port=1234)
@@ -22,9 +114,10 @@ def test_dict_string():
         subject="Some news",
         attachments={'data.txt': 'Some content'}
     )
-    payload = msg.get_payload(0)
-    filename = payload.get_filename()
-    data = payload.get_payload()
+    assert msg.get_content_type() == "multipart/mixed"
+    attachment = msg.get_payload(0)
+    filename = attachment.get_filename()
+    data = attachment.get_payload()
     assert filename == 'data.txt'
     assert to_encoded("Some content") == data.replace('\n', '')
 
@@ -37,6 +130,7 @@ def test_dict_bytes():
         subject="Some news",
         attachments={'data.bin': bytes(10)}
     )
+    assert msg.get_content_type() == "multipart/mixed"
     payload = msg.get_payload(0)
     filename = payload.get_filename()
     data = payload.get_payload()
@@ -54,6 +148,7 @@ def test_dict_path(tmpdir):
         subject="Some news",
         attachments={'myfile.txt': Path(str(file))}
     )
+    assert msg.get_content_type() == "multipart/mixed"
     payload = msg.get_payload(0)
     filename = payload.get_filename()
     data = payload.get_payload()
@@ -73,6 +168,7 @@ def test_dict_dataframe_txt():
     )
     expected = str(pd.DataFrame({'a': [1,2,3], 'b': ['1', '2', '3']}))
 
+    assert msg.get_content_type() == "multipart/mixed"
     payload = msg.get_payload(0)
     filename = payload.get_filename()
     data = payload.get_payload()
@@ -93,6 +189,7 @@ def test_dict_dataframe_csv():
         attachments={'myfile.csv': df}
     )
 
+    assert msg.get_content_type() == "multipart/mixed"
     payload = msg.get_payload(0)
     filename = payload.get_filename()
     data = payload.get_payload()
@@ -112,6 +209,7 @@ def test_dict_dataframe_html():
     )
     expected = '<table border="1" class="dataframe">\n  <thead>\n    <tr style="text-align: right;">\n      <th></th>\n      <th>a</th>\n      <th>b</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>1</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>2</td>\n      <td>2</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>3</td>\n      <td>3</td>\n    </tr>\n  </tbody>\n</table>'
 
+    assert msg.get_content_type() == "multipart/mixed"
     payload = msg.get_payload(0)
     filename = payload.get_filename()
     data = payload.get_payload().replace('\n', '')
@@ -144,6 +242,7 @@ def test_dict_dataframe_excel_no_error():
         subject="Some news",
         attachments={'myfile.xlsx': pd.DataFrame({'a': [1,2,3], 'b': ['1', '2', '3']})}
     )
+    assert msg.get_content_type() == "multipart/mixed"
     payload = msg.get_payload(0)
     filename = payload.get_filename()
     data = payload.get_payload()
@@ -160,6 +259,7 @@ def test_dict_pil_no_error():
         subject="Some news",
         attachments={'myimg.png': pil}
     )
+    assert msg.get_content_type() == "multipart/mixed"
     payload = msg.get_payload(0)
     filename = payload.get_filename()
     data = payload.get_payload()
@@ -176,6 +276,7 @@ def test_dict_matplotlib_no_error():
         subject="Some news",
         attachments={'myimg.png': fig}
     )
+    assert msg.get_content_type() == "multipart/mixed"
     payload = msg.get_payload(0)
     filename = payload.get_filename()
     data = payload.get_payload()
@@ -219,8 +320,9 @@ def test_dict_multiple(tmpdir):
         subject="Some news",
         attachments={'data_1.txt': Path(file1), 'data_2.txt': Path(file2)}
     )
+    assert msg.get_content_type() == "multipart/mixed"
     expected = [('data_1.txt', 'Some content 1'), ('data_2.txt', 'Some content 2')]
-    for payload, expected in zip(msg.get_payload(), expected):
+    for payload, expected in zip(msg.iter_attachments(), expected):
         filename = payload.get_filename()
         data = payload.get_payload()
         assert filename == expected[0]
@@ -242,6 +344,7 @@ def test_list_path(tmpdir):
         subject="Some news",
         attachments=[Path(str(file))]
     )
+    assert msg.get_content_type() == "multipart/mixed"
     payload = msg.get_payload(0)
     filename = payload.get_filename()
     data = payload.get_payload()
@@ -259,6 +362,7 @@ def test_list_string_path(tmpdir):
         subject="Some news",
         attachments=[str(file)]
     )
+    assert msg.get_content_type() == "multipart/mixed"
     payload = msg.get_payload(0)
     filename = payload.get_filename()
     data = payload.get_payload()
@@ -290,8 +394,9 @@ def test_list_multiple(tmpdir):
         subject="Some news",
         attachments=[Path(str(file1)), Path(str(file2))]
     )
+    assert msg.get_content_type() == "multipart/mixed"
     expected = [('data_1.txt', 'Some content 1'), ('data_2.txt', 'Some content 2')]
-    for payload, expected in zip(msg.get_payload(), expected):
+    for payload, expected in zip(msg.iter_attachments(), expected):
         filename = payload.get_filename()
         data = payload.get_payload()
         assert filename == expected[0]
@@ -319,6 +424,7 @@ def test_string_path(tmpdir):
         subject="Some news",
         attachments=str(file)
     )
+    assert msg.get_content_type() == "multipart/mixed"
     payload = msg.get_payload(0)
     filename = payload.get_filename()
     data = payload.get_payload()
@@ -346,6 +452,7 @@ def test_path(tmpdir):
         subject="Some news",
         attachments=Path(file)
     )
+    assert msg.get_content_type() == "multipart/mixed"
     payload = msg.get_payload(0)
     filename = payload.get_filename()
     data = payload.get_payload()