def test_set_headers_with_invalid_duplicate_string_header_raises(self): m = self._make_message() content = "Simple message.\n" with self.assertRaisesRegex(ValueError, 'Content-Type'): raw_data_manager.set_content(m, content, headers=( "Content-Type: foo/bar",) )
def test_set_text_11_lines_long_line_maximal_non_ascii_heuristics(self): # Yes, it chooses "wrong" here. It's a heuristic. So this result # could change if we come up with a better heuristic. m = self._make_message() content = ('\n'*10 + "áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő" "áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő" "áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő.\n") raw_data_manager.set_content(m, "\n"*10 + "áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő" "áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő" "áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő.\n") self.assertEqual(bytes(m), textwrap.dedent("""\ Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable """ + '\n'*10 + """ =C3=A1=C3=A0=C3=A4=C3=A9=C3=A8=C4=99=C3=B6=C5=91=C3=A1=C3= =A0=C3=A4=C3=A9=C3=A8=C4=99=C3=B6=C5=91=C3=A1=C3=A0=C3=A4= =C3=A9=C3=A8=C4=99=C3=B6=C5=91=C3=A1=C3=A0=C3=A4=C3=A9=C3= =A8=C4=99=C3=B6=C5=91=C3=A1=C3=A0=C3=A4=C3=A9=C3=A8=C4=99= =C3=B6=C5=91=C3=A1=C3=A0=C3=A4=C3=A9=C3=A8=C4=99=C3=B6=C5= =91=C3=A1=C3=A0=C3=A4=C3=A9=C3=A8=C4=99=C3=B6=C5=91=C3=A1= =C3=A0=C3=A4=C3=A9=C3=A8=C4=99=C3=B6=C5=91=C3=A1=C3=A0=C3= =A4=C3=A9=C3=A8=C4=99=C3=B6=C5=91=C3=A1=C3=A0=C3=A4=C3=A9= =C3=A8=C4=99=C3=B6=C5=91=C3=A1=C3=A0=C3=A4=C3=A9=C3=A8=C4= =99=C3=B6=C5=91=C3=A1=C3=A0=C3=A4=C3=A9=C3=A8=C4=99=C3=B6= =C5=91. """).encode('utf-8')) self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content) self.assertEqual(m.get_content(), content)
def test_set_message(self): m = self._make_message() m['Subject'] = "Forwarded message" content = self._make_message() content['To'] = '*****@*****.**' content['From'] = '*****@*****.**' content['Subject'] = "get back in your box" content.set_content("Or face the comfy chair.") raw_data_manager.set_content(m, content) self.assertEqual(str(m), textwrap.dedent("""\ Subject: Forwarded message Content-Type: message/rfc822 Content-Transfer-Encoding: 8bit To: [email protected] From: [email protected] Subject: get back in your box Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit MIME-Version: 1.0 Or face the comfy chair. """)) payload = m.get_payload(0) self.assertIsInstance(payload, self.message) self.assertEqual(str(payload), str(content)) self.assertIsInstance(m.get_content(), self.message) self.assertEqual(str(m.get_content()), str(content))
def test_set_headers_with_invalid_duplicate_header_header_raises(self): m = self._make_message() content = "Simple message.\n" header_factory = self.policy.header_factory with self.assertRaisesRegex(ValueError, 'Content-Type'): raw_data_manager.set_content(m, content, headers=( header_factory("Content-Type", " foo/bar"),) )
def test_set_headers_with_defective_string_header_raises(self): m = self._make_message() content = "Simple message.\n" with self.assertRaisesRegex(ValueError, 'a@fairly@@invalid@address'): raw_data_manager.set_content(m, content, headers=( 'To: a@fairly@@invalid@address',) ) print(m['To'].defects)
def set_content(self, msg, obj, *args, **kw): if isinstance(obj, str): kw["cte"] = "quoted-printable" raw_data_manager.set_content(msg, obj, *args, **kw) if msg.get("content-transfer-encoding") == "quoted-printable": content = msg.get_payload(decode=False) from_escaped = content.replace("From ", "From=20") msg.set_payload(from_escaped)
def test_set_text_charset_latin_1(self): m = self._make_message() content = "Simple message.\n" raw_data_manager.set_content(m, content, charset='latin-1') self.assertEqual(str(m), textwrap.dedent("""\ Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Simple message. """)) self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content) self.assertEqual(m.get_content(), content)
def test_set_text_11_lines_maximal_non_ascii_heuristics(self): m = self._make_message() content = '\n'*10 + "áàäéèęöő.\n" raw_data_manager.set_content(m, content) self.assertEqual(bytes(m), textwrap.dedent("""\ Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit """ + '\n'*10 + """ áàäéèęöő. """).encode('utf-8')) self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content) self.assertEqual(m.get_content(), content)
def test_set_text_short_line_minimal_non_ascii_heuristics(self): m = self._make_message() content = "et là il est monté sur moi et il commence à m'éto.\n" raw_data_manager.set_content(m, content) self.assertEqual(bytes(m), textwrap.dedent("""\ Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit et là il est monté sur moi et il commence à m'éto. """).encode('utf-8')) self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content) self.assertEqual(m.get_content(), content)
def test_set_text_html(self): m = self._make_message() content = "<p>Simple message.</p>\n" raw_data_manager.set_content(m, content, subtype='html') self.assertEqual(str(m), textwrap.dedent("""\ Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: 7bit <p>Simple message.</p> """)) self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content) self.assertEqual(m.get_content(), content)
def test_set_text_maximal_non_ascii_heuristics(self): m = self._make_message() content = "áàäéèęöő.\n" raw_data_manager.set_content(m, content) self.assertEqual( bytes(m), textwrap.dedent("""\ Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit áàäéèęöő. """).encode('utf-8')) self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content) self.assertEqual(m.get_content(), content)
def test_set_text_short_line_minimal_non_ascii_heuristics(self): m = self._make_message() content = "et là il est monté sur moi et il commence à m'éto.\n" raw_data_manager.set_content(m, content) self.assertEqual( bytes(m), textwrap.dedent("""\ Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit et là il est monté sur moi et il commence à m'éto. """).encode('utf-8')) self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content) self.assertEqual(m.get_content(), content)
def test_set_text_charset_latin_1(self): m = self._make_message() content = "Simple message.\n" raw_data_manager.set_content(m, content, charset='latin-1') self.assertEqual( str(m), textwrap.dedent("""\ Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Simple message. """)) self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content) self.assertEqual(m.get_content(), content)
def test_set_text_html(self): m = self._make_message() content = "<p>Simple message.</p>\n" raw_data_manager.set_content(m, content, subtype='html') self.assertEqual( str(m), textwrap.dedent("""\ Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: 7bit <p>Simple message.</p> """)) self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content) self.assertEqual(m.get_content(), content)
def test_set_message_with_non_ascii_and_coercion_to_7bit(self): m = self._make_message() m['Subject'] = "Escape report" content = self._make_message() content['To'] = '*****@*****.**' content['From'] = '*****@*****.**' content['Subject'] = "Help" content.set_content("j'ai un problème de python. il est sorti de son" " vivarium.") raw_data_manager.set_content(m, content) self.assertEqual( bytes(m), textwrap.dedent("""\ Subject: Escape report Content-Type: message/rfc822 Content-Transfer-Encoding: 8bit To: [email protected] From: [email protected] Subject: Help Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit MIME-Version: 1.0 j'ai un problème de python. il est sorti de son vivarium. """).encode('utf-8')) # The choice of base64 for the body encoding is because generator # doesn't bother with heuristics and uses it unconditionally for utf-8 # text. # XXX: the first cte should be 7bit, too...that's a generator bug. # XXX: the line length in the body also looks like a generator bug. self.assertEqual( m.as_string(maxheaderlen=self.policy.max_line_length), textwrap.dedent("""\ Subject: Escape report Content-Type: message/rfc822 Content-Transfer-Encoding: 8bit To: [email protected] From: [email protected] Subject: Help Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 aidhaSB1biBwcm9ibMOobWUgZGUgcHl0aG9uLiBpbCBlc3Qgc29ydGkgZGUgc29uIHZpdmFyaXVt Lgo= """)) self.assertIsInstance(m.get_content(), self.message) self.assertEqual(str(m.get_content()), str(content))
def test_set_headers_from_strings(self): m = self._make_message() content = 'Simple message.\n' raw_data_manager.set_content(m, content, headers=( 'X-Foo-Header: foo', 'X-Bar-Header: bar')) self.assertEqual(str(m), textwrap.dedent( """ Content-Type: text/plain; charset="utf-8" X-Foo-Header: foo X-Bar-Header: bar Content-Transfer-Encoding: 7bit Simple message. """ ))
def test_set_text_plain_null(self): m = self._make_message() content = '' raw_data_manager.set_content(m, content) self.assertEqual( str(m), textwrap.dedent("""\ Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit """)) self.assertEqual(m.get_payload(decode=True).decode('utf-8'), '\n') self.assertEqual(m.get_content(), '\n')
def test_set_text_plain_long_line_heuristics(self): m = self._make_message() content = ("Simple but long message that is over 78 characters" " long to force transfer encoding.\n") raw_data_manager.set_content(m, content) self.assertEqual(str(m), textwrap.dedent("""\ Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Simple but long message that is over 78 characters long to = force transfer encoding. """)) self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content) self.assertEqual(m.get_content(), content)
def test_set_headers_from_strings(self): m = self._make_message() content = "Simple message.\n" raw_data_manager.set_content(m, content, headers=( "X-Foo-Header: foo", "X-Bar-Header: bar",)) self.assertEqual(str(m), textwrap.dedent("""\ Content-Type: text/plain; charset="utf-8" X-Foo-Header: foo X-Bar-Header: bar Content-Transfer-Encoding: 7bit Simple message. """))
def test_set_image_jpg(self): for content in (b'bogus content', bytearray(b'bogus content'), memoryview(b'bogus content')): with self.subTest(content=content): m = self._make_message() raw_data_manager.set_content(m, content, 'image', 'jpeg') self.assertEqual(str(m), textwrap.dedent( """ Content-Type: image/jpeg Content-Transfer-Encoding: base64 Ym9ndXMgY29udGVudA== """ )) self.assertEqual(m.get_payload(decode=True), content) self.assertEqual(m.get_content(), content)
def test_set_image_jpg(self): for content in (b"bogus content", bytearray(b"bogus content"), memoryview(b"bogus content")): with self.subTest(content=content): m = self._make_message() raw_data_manager.set_content(m, content, 'image', 'jpeg') self.assertEqual(str(m), textwrap.dedent("""\ Content-Type: image/jpeg Content-Transfer-Encoding: base64 Ym9ndXMgY29udGVudA== """)) self.assertEqual(m.get_payload(decode=True), content) self.assertEqual(m.get_content(), content)
def test_set_text_long_line_minimal_non_ascii_heuristics(self): m = self._make_message() content = """j'ai un problème de python. il est sorti de son vivarium. et là il est monté sur moi et il commence à m'éto. """ raw_data_manager.set_content(m, content) self.assertEqual(bytes(m), textwrap.dedent( """ Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable j'ai un probl=C3=A8me de python. il est sorti de son vivari= um. et l=C3=A0 il est mont=C3=A9 sur moi et il commence = =C3=A0 m'=C3=A9to. """ ).encode('utf-8')) self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content) self.assertEqual(m.get_content(), content)
def test_set_text_long_line_minimal_non_ascii_heuristics(self): m = self._make_message() content = ("j'ai un problème de python. il est sorti de son" " vivarium. et là il est monté sur moi et il commence" " à m'éto.\n") raw_data_manager.set_content(m, content) self.assertEqual(bytes(m), textwrap.dedent("""\ Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable j'ai un probl=C3=A8me de python. il est sorti de son vivari= um. et l=C3=A0 il est mont=C3=A9 sur moi et il commence = =C3=A0 m'=C3=A9to. """).encode('utf-8')) self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content) self.assertEqual(m.get_content(), content)
def test_set_message_with_non_ascii_and_coercion_to_7bit(self): m = self._make_message() m['Subject'] = "Escape report" content = self._make_message() content['To'] = '*****@*****.**' content['From'] = '*****@*****.**' content['Subject'] = "Help" content.set_content("j'ai un problème de python. il est sorti de son" " vivarium.") raw_data_manager.set_content(m, content) self.assertEqual(bytes(m), textwrap.dedent("""\ Subject: Escape report Content-Type: message/rfc822 Content-Transfer-Encoding: 8bit To: [email protected] From: [email protected] Subject: Help Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit MIME-Version: 1.0 j'ai un problème de python. il est sorti de son vivarium. """).encode('utf-8')) # The choice of base64 for the body encoding is because generator # doesn't bother with heuristics and uses it unconditionally for utf-8 # text. # XXX: the first cte should be 7bit, too...that's a generator bug. # XXX: the line length in the body also looks like a generator bug. self.assertEqual(m.as_string(maxheaderlen=self.policy.max_line_length), textwrap.dedent("""\ Subject: Escape report Content-Type: message/rfc822 Content-Transfer-Encoding: 8bit To: [email protected] From: [email protected] Subject: Help Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 MIME-Version: 1.0 aidhaSB1biBwcm9ibMOobWUgZGUgcHl0aG9uLiBpbCBlc3Qgc29ydGkgZGUgc29uIHZpdmFyaXVt Lgo= """)) self.assertIsInstance(m.get_content(), self.message) self.assertEqual(str(m.get_content()), str(content))
def test_set_headers_from_header_objects(self): m = self._make_message() content = "Simple message.\n" header_factory = self.policy.header_factory raw_data_manager.set_content(m, content, headers=( header_factory("To", "*****@*****.**"), header_factory("From", "*****@*****.**"), header_factory("Subject", "I'm talking to myself."))) self.assertEqual(str(m), textwrap.dedent("""\ Content-Type: text/plain; charset="utf-8" To: [email protected] From: [email protected] Subject: I'm talking to myself. Content-Transfer-Encoding: 7bit Simple message. """))
def test_set_headers_from_header_objects(self): m = self._make_message() content = "Simple message.\n" header_factory = self.policy.header_factory raw_data_manager.set_content(m, content, headers=( header_factory("To", "*****@*****.**"), header_factory("From", "*****@*****.**"), header_factory("Subject", "I'm talking to myself."))) self.assertEqual(str(m), textwrap.dedent("""\ Content-Type: text/plain; charset="utf-8" To: [email protected] From: [email protected] Subject: I'm talking to myself. Content-Transfer-Encoding: 7bit Simple message. """))
def test_set_text_long_line_maximal_non_ascii_heuristics(self): m = self._make_message() content = """áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő. """ raw_data_manager.set_content(m, content) self.assertEqual(bytes(m), textwrap.dedent( """ Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 w6HDoMOkw6nDqMSZw7bFkcOhw6DDpMOpw6jEmcO2xZHDocOgw6TDqcOoxJnD tsWRw6HDoMOkw6nDqMSZw7bFkcOhw6DDpMOpw6jEmcO2xZHDocOgw6TDqcOo xJnDtsWRw6HDoMOkw6nDqMSZw7bFkcOhw6DDpMOpw6jEmcO2xZHDocOgw6TD qcOoxJnDtsWRw6HDoMOkw6nDqMSZw7bFkcOhw6DDpMOpw6jEmcO2xZHDocOg w6TDqcOoxJnDtsWRLgo= """ ).encode('utf-8')) self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content) self.assertEqual(m.get_content(), content)
def test_set_text_long_line_maximal_non_ascii_heuristics(self): m = self._make_message() content = ("áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő" "áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő" "áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő.\n") raw_data_manager.set_content(m, content) self.assertEqual(bytes(m), textwrap.dedent("""\ Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 w6HDoMOkw6nDqMSZw7bFkcOhw6DDpMOpw6jEmcO2xZHDocOgw6TDqcOoxJnD tsWRw6HDoMOkw6nDqMSZw7bFkcOhw6DDpMOpw6jEmcO2xZHDocOgw6TDqcOo xJnDtsWRw6HDoMOkw6nDqMSZw7bFkcOhw6DDpMOpw6jEmcO2xZHDocOgw6TD qcOoxJnDtsWRw6HDoMOkw6nDqMSZw7bFkcOhw6DDpMOpw6jEmcO2xZHDocOg w6TDqcOoxJnDtsWRLgo= """).encode('utf-8')) self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content) self.assertEqual(m.get_content(), content)
def test_set_message_with_non_ascii_and_coercion_to_7bit(self): m = self._make_message() m['Subject'] = 'Escape report' content = self._make_message() content['To'] = '*****@*****.**' content['From'] = '*****@*****.**' content['Subject'] = 'Help' content.set_content( "j'ai un problème de python. il est sorti de son vivarium.") raw_data_manager.set_content(m, content) self.assertEqual(bytes(m), textwrap.dedent( """ Subject: Escape report Content-Type: message/rfc822 Content-Transfer-Encoding: 8bit To: [email protected] From: [email protected] Subject: Help Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit MIME-Version: 1.0 j'ai un problème de python. il est sorti de son vivarium. """ ).encode('utf-8')) self.assertEqual(m.as_string(maxheaderlen=self.policy. max_line_length), textwrap.dedent( """ Subject: Escape report Content-Type: message/rfc822 Content-Transfer-Encoding: 8bit To: [email protected] From: [email protected] Subject: Help Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 MIME-Version: 1.0 aidhaSB1biBwcm9ibMOobWUgZGUgcHl0aG9uLiBpbCBlc3Qgc29ydGkgZGUgc29uIHZpdmFyaXVt Lgo= """ )) self.assertIsInstance(m.get_content(), self.message) self.assertEqual(str(m.get_content()), str(content))
def properties(self): """Serialize the object as a simple dict. Can be used to transform to CloudFormation Yaml format. :rtype: dict """ # This is important to keep the boundary static in order to avoid # spurious instance reboots. multi_part = MIMEMultipart( boundary="-_- :( :( /o/ Static User Data Boundary /o/ :) :) -_-") for name, kind, part in self.parts: mime_part = EmailMessage() raw_data_manager.set_content(mime_part, part, subtype=kind, filename=name) multi_part.attach(mime_part) return Base64(Sub(multi_part.as_string(), self.variables))
def test_set_text_non_ascii_with_cte_7bit_raises(self): m = self._make_message() with self.assertRaises(UnicodeError): raw_data_manager.set_content(m, 'áàäéèęöő.\n', cte='7bit')
def test_set_text_non_ascii_with_cte_7bit_and_charset_ascii_raises(self): m = self._make_message() with self.assertRaises(UnicodeError): raw_data_manager.set_content(m,"áàäéèęöő.\n", cte='7bit', charset='ascii')
def test_set_headers_with_invalid_duplicate_string_header_raises(self): m = self._make_message() content = 'Simple message.\n' with self.assertRaisesRegex(ValueError, 'Content-Type'): raw_data_manager.set_content(m, content, headers=( 'Content-Type: foo/bar',))
def test_set_text_non_ascii_with_charset_ascii_raises(self): m = self._make_message() with self.assertRaises(UnicodeError): raw_data_manager.set_content(m, "áàäéèęöő.\n", charset='ascii')