| OLD | NEW |
| 1 # Copyright (C) 2001-2010 Python Software Foundation | 1 # Copyright (C) 2001-2010 Python Software Foundation |
| 2 # Contact: email-sig@python.org | 2 # Contact: email-sig@python.org |
| 3 # email package unit tests | 3 # email package unit tests |
| 4 | 4 |
| 5 import os | 5 import os |
| 6 import re | 6 import re |
| 7 import sys | 7 import sys |
| 8 import time | 8 import time |
| 9 import base64 | 9 import base64 |
| 10 import difflib | 10 import difflib |
| 11 import unittest | 11 import unittest |
| 12 import warnings | 12 import warnings |
| 13 import textwrap | 13 import textwrap |
| 14 | 14 |
| 15 from io import StringIO, BytesIO | 15 from io import StringIO, BytesIO |
| 16 from itertools import chain | 16 from itertools import chain |
| 17 | 17 |
| 18 import email | 18 import email |
| 19 import email.policy |
| 19 | 20 |
| 20 from email.charset import Charset | 21 from email.charset import Charset |
| 21 from email.header import Header, decode_header, make_header | 22 from email.header import Header, decode_header, make_header |
| 22 from email.parser import Parser, HeaderParser | 23 from email.parser import Parser, HeaderParser |
| 23 from email.generator import Generator, DecodedGenerator | 24 from email.generator import Generator, DecodedGenerator |
| 24 from email.message import Message | 25 from email.message import Message |
| 25 from email.mime.application import MIMEApplication | 26 from email.mime.application import MIMEApplication |
| 26 from email.mime.audio import MIMEAudio | 27 from email.mime.audio import MIMEAudio |
| 27 from email.mime.text import MIMEText | 28 from email.mime.text import MIMEText |
| 28 from email.mime.image import MIMEImage | 29 from email.mime.image import MIMEImage |
| (...skipping 1769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1798 MIME-Version: 1.0 | 1799 MIME-Version: 1.0 |
| 1799 Content-Transfer-Encoding: base64 | 1800 Content-Transfer-Encoding: base64 |
| 1800 | 1801 |
| 1801 YXNkZg== | 1802 YXNkZg== |
| 1802 --===============0012394164==--""") | 1803 --===============0012394164==--""") |
| 1803 self.assertEqual(m.get_payload(0).get_payload(), 'YXNkZg==') | 1804 self.assertEqual(m.get_payload(0).get_payload(), 'YXNkZg==') |
| 1804 | 1805 |
| 1805 | 1806 |
| 1806 | 1807 |
| 1807 # Test some badly formatted messages | 1808 # Test some badly formatted messages |
| 1808 class TestNonConformantBase: | 1809 class TestNonConformant(TestEmailBase): |
| 1809 | |
| 1810 def _msgobj(self, filename): | |
| 1811 with openfile(filename) as fp: | |
| 1812 return email.message_from_file(fp, policy=self.policy) | |
| 1813 | 1810 |
| 1814 def test_parse_missing_minor_type(self): | 1811 def test_parse_missing_minor_type(self): |
| 1815 eq = self.assertEqual | 1812 eq = self.assertEqual |
| 1816 msg = self._msgobj('msg_14.txt') | 1813 msg = self._msgobj('msg_14.txt') |
| 1817 eq(msg.get_content_type(), 'text/plain') | 1814 eq(msg.get_content_type(), 'text/plain') |
| 1818 eq(msg.get_content_maintype(), 'text') | 1815 eq(msg.get_content_maintype(), 'text') |
| 1819 eq(msg.get_content_subtype(), 'plain') | 1816 eq(msg.get_content_subtype(), 'plain') |
| 1820 | 1817 |
| 1818 # test_parser.TestMessageDefectDetectionBase |
| 1821 def test_same_boundary_inner_outer(self): | 1819 def test_same_boundary_inner_outer(self): |
| 1822 unless = self.assertTrue | 1820 unless = self.assertTrue |
| 1823 msg = self._msgobj('msg_15.txt') | 1821 msg = self._msgobj('msg_15.txt') |
| 1824 # XXX We can probably eventually do better | 1822 # XXX We can probably eventually do better |
| 1825 inner = msg.get_payload(0) | 1823 inner = msg.get_payload(0) |
| 1826 unless(hasattr(inner, 'defects')) | 1824 unless(hasattr(inner, 'defects')) |
| 1827 self.assertEqual(len(self.get_defects(inner)), 1) | 1825 self.assertEqual(len(inner.defects), 1) |
| 1828 unless(isinstance(self.get_defects(inner)[0], | 1826 unless(isinstance(inner.defects[0], |
| 1829 errors.StartBoundaryNotFoundDefect)) | 1827 errors.StartBoundaryNotFoundDefect)) |
| 1830 | 1828 |
| 1829 # test_parser.TestMessageDefectDetectionBase |
| 1831 def test_multipart_no_boundary(self): | 1830 def test_multipart_no_boundary(self): |
| 1832 unless = self.assertTrue | 1831 unless = self.assertTrue |
| 1833 msg = self._msgobj('msg_25.txt') | 1832 msg = self._msgobj('msg_25.txt') |
| 1834 unless(isinstance(msg.get_payload(), str)) | 1833 unless(isinstance(msg.get_payload(), str)) |
| 1835 self.assertEqual(len(self.get_defects(msg)), 2) | 1834 self.assertEqual(len(msg.defects), 2) |
| 1836 unless(isinstance(self.get_defects(msg)[0], | 1835 unless(isinstance(msg.defects[0], |
| 1837 errors.NoBoundaryInMultipartDefect)) | 1836 errors.NoBoundaryInMultipartDefect)) |
| 1838 unless(isinstance(self.get_defects(msg)[1], | 1837 unless(isinstance(msg.defects[1], |
| 1839 errors.MultipartInvariantViolationDefect)) | 1838 errors.MultipartInvariantViolationDefect)) |
| 1840 | 1839 |
| 1841 multipart_msg = textwrap.dedent("""\ | 1840 multipart_msg = textwrap.dedent("""\ |
| 1842 Date: Wed, 14 Nov 2007 12:56:23 GMT | 1841 Date: Wed, 14 Nov 2007 12:56:23 GMT |
| 1843 From: foo@bar.invalid | 1842 From: foo@bar.invalid |
| 1844 To: foo@bar.invalid | 1843 To: foo@bar.invalid |
| 1845 Subject: Content-Transfer-Encoding: base64 and multipart | 1844 Subject: Content-Transfer-Encoding: base64 and multipart |
| 1846 MIME-Version: 1.0 | 1845 MIME-Version: 1.0 |
| 1847 Content-Type: multipart/mixed; | 1846 Content-Type: multipart/mixed; |
| 1848 boundary="===============3344438784458119861=="{} | 1847 boundary="===============3344438784458119861=="{} |
| 1849 | 1848 |
| 1850 --===============3344438784458119861== | 1849 --===============3344438784458119861== |
| 1851 Content-Type: text/plain | 1850 Content-Type: text/plain |
| 1852 | 1851 |
| 1853 Test message | 1852 Test message |
| 1854 | 1853 |
| 1855 --===============3344438784458119861== | 1854 --===============3344438784458119861== |
| 1856 Content-Type: application/octet-stream | 1855 Content-Type: application/octet-stream |
| 1857 Content-Transfer-Encoding: base64 | 1856 Content-Transfer-Encoding: base64 |
| 1858 | 1857 |
| 1859 YWJj | 1858 YWJj |
| 1860 | 1859 |
| 1861 --===============3344438784458119861==-- | 1860 --===============3344438784458119861==-- |
| 1862 """) | 1861 """) |
| 1863 | 1862 |
| 1863 # test_parser.TestMessageDefectDetectionBase |
| 1864 def test_multipart_invalid_cte(self): | 1864 def test_multipart_invalid_cte(self): |
| 1865 msg = email.message_from_string( | 1865 msg = self._str_msg( |
| 1866 self.multipart_msg.format("\nContent-Transfer-Encoding: base64"), | 1866 self.multipart_msg.format("\nContent-Transfer-Encoding: base64")) |
| 1867 policy = self.policy) | 1867 self.assertEqual(len(msg.defects), 1) |
| 1868 self.assertEqual(len(self.get_defects(msg)), 1) | 1868 self.assertIsInstance(msg.defects[0], |
| 1869 self.assertIsInstance(self.get_defects(msg)[0], | |
| 1870 errors.InvalidMultipartContentTransferEncodingDefect) | 1869 errors.InvalidMultipartContentTransferEncodingDefect) |
| 1871 | 1870 |
| 1871 # test_parser.TestMessageDefectDetectionBase |
| 1872 def test_multipart_no_cte_no_defect(self): | 1872 def test_multipart_no_cte_no_defect(self): |
| 1873 msg = email.message_from_string( | 1873 msg = self._str_msg(self.multipart_msg.format('')) |
| 1874 self.multipart_msg.format(''), | 1874 self.assertEqual(len(msg.defects), 0) |
| 1875 policy = self.policy) | |
| 1876 self.assertEqual(len(self.get_defects(msg)), 0) | |
| 1877 | 1875 |
| 1876 # test_parser.TestMessageDefectDetectionBase |
| 1878 def test_multipart_valid_cte_no_defect(self): | 1877 def test_multipart_valid_cte_no_defect(self): |
| 1879 for cte in ('7bit', '8bit', 'BINary'): | 1878 for cte in ('7bit', '8bit', 'BINary'): |
| 1880 msg = email.message_from_string( | 1879 msg = self._str_msg( |
| 1881 self.multipart_msg.format( | 1880 self.multipart_msg.format( |
| 1882 "\nContent-Transfer-Encoding: {}".format(cte)), | 1881 "\nContent-Transfer-Encoding: {}".format(cte))) |
| 1883 policy = self.policy) | 1882 self.assertEqual(len(msg.defects), 0) |
| 1884 self.assertEqual(len(self.get_defects(msg)), 0) | |
| 1885 | 1883 |
| 1886 def test_invalid_content_type(self): | 1884 def test_invalid_content_type(self): |
| 1887 eq = self.assertEqual | 1885 eq = self.assertEqual |
| 1888 neq = self.ndiffAssertEqual | 1886 neq = self.ndiffAssertEqual |
| 1889 msg = Message() | 1887 msg = Message() |
| 1890 # RFC 2045, $5.2 says invalid yields text/plain | 1888 # RFC 2045, $5.2 says invalid yields text/plain |
| 1891 msg['Content-Type'] = 'text' | 1889 msg['Content-Type'] = 'text' |
| 1892 eq(msg.get_content_maintype(), 'text') | 1890 eq(msg.get_content_maintype(), 'text') |
| 1893 eq(msg.get_content_subtype(), 'plain') | 1891 eq(msg.get_content_subtype(), 'plain') |
| 1894 eq(msg.get_content_type(), 'text/plain') | 1892 eq(msg.get_content_type(), 'text/plain') |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1925 eq = self.ndiffAssertEqual | 1923 eq = self.ndiffAssertEqual |
| 1926 msg = self._msgobj('msg_35.txt') | 1924 msg = self._msgobj('msg_35.txt') |
| 1927 eq(msg.as_string(), """\ | 1925 eq(msg.as_string(), """\ |
| 1928 From: aperson@dom.ain | 1926 From: aperson@dom.ain |
| 1929 To: bperson@dom.ain | 1927 To: bperson@dom.ain |
| 1930 Subject: here's something interesting | 1928 Subject: here's something interesting |
| 1931 | 1929 |
| 1932 counter to RFC 2822, there's no separating newline here | 1930 counter to RFC 2822, there's no separating newline here |
| 1933 """) | 1931 """) |
| 1934 | 1932 |
| 1933 # test_parser.TestMessageDefectDetectionBase |
| 1935 def test_lying_multipart(self): | 1934 def test_lying_multipart(self): |
| 1936 unless = self.assertTrue | 1935 unless = self.assertTrue |
| 1937 msg = self._msgobj('msg_41.txt') | 1936 msg = self._msgobj('msg_41.txt') |
| 1938 unless(hasattr(msg, 'defects')) | 1937 unless(hasattr(msg, 'defects')) |
| 1939 self.assertEqual(len(self.get_defects(msg)), 2) | 1938 self.assertEqual(len(msg.defects), 2) |
| 1940 unless(isinstance(self.get_defects(msg)[0], | 1939 unless(isinstance(msg.defects[0], |
| 1941 errors.NoBoundaryInMultipartDefect)) | 1940 errors.NoBoundaryInMultipartDefect)) |
| 1942 unless(isinstance(self.get_defects(msg)[1], | 1941 unless(isinstance(msg.defects[1], |
| 1943 errors.MultipartInvariantViolationDefect)) | 1942 errors.MultipartInvariantViolationDefect)) |
| 1944 | 1943 |
| 1944 # test_parser.TestMessageDefectDetectionBase |
| 1945 def test_missing_start_boundary(self): | 1945 def test_missing_start_boundary(self): |
| 1946 outer = self._msgobj('msg_42.txt') | 1946 outer = self._msgobj('msg_42.txt') |
| 1947 # The message structure is: | 1947 # The message structure is: |
| 1948 # | 1948 # |
| 1949 # multipart/mixed | 1949 # multipart/mixed |
| 1950 # text/plain | 1950 # text/plain |
| 1951 # message/rfc822 | 1951 # message/rfc822 |
| 1952 # multipart/mixed [*] | 1952 # multipart/mixed [*] |
| 1953 # | 1953 # |
| 1954 # [*] This message is missing its start boundary | 1954 # [*] This message is missing its start boundary |
| 1955 bad = outer.get_payload(1).get_payload(0) | 1955 bad = outer.get_payload(1).get_payload(0) |
| 1956 self.assertEqual(len(self.get_defects(bad)), 1) | 1956 self.assertEqual(len(bad.defects), 1) |
| 1957 self.assertTrue(isinstance(self.get_defects(bad)[0], | 1957 self.assertTrue(isinstance(bad.defects[0], |
| 1958 errors.StartBoundaryNotFoundDefect)) | 1958 errors.StartBoundaryNotFoundDefect)) |
| 1959 | 1959 |
| 1960 # test_parser.TestMessageDefectDetectionBase |
| 1960 def test_first_line_is_continuation_header(self): | 1961 def test_first_line_is_continuation_header(self): |
| 1961 eq = self.assertEqual | 1962 eq = self.assertEqual |
| 1962 m = ' Line 1\nLine 2\nLine 3' | 1963 m = ' Line 1\nLine 2\nLine 3' |
| 1963 msg = email.message_from_string(m, policy=self.policy) | 1964 msg = email.message_from_string(m) |
| 1964 eq(msg.keys(), []) | 1965 eq(msg.keys(), []) |
| 1965 eq(msg.get_payload(), 'Line 2\nLine 3') | 1966 eq(msg.get_payload(), 'Line 2\nLine 3') |
| 1966 eq(len(self.get_defects(msg)), 1) | 1967 eq(len(msg.defects), 1) |
| 1967 self.assertTrue(isinstance(self.get_defects(msg)[0], | 1968 self.assertTrue(isinstance(msg.defects[0], |
| 1968 errors.FirstHeaderLineIsContinuationDefect)) | 1969 errors.FirstHeaderLineIsContinuationDefect)) |
| 1969 eq(self.get_defects(msg)[0].line, ' Line 1\n') | 1970 eq(msg.defects[0].line, ' Line 1\n') |
| 1970 | |
| 1971 | |
| 1972 class TestNonConformant(TestNonConformantBase, TestEmailBase): | |
| 1973 | |
| 1974 policy=email.policy.default | |
| 1975 | |
| 1976 def get_defects(self, obj): | |
| 1977 return obj.defects | |
| 1978 | |
| 1979 | |
| 1980 class TestNonConformantCapture(TestNonConformantBase, TestEmailBase): | |
| 1981 | |
| 1982 class CapturePolicy(email.policy.Policy): | |
| 1983 captured = None | |
| 1984 def register_defect(self, obj, defect): | |
| 1985 self.captured.append(defect) | |
| 1986 | |
| 1987 def setUp(self): | |
| 1988 self.policy = self.CapturePolicy(captured=list()) | |
| 1989 | |
| 1990 def get_defects(self, obj): | |
| 1991 return self.policy.captured | |
| 1992 | |
| 1993 | |
| 1994 class TestRaisingDefects(TestEmailBase): | |
| 1995 | |
| 1996 def _msgobj(self, filename): | |
| 1997 with openfile(filename) as fp: | |
| 1998 return email.message_from_file(fp, policy=email.policy.strict) | |
| 1999 | |
| 2000 def test_same_boundary_inner_outer(self): | |
| 2001 with self.assertRaises(errors.StartBoundaryNotFoundDefect): | |
| 2002 self._msgobj('msg_15.txt') | |
| 2003 | |
| 2004 def test_multipart_no_boundary(self): | |
| 2005 with self.assertRaises(errors.NoBoundaryInMultipartDefect): | |
| 2006 self._msgobj('msg_25.txt') | |
| 2007 | |
| 2008 def test_lying_multipart(self): | |
| 2009 with self.assertRaises(errors.NoBoundaryInMultipartDefect): | |
| 2010 self._msgobj('msg_41.txt') | |
| 2011 | |
| 2012 | |
| 2013 def test_missing_start_boundary(self): | |
| 2014 with self.assertRaises(errors.StartBoundaryNotFoundDefect): | |
| 2015 self._msgobj('msg_42.txt') | |
| 2016 | |
| 2017 def test_first_line_is_continuation_header(self): | |
| 2018 m = ' Line 1\nLine 2\nLine 3' | |
| 2019 with self.assertRaises(errors.FirstHeaderLineIsContinuationDefect): | |
| 2020 msg = email.message_from_string(m, policy=email.policy.strict) | |
| 2021 | 1971 |
| 2022 | 1972 |
| 2023 # Test RFC 2047 header encoding and decoding | 1973 # Test RFC 2047 header encoding and decoding |
| 2024 class TestRFC2047(TestEmailBase): | 1974 class TestRFC2047(TestEmailBase): |
| 2025 def test_rfc2047_multiline(self): | 1975 def test_rfc2047_multiline(self): |
| 2026 eq = self.assertEqual | 1976 eq = self.assertEqual |
| 2027 s = """Re: =?mac-iceland?q?r=8Aksm=9Arg=8Cs?= baz | 1977 s = """Re: =?mac-iceland?q?r=8Aksm=9Arg=8Cs?= baz |
| 2028 foo bar =?mac-iceland?q?r=8Aksm=9Arg=8Cs?=""" | 1978 foo bar =?mac-iceland?q?r=8Aksm=9Arg=8Cs?=""" |
| 2029 dh = decode_header(s) | 1979 dh = decode_header(s) |
| 2030 eq(dh, [ | 1980 eq(dh, [ |
| (...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2602 pass | 2552 pass |
| 2603 | 2553 |
| 2604 with openfile('msg_01.txt') as fp: | 2554 with openfile('msg_01.txt') as fp: |
| 2605 msg = email.message_from_file(fp, MyMessage) | 2555 msg = email.message_from_file(fp, MyMessage) |
| 2606 unless(isinstance(msg, MyMessage)) | 2556 unless(isinstance(msg, MyMessage)) |
| 2607 # Try something more complicated | 2557 # Try something more complicated |
| 2608 with openfile('msg_02.txt') as fp: | 2558 with openfile('msg_02.txt') as fp: |
| 2609 msg = email.message_from_file(fp, MyMessage) | 2559 msg = email.message_from_file(fp, MyMessage) |
| 2610 for subpart in msg.walk(): | 2560 for subpart in msg.walk(): |
| 2611 unless(isinstance(subpart, MyMessage)) | 2561 unless(isinstance(subpart, MyMessage)) |
| 2562 |
| 2563 def test_custom_message_does_not_require_arguments(self): |
| 2564 class MyMessage(Message): |
| 2565 def __init__(self): |
| 2566 super().__init__() |
| 2567 msg = self._str_msg("Subject: test\n\ntest", MyMessage) |
| 2568 self.assertTrue(isinstance(msg, MyMessage)) |
| 2612 | 2569 |
| 2613 def test__all__(self): | 2570 def test__all__(self): |
| 2614 module = __import__('email') | 2571 module = __import__('email') |
| 2615 self.assertEqual(sorted(module.__all__), [ | 2572 self.assertEqual(sorted(module.__all__), [ |
| 2616 'base64mime', 'charset', 'encoders', 'errors', 'feedparser', | 2573 'base64mime', 'charset', 'encoders', 'errors', 'feedparser', |
| 2617 'generator', 'header', 'iterators', 'message', | 2574 'generator', 'header', 'iterators', 'message', |
| 2618 'message_from_binary_file', 'message_from_bytes', | 2575 'message_from_binary_file', 'message_from_bytes', |
| 2619 'message_from_file', 'message_from_string', 'mime', 'parser', | 2576 'message_from_file', 'message_from_string', 'mime', 'parser', |
| 2620 'quoprimime', 'utils', | 2577 'quoprimime', 'utils', |
| 2621 ]) | 2578 ]) |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3128 eq(part2.get_content_type(), 'application/riscos') | 3085 eq(part2.get_content_type(), 'application/riscos') |
| 3129 | 3086 |
| 3130 def test_crlf_flatten(self): | 3087 def test_crlf_flatten(self): |
| 3131 # Using newline='\n' preserves the crlfs in this input file. | 3088 # Using newline='\n' preserves the crlfs in this input file. |
| 3132 with openfile('msg_26.txt', newline='\n') as fp: | 3089 with openfile('msg_26.txt', newline='\n') as fp: |
| 3133 text = fp.read() | 3090 text = fp.read() |
| 3134 msg = email.message_from_string(text) | 3091 msg = email.message_from_string(text) |
| 3135 s = StringIO() | 3092 s = StringIO() |
| 3136 g = Generator(s) | 3093 g = Generator(s) |
| 3137 g.flatten(msg, linesep='\r\n') | 3094 g.flatten(msg, linesep='\r\n') |
| 3138 self.assertEqual(s.getvalue(), text) | |
| 3139 | |
| 3140 def test_crlf_control_via_policy(self): | |
| 3141 with openfile('msg_26.txt', newline='\n') as fp: | |
| 3142 text = fp.read() | |
| 3143 msg = email.message_from_string(text) | |
| 3144 s = StringIO() | |
| 3145 g = email.generator.Generator(s, policy=email.policy.SMTP) | |
| 3146 g.flatten(msg) | |
| 3147 self.assertEqual(s.getvalue(), text) | |
| 3148 | |
| 3149 def test_flatten_linesep_overrides_policy(self): | |
| 3150 # msg_27 is lf separated | |
| 3151 with openfile('msg_27.txt', newline='\n') as fp: | |
| 3152 text = fp.read() | |
| 3153 msg = email.message_from_string(text) | |
| 3154 s = StringIO() | |
| 3155 g = email.generator.Generator(s, policy=email.policy.SMTP) | |
| 3156 g.flatten(msg, linesep='\n') | |
| 3157 self.assertEqual(s.getvalue(), text) | 3095 self.assertEqual(s.getvalue(), text) |
| 3158 | 3096 |
| 3159 maxDiff = None | 3097 maxDiff = None |
| 3160 | 3098 |
| 3161 def test_multipart_digest_with_extra_mime_headers(self): | 3099 def test_multipart_digest_with_extra_mime_headers(self): |
| 3162 eq = self.assertEqual | 3100 eq = self.assertEqual |
| 3163 neq = self.ndiffAssertEqual | 3101 neq = self.ndiffAssertEqual |
| 3164 with openfile('msg_28.txt') as fp: | 3102 with openfile('msg_28.txt') as fp: |
| 3165 msg = email.message_from_file(fp) | 3103 msg = email.message_from_file(fp) |
| 3166 # Structure is: | 3104 # Structure is: |
| (...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3638 # Since this broke in ByteGenerator, test Generator for completeness. | 3576 # Since this broke in ByteGenerator, test Generator for completeness. |
| 3639 m = Message() | 3577 m = Message() |
| 3640 # This has enough non-ascii that it should always end up b encoded. | 3578 # This has enough non-ascii that it should always end up b encoded. |
| 3641 m['Subject'] = Header('žluťoučký kůň') | 3579 m['Subject'] = Header('žluťoučký kůň') |
| 3642 s = StringIO() | 3580 s = StringIO() |
| 3643 g = email.generator.Generator(s) | 3581 g = email.generator.Generator(s) |
| 3644 g.flatten(m, linesep='\r\n') | 3582 g.flatten(m, linesep='\r\n') |
| 3645 self.assertEqual( | 3583 self.assertEqual( |
| 3646 s.getvalue(), | 3584 s.getvalue(), |
| 3647 'Subject: =?utf-8?b?xb5sdcWlb3XEjWvDvSBrxa/FiA==?=\r\n\r\n') | 3585 'Subject: =?utf-8?b?xb5sdcWlb3XEjWvDvSBrxa/FiA==?=\r\n\r\n') |
| 3648 | |
| 3649 def test_crlf_control_via_policy(self): | |
| 3650 # msg_26 is crlf terminated | |
| 3651 with openfile('msg_26.txt', 'rb') as fp: | |
| 3652 text = fp.read() | |
| 3653 msg = email.message_from_bytes(text) | |
| 3654 s = BytesIO() | |
| 3655 g = email.generator.BytesGenerator(s, policy=email.policy.SMTP) | |
| 3656 g.flatten(msg) | |
| 3657 self.assertEqual(s.getvalue(), text) | |
| 3658 | |
| 3659 def test_flatten_linesep_overrides_policy(self): | |
| 3660 # msg_27 is lf separated | |
| 3661 with openfile('msg_27.txt', 'rb') as fp: | |
| 3662 text = fp.read() | |
| 3663 msg = email.message_from_bytes(text) | |
| 3664 s = BytesIO() | |
| 3665 g = email.generator.BytesGenerator(s, policy=email.policy.SMTP) | |
| 3666 g.flatten(msg, linesep='\n') | |
| 3667 self.assertEqual(s.getvalue(), text) | |
| 3668 | |
| 3669 def test_must_be_7bit_handles_unknown_8bit(self): | |
| 3670 msg = email.message_from_bytes(self.non_latin_bin_msg) | |
| 3671 out = BytesIO() | |
| 3672 g = email.generator.BytesGenerator(out, | |
| 3673 policy=email.policy.default.clone(must_be_7bit=True)) | |
| 3674 g.flatten(msg) | |
| 3675 self.assertEqual(out.getvalue(), | |
| 3676 self.non_latin_bin_msg_as7bit_wrapped.encode('ascii')) | |
| 3677 | |
| 3678 def test_must_be_7bit_transforms_8bit_cte(self): | |
| 3679 msg = email.message_from_bytes(self.latin_bin_msg) | |
| 3680 out = BytesIO() | |
| 3681 g = email.generator.BytesGenerator(out, | |
| 3682 policy=email.policy.default.clone(must_be_7bit=True)) | |
| 3683 g.flatten(msg) | |
| 3684 self.assertEqual(out.getvalue(), | |
| 3685 self.latin_bin_msg_as7bit.encode('ascii')) | |
| 3686 | 3586 |
| 3687 maxDiff = None | 3587 maxDiff = None |
| 3688 | 3588 |
| 3689 | 3589 |
| 3690 class BaseTestBytesGeneratorIdempotent: | 3590 class BaseTestBytesGeneratorIdempotent: |
| 3691 | 3591 |
| 3692 maxDiff = None | 3592 maxDiff = None |
| 3693 | 3593 |
| 3694 def _msgobj(self, filename): | 3594 def _msgobj(self, filename): |
| 3695 with openfile(filename, 'rb') as fp: | 3595 with openfile(filename, 'rb') as fp: |
| (...skipping 1185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4881 original, msg = self._msg_and_obj('msg_45.txt') | 4781 original, msg = self._msg_and_obj('msg_45.txt') |
| 4882 fp = StringIO() | 4782 fp = StringIO() |
| 4883 Generator(fp).flatten(msg) | 4783 Generator(fp).flatten(msg) |
| 4884 result = fp.getvalue() | 4784 result = fp.getvalue() |
| 4885 self._signed_parts_eq(original, result) | 4785 self._signed_parts_eq(original, result) |
| 4886 | 4786 |
| 4887 | 4787 |
| 4888 | 4788 |
| 4889 if __name__ == '__main__': | 4789 if __name__ == '__main__': |
| 4890 unittest.main() | 4790 unittest.main() |
| OLD | NEW |