10c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Copyright (C) 2001-2010 Python Software Foundation 20c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Contact: email-sig@python.org 30c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# email package unit tests 40c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 50c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport os 60c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport sys 70c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport time 80c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport base64 90c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport difflib 100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport unittest 110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport warnings 120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport textwrap 130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom cStringIO import StringIO 140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport email 160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email.Charset import Charset 180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email.Header import Header, decode_header, make_header 190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email.Parser import Parser, HeaderParser 200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email.Generator import Generator, DecodedGenerator 210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email.Message import Message 220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email.MIMEAudio import MIMEAudio 230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email.MIMEText import MIMEText 240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email.MIMEImage import MIMEImage 250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email.MIMEBase import MIMEBase 260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email.MIMEMessage import MIMEMessage 270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email.MIMEMultipart import MIMEMultipart 280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email import Utils 290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email import Errors 300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email import Encoders 310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email import Iterators 320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email import base64MIME 330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email import quopriMIME 340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom test.test_support import findfile, run_unittest 360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom email.test import __file__ as landmark 370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiNL = '\n' 400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiEMPTYSTRING = '' 410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSPACE = ' ' 420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef openfile(filename, mode='r'): 460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi path = os.path.join(os.path.dirname(landmark), 'data', filename) 470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return open(path, mode) 480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Base test class 520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestEmailBase(unittest.TestCase): 530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def ndiffAssertEqual(self, first, second): 540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """Like assertEqual except use ndiff for readable output.""" 550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if first != second: 560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sfirst = str(first) 570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ssecond = str(second) 580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi diff = difflib.ndiff(sfirst.splitlines(), ssecond.splitlines()) 590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = StringIO() 600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print >> fp, NL, NL.join(diff) 610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi raise self.failureException, fp.getvalue() 620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def _msgobj(self, filename): 640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile(findfile(filename)) 650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_file(fp) 670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return msg 700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Test various aspects of the Message class's API 740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestMessageAPI(TestEmailBase): 750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_all(self): 760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_20.txt') 780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_all('cc'), ['ccc@zzz.org', 'ddd@zzz.org', 'eee@zzz.org']) 790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_all('xx', 'n/a'), 'n/a') 800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_getset_charset(self): 820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_charset(), None) 850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charset = Charset('iso-8859-1') 860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_charset(charset) 870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['mime-version'], '1.0') 880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_type(), 'text/plain') 890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-type'], 'text/plain; charset="iso-8859-1"') 900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('charset'), 'iso-8859-1') 910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-transfer-encoding'], 'quoted-printable') 920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_charset().input_charset, 'iso-8859-1') 930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Remove the charset 940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_charset(None) 950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_charset(), None) 960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-type'], 'text/plain') 970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Try adding a charset when there's already MIME headers present 980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['MIME-Version'] = '2.0' 1000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Content-Type'] = 'text/x-weird' 1010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Content-Transfer-Encoding'] = 'quinted-puntable' 1020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_charset(charset) 1030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['mime-version'], '2.0') 1040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-type'], 'text/x-weird; charset="iso-8859-1"') 1050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-transfer-encoding'], 'quinted-puntable') 1060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_set_charset_from_string(self): 1080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 1090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 1100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_charset('us-ascii') 1110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_charset().input_charset, 'us-ascii') 1120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-type'], 'text/plain; charset="us-ascii"') 1130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_set_payload_with_charset(self): 1150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 1160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charset = Charset('iso-8859-1') 1170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_payload('This is a string payload', charset) 1180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_charset().input_charset, 'iso-8859-1') 1190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_charsets(self): 1210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 1220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_08.txt') 1240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charsets = msg.get_charsets() 1250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(charsets, [None, 'us-ascii', 'iso-8859-1', 'iso-8859-2', 'koi8-r']) 1260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_09.txt') 1280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charsets = msg.get_charsets('dingbat') 1290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(charsets, ['dingbat', 'us-ascii', 'iso-8859-1', 'dingbat', 1300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'koi8-r']) 1310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_12.txt') 1330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charsets = msg.get_charsets() 1340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(charsets, [None, 'us-ascii', 'iso-8859-1', None, 'iso-8859-2', 1350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'iso-8859-3', 'us-ascii', 'koi8-r']) 1360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_filename(self): 1380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 1390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_04.txt') 1410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi filenames = [p.get_filename() for p in msg.get_payload()] 1420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(filenames, ['msg.txt', 'msg.txt']) 1430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_07.txt') 1450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi subpart = msg.get_payload(1) 1460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subpart.get_filename(), 'dingusfish.gif') 1470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_filename_with_name_parameter(self): 1490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 1500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_44.txt') 1520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi filenames = [p.get_filename() for p in msg.get_payload()] 1530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(filenames, ['msg.txt', 'msg.txt']) 1540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_boundary(self): 1560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 1570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_07.txt') 1580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # No quotes! 1590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_boundary(), 'BOUNDARY') 1600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_set_boundary(self): 1620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 1630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # This one has no existing boundary parameter, but the Content-Type: 1640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # header appears fifth. 1650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_01.txt') 1660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_boundary('BOUNDARY') 1670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi header, value = msg.items()[4] 1680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(header.lower(), 'content-type') 1690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(value, 'text/plain; charset="us-ascii"; boundary="BOUNDARY"') 1700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # This one has a Content-Type: header, with a boundary, stuck in the 1710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # middle of its headers. Make sure the order is preserved; it should 1720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # be fifth. 1730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_04.txt') 1740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_boundary('BOUNDARY') 1750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi header, value = msg.items()[4] 1760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(header.lower(), 'content-type') 1770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(value, 'multipart/mixed; boundary="BOUNDARY"') 1780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # And this one has no Content-Type: header at all. 1790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_03.txt') 1800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertRaises(Errors.HeaderParseError, 1810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_boundary, 'BOUNDARY') 1820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_make_boundary(self): 1840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEMultipart('form-data') 1850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Note that when the boundary gets created is an implementation 1860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # detail and might change. 1870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.items()[0][1], 'multipart/form-data') 1880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Trigger creation of boundary 1890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.as_string() 1900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.items()[0][1][:33], 1910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'multipart/form-data; boundary="==') 1920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # XXX: there ought to be tests of the uniqueness of the boundary, too. 1930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_message_rfc822_only(self): 1950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Issue 7970: message/rfc822 not in multipart parsed by 1960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # HeaderParser caused an exception when flattened. 1970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile(findfile('msg_46.txt')) 1980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msgdata = fp.read() 1990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi parser = email.Parser.HeaderParser() 2000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = parser.parsestr(msgdata) 2010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi out = StringIO() 2020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gen = email.Generator.Generator(out, True, 0) 2030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gen.flatten(msg, False) 2040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(out.getvalue(), msgdata) 2050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_decoded_payload(self): 2070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 2080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_10.txt') 2090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # The outer message is a multipart 2100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(decode=True), None) 2110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Subpart 1 is 7bit encoded 2120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(0).get_payload(decode=True), 2130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'This is a 7bit encoded message.\n') 2140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Subpart 2 is quopri 2150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(1).get_payload(decode=True), 2160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi '\xa1This is a Quoted Printable encoded message!\n') 2170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Subpart 3 is base64 2180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(2).get_payload(decode=True), 2190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'This is a Base64 encoded message.') 2200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Subpart 4 is base64 with a trailing newline, which 2210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # used to be stripped (issue 7143). 2220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(3).get_payload(decode=True), 2230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'This is a Base64 encoded message.\n') 2240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Subpart 5 has no Content-Transfer-Encoding: header. 2250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(4).get_payload(decode=True), 2260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'This has no Content-Transfer-Encoding: header.\n') 2270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_decoded_uu_payload(self): 2290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 2300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 2310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_payload('begin 666 -\n+:&5L;&\\@=V]R;&0 \n \nend\n') 2320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for cte in ('x-uuencode', 'uuencode', 'uue', 'x-uue'): 2330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['content-transfer-encoding'] = cte 2340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(decode=True), 'hello world') 2350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Now try some bogus data 2360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_payload('foo') 2370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(decode=True), 'foo') 2380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_decode_bogus_uu_payload_quietly(self): 2400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 2410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_payload('begin 664 foo.txt\n%<W1F=0000H \n \nend\n') 2420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Content-Transfer-Encoding'] = 'x-uuencode' 2430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi old_stderr = sys.stderr 2440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 2450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sys.stderr = sfp = StringIO() 2460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # We don't care about the payload 2470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.get_payload(decode=True) 2480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 2490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sys.stderr = old_stderr 2500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(sfp.getvalue(), '') 2510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_decoded_generator(self): 2530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 2540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_07.txt') 2550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('msg_17.txt') 2560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 2570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text = fp.read() 2580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 2590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 2600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = StringIO() 2610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = DecodedGenerator(s) 2620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g.flatten(msg) 2630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(s.getvalue(), text) 2640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test__contains__(self): 2660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 2670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['From'] = 'Me' 2680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['to'] = 'You' 2690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Check for case insensitivity 2700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue('from' in msg) 2710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue('From' in msg) 2720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue('FROM' in msg) 2730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue('to' in msg) 2740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue('To' in msg) 2750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue('TO' in msg) 2760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_as_string(self): 2780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 2790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_01.txt') 2800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('msg_01.txt') 2810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 2820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # BAW 30-Mar-2009 Evil be here. So, the generator is broken with 2830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # respect to long line breaking. It's also not idempotent when a 2840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # header from a parsed message is continued with tabs rather than 2850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # spaces. Before we fixed bug 1974 it was reversedly broken, 2860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # i.e. headers that were continued with spaces got continued with 2870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # tabs. For Python 2.x there's really no good fix and in Python 2880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # 3.x all this stuff is re-written to be right(er). Chris Withers 2890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # convinced me that using space as the default continuation 2900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # character is less bad for more applications. 2910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text = fp.read().replace('\t', ' ') 2920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 2930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 2940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(text, msg.as_string()) 2950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fullrepr = str(msg) 2960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi lines = fullrepr.split('\n') 2970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(lines[0].startswith('From ')) 2980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(text, NL.join(lines[1:])) 2990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_bad_param(self): 3010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string("Content-Type: blarg; baz; boo\n") 3020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_param('baz'), '') 3030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_missing_filename(self): 3050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string("From: foo\n") 3060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_filename(), None) 3070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_bogus_filename(self): 3090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string( 3100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "Content-Disposition: blarg; filename\n") 3110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_filename(), '') 3120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_missing_boundary(self): 3140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string("From: foo\n") 3150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_boundary(), None) 3160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_params(self): 3180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 3190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string( 3200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'X-Header: foo=one; bar=two; baz=three\n') 3210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_params(header='x-header'), 3220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi [('foo', 'one'), ('bar', 'two'), ('baz', 'three')]) 3230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string( 3240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'X-Header: foo; bar=one; baz=two\n') 3250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_params(header='x-header'), 3260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi [('foo', ''), ('bar', 'one'), ('baz', 'two')]) 3270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_params(), None) 3280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string( 3290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'X-Header: foo; bar="one"; baz=two\n') 3300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_params(header='x-header'), 3310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi [('foo', ''), ('bar', 'one'), ('baz', 'two')]) 3320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_param_liberal(self): 3340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 3350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Content-Type'] = 'Content-Type: Multipart/mixed; boundary = "CPIMSSMTPC06p5f3tG"' 3360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_param('boundary'), 'CPIMSSMTPC06p5f3tG') 3370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_param(self): 3390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 3400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string( 3410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "X-Header: foo=one; bar=two; baz=three\n") 3420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('bar', header='x-header'), 'two') 3430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('quuz', header='x-header'), None) 3440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('quuz'), None) 3450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string( 3460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'X-Header: foo; bar="one"; baz=two\n') 3470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('foo', header='x-header'), '') 3480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('bar', header='x-header'), 'one') 3490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('baz', header='x-header'), 'two') 3500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # XXX: We are not RFC-2045 compliant! We cannot parse: 3510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # msg["Content-Type"] = 'text/plain; weird="hey; dolly? [you] @ <\\"home\\">?"' 3520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # msg.get_param("weird") 3530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # yet. 3540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_param_funky_continuation_lines(self): 3560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_22.txt') 3570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_payload(1).get_param('name'), 'wibble.JPG') 3580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_param_with_semis_in_quotes(self): 3600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string( 3610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'Content-Type: image/pjpeg; name="Jim&&Jill"\n') 3620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_param('name'), 'Jim&&Jill') 3630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_param('name', unquote=False), 3640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi '"Jim&&Jill"') 3650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_param_with_quotes(self): 3670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string( 3680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'Content-Type: foo; bar*0="baz\\"foobar"; bar*1="\\"baz"') 3690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_param('bar'), 'baz"foobar"baz') 3700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string( 3710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "Content-Type: foo; bar*0=\"baz\\\"foobar\"; bar*1=\"\\\"baz\"") 3720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_param('bar'), 'baz"foobar"baz') 3730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_has_key(self): 3750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string('Header: exists') 3760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(msg.has_key('header')) 3770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(msg.has_key('Header')) 3780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(msg.has_key('HEADER')) 3790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(msg.has_key('headeri')) 3800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_set_param(self): 3820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 3830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 3840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_param('charset', 'iso-2022-jp') 3850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('charset'), 'iso-2022-jp') 3860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_param('importance', 'high value') 3870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('importance'), 'high value') 3880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('importance', unquote=False), '"high value"') 3890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_params(), [('text/plain', ''), 3900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('charset', 'iso-2022-jp'), 3910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('importance', 'high value')]) 3920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_params(unquote=False), [('text/plain', ''), 3930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('charset', '"iso-2022-jp"'), 3940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('importance', '"high value"')]) 3950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_param('charset', 'iso-9999-xx', header='X-Jimmy') 3960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('charset', header='X-Jimmy'), 'iso-9999-xx') 3970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 3980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_del_param(self): 3990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 4000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_05.txt') 4010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_params(), 4020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi [('multipart/report', ''), ('report-type', 'delivery-status'), 4030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('boundary', 'D1690A7AC1.996856090/mail.example.com')]) 4040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi old_val = msg.get_param("report-type") 4050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.del_param("report-type") 4060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_params(), 4070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi [('multipart/report', ''), 4080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('boundary', 'D1690A7AC1.996856090/mail.example.com')]) 4090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_param("report-type", old_val) 4100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_params(), 4110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi [('multipart/report', ''), 4120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('boundary', 'D1690A7AC1.996856090/mail.example.com'), 4130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('report-type', old_val)]) 4140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_del_param_on_other_header(self): 4160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 4170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.add_header('Content-Disposition', 'attachment', filename='bud.gif') 4180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.del_param('filename', 'content-disposition') 4190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg['content-disposition'], 'attachment') 4200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_set_type(self): 4220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 4230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 4240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertRaises(ValueError, msg.set_type, 'text') 4250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_type('text/plain') 4260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-type'], 'text/plain') 4270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_param('charset', 'us-ascii') 4280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-type'], 'text/plain; charset="us-ascii"') 4290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_type('text/html') 4300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-type'], 'text/html; charset="us-ascii"') 4310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_set_type_on_other_header(self): 4330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 4340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['X-Content-Type'] = 'text/plain' 4350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_type('application/octet-stream', 'X-Content-Type') 4360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg['x-content-type'], 'application/octet-stream') 4370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_type_missing(self): 4390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 4400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_type(), 'text/plain') 4410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_type_missing_with_default_type(self): 4430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 4440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_default_type('message/rfc822') 4450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_type(), 'message/rfc822') 4460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_type_from_message_implicit(self): 4480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_30.txt') 4490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_payload(0).get_content_type(), 4500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'message/rfc822') 4510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_type_from_message_explicit(self): 4530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_28.txt') 4540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_payload(0).get_content_type(), 4550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'message/rfc822') 4560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_type_from_message_text_plain_implicit(self): 4580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_03.txt') 4590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_type(), 'text/plain') 4600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_type_from_message_text_plain_explicit(self): 4620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_01.txt') 4630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_type(), 'text/plain') 4640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_maintype_missing(self): 4660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 4670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_maintype(), 'text') 4680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_maintype_missing_with_default_type(self): 4700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 4710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_default_type('message/rfc822') 4720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_maintype(), 'message') 4730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_maintype_from_message_implicit(self): 4750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_30.txt') 4760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_payload(0).get_content_maintype(), 'message') 4770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_maintype_from_message_explicit(self): 4790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_28.txt') 4800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_payload(0).get_content_maintype(), 'message') 4810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_maintype_from_message_text_plain_implicit(self): 4830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_03.txt') 4840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_maintype(), 'text') 4850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_maintype_from_message_text_plain_explicit(self): 4870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_01.txt') 4880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_maintype(), 'text') 4890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_subtype_missing(self): 4910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 4920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_subtype(), 'plain') 4930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_subtype_missing_with_default_type(self): 4950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 4960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_default_type('message/rfc822') 4970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_subtype(), 'rfc822') 4980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 4990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_subtype_from_message_implicit(self): 5000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_30.txt') 5010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_payload(0).get_content_subtype(), 'rfc822') 5020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_subtype_from_message_explicit(self): 5040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_28.txt') 5050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_payload(0).get_content_subtype(), 'rfc822') 5060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_subtype_from_message_text_plain_implicit(self): 5080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_03.txt') 5090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_subtype(), 'plain') 5100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_subtype_from_message_text_plain_explicit(self): 5120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_01.txt') 5130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_subtype(), 'plain') 5140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_maintype_error(self): 5160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 5170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Content-Type'] = 'no-slash-in-this-string' 5180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_maintype(), 'text') 5190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_subtype_error(self): 5210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 5220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Content-Type'] = 'no-slash-in-this-string' 5230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_subtype(), 'plain') 5240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_replace_header(self): 5260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 5270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 5280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.add_header('First', 'One') 5290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.add_header('Second', 'Two') 5300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.add_header('Third', 'Three') 5310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.keys(), ['First', 'Second', 'Third']) 5320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.values(), ['One', 'Two', 'Three']) 5330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.replace_header('Second', 'Twenty') 5340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.keys(), ['First', 'Second', 'Third']) 5350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.values(), ['One', 'Twenty', 'Three']) 5360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.add_header('First', 'Eleven') 5370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.replace_header('First', 'One Hundred') 5380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.keys(), ['First', 'Second', 'Third', 'First']) 5390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.values(), ['One Hundred', 'Twenty', 'Three', 'Eleven']) 5400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertRaises(KeyError, msg.replace_header, 'Fourth', 'Missing') 5410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_broken_base64_payload(self): 5430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi x = 'AwDp0P7//y6LwKEAcPa/6Q=9' 5440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 5450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['content-type'] = 'audio/x-midi' 5460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['content-transfer-encoding'] = 'base64' 5470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_payload(x) 5480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_payload(decode=True), x) 5490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_content_charset(self): 5510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 5520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_charset('us-ascii') 5530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual('us-ascii', msg.get_content_charset()) 5540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_charset(u'us-ascii') 5550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual('us-ascii', msg.get_content_charset()) 5560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Issue 5871: reject an attempt to embed a header inside a header value 5580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # (header injection attack). 5590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_embeded_header_via_Header_rejected(self): 5600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 5610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Dummy'] = Header('dummy\nX-Injected-Header: test') 5620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertRaises(Errors.HeaderParseError, msg.as_string) 5630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_embeded_header_via_string_rejected(self): 5650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 5660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Dummy'] = 'dummy\nX-Injected-Header: test' 5670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertRaises(Errors.HeaderParseError, msg.as_string) 5680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Test the email.Encoders module 5710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestEncoders(unittest.TestCase): 5720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_encode_empty_payload(self): 5730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 5740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 5750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_charset('us-ascii') 5760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-transfer-encoding'], '7bit') 5770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_default_cte(self): 5790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 5800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # 7bit data and the default us-ascii _charset 5810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEText('hello world') 5820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-transfer-encoding'], '7bit') 5830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Similar, but with 8bit data 5840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEText('hello \xf8 world') 5850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-transfer-encoding'], '8bit') 5860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # And now with a different charset 5870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEText('hello \xf8 world', _charset='iso-8859-1') 5880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-transfer-encoding'], 'quoted-printable') 5890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_encode7or8bit(self): 5910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Make sure a charset whose input character set is 8bit but 5920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # whose output character set is 7bit gets a transfer-encoding 5930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # of 7bit. 5940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 5950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.MIMEText.MIMEText('\xca\xb8', _charset='euc-jp') 5960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-transfer-encoding'], '7bit') 5970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 5990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Test long header wrapping 6000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestLongHeaders(TestEmailBase): 6010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_split_long_continuation(self): 6020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 6030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string("""\ 6040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: bug demonstration 6050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\t12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 6060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tmore text 6070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yitest 6090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 6100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sfp = StringIO() 6110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = Generator(sfp) 6120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g.flatten(msg) 6130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(sfp.getvalue(), """\ 6140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: bug demonstration 6150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 6160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi more text 6170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yitest 6190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 6200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_another_long_almost_unsplittable_header(self): 6220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 6230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi hstr = """\ 6240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yibug demonstration 6250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\t12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 6260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tmore text""" 6270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header(hstr, continuation_ws='\t') 6280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), """\ 6290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yibug demonstration 6300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\t12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 6310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tmore text""") 6320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header(hstr) 6330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), """\ 6340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yibug demonstration 6350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 6360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi more text""") 6370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_long_nonstring(self): 6390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 6400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = Charset("iso-8859-1") 6410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi cz = Charset("iso-8859-2") 6420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi utf8 = Charset("utf-8") 6430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g_head = "Die Mieter treten hier ein werden mit einem Foerderband komfortabel den Korridor entlang, an s\xfcdl\xfcndischen Wandgem\xe4lden vorbei, gegen die rotierenden Klingen bef\xf6rdert. " 6440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi cz_head = "Finan\xe8ni metropole se hroutily pod tlakem jejich d\xf9vtipu.. " 6450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi utf8_head = u"\u6b63\u78ba\u306b\u8a00\u3046\u3068\u7ffb\u8a33\u306f\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u4e00\u90e8\u306f\u30c9\u30a4\u30c4\u8a9e\u3067\u3059\u304c\u3001\u3042\u3068\u306f\u3067\u305f\u3089\u3081\u3067\u3059\u3002\u5b9f\u969b\u306b\u306f\u300cWenn ist das Nunstuck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput.\u300d\u3068\u8a00\u3063\u3066\u3044\u307e\u3059\u3002".encode("utf-8") 6460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header(g_head, g, header_name='Subject') 6470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h.append(cz_head, cz) 6480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h.append(utf8_head, utf8) 6490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 6500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Subject'] = h 6510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sfp = StringIO() 6520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = Generator(sfp) 6530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g.flatten(msg) 6540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(sfp.getvalue(), """\ 6550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: =?iso-8859-1?q?Die_Mieter_treten_hier_ein_werden_mit_einem_Foerd?= 6560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?erband_komfortabel_den_Korridor_entlang=2C_an_s=FCdl=FCndi?= 6570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?schen_Wandgem=E4lden_vorbei=2C_gegen_die_rotierenden_Kling?= 6580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?en_bef=F6rdert=2E_?= =?iso-8859-2?q?Finan=E8ni_met?= 6590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-2?q?ropole_se_hroutily_pod_tlakem_jejich_d=F9vtipu=2E=2E_?= 6600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?b?5q2j56K644Gr6KiA44GG44Go57+76Kiz44Gv44GV44KM44Gm44GE?= 6610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?b?44G+44Gb44KT44CC5LiA6YOo44Gv44OJ44Kk44OE6Kqe44Gn44GZ44GM44CB?= 6620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?b?44GC44Go44Gv44Gn44Gf44KJ44KB44Gn44GZ44CC5a6f6Zqb44Gr44Gv44CM?= 6630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?q?Wenn_ist_das_Nunstuck_git_und_Slotermeyer=3F_Ja!_Beiherhund_das?= 6640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?b?IE9kZXIgZGllIEZsaXBwZXJ3YWxkdCBnZXJzcHV0LuOAjeOBqOiogOOBow==?= 6650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?b?44Gm44GE44G+44GZ44CC?= 6660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 6680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), """\ 6690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi=?iso-8859-1?q?Die_Mieter_treten_hier_ein_werden_mit_einem_Foerd?= 6700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?erband_komfortabel_den_Korridor_entlang=2C_an_s=FCdl=FCndi?= 6710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?schen_Wandgem=E4lden_vorbei=2C_gegen_die_rotierenden_Kling?= 6720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?en_bef=F6rdert=2E_?= =?iso-8859-2?q?Finan=E8ni_met?= 6730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-2?q?ropole_se_hroutily_pod_tlakem_jejich_d=F9vtipu=2E=2E_?= 6740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?b?5q2j56K644Gr6KiA44GG44Go57+76Kiz44Gv44GV44KM44Gm44GE?= 6750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?b?44G+44Gb44KT44CC5LiA6YOo44Gv44OJ44Kk44OE6Kqe44Gn44GZ44GM44CB?= 6760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?b?44GC44Go44Gv44Gn44Gf44KJ44KB44Gn44GZ44CC5a6f6Zqb44Gr44Gv44CM?= 6770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?q?Wenn_ist_das_Nunstuck_git_und_Slotermeyer=3F_Ja!_Beiherhund_das?= 6780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?b?IE9kZXIgZGllIEZsaXBwZXJ3YWxkdCBnZXJzcHV0LuOAjeOBqOiogOOBow==?= 6790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?b?44Gm44GE44G+44GZ44CC?=""") 6800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_long_header_encode(self): 6820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 6830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header('wasnipoop; giraffes="very-long-necked-animals"; ' 6840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'spooge="yummy"; hippos="gargantuan"; marshmallows="gooey"', 6850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi header_name='X-Foobar-Spoink-Defrobnit') 6860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), '''\ 6870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiwasnipoop; giraffes="very-long-necked-animals"; 6880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi spooge="yummy"; hippos="gargantuan"; marshmallows="gooey"''') 6890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 6900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_long_header_encode_with_tab_continuation(self): 6910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 6920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header('wasnipoop; giraffes="very-long-necked-animals"; ' 6930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'spooge="yummy"; hippos="gargantuan"; marshmallows="gooey"', 6940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi header_name='X-Foobar-Spoink-Defrobnit', 6950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi continuation_ws='\t') 6960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), '''\ 6970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiwasnipoop; giraffes="very-long-necked-animals"; 6980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tspooge="yummy"; hippos="gargantuan"; marshmallows="gooey"''') 6990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 7000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_header_splitter(self): 7010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 7020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEText('') 7030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # It'd be great if we could use add_header() here, but that doesn't 7040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # guarantee an order of the parameters. 7050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['X-Foobar-Spoink-Defrobnit'] = ( 7060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'wasnipoop; giraffes="very-long-necked-animals"; ' 7070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'spooge="yummy"; hippos="gargantuan"; marshmallows="gooey"') 7080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sfp = StringIO() 7090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = Generator(sfp) 7100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g.flatten(msg) 7110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(sfp.getvalue(), '''\ 7120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset="us-ascii" 7130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 7140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 7bit 7150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiX-Foobar-Spoink-Defrobnit: wasnipoop; giraffes="very-long-necked-animals"; 7160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi spooge="yummy"; hippos="gargantuan"; marshmallows="gooey" 7170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 7180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''') 7190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 7200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_no_semis_header_splitter(self): 7210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 7220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 7230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['From'] = 'test@dom.ain' 7240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['References'] = SPACE.join(['<%d@dom.ain>' % i for i in range(10)]) 7250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_payload('Test') 7260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sfp = StringIO() 7270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = Generator(sfp) 7280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g.flatten(msg) 7290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(sfp.getvalue(), """\ 7300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: test@dom.ain 7310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiReferences: <0@dom.ain> <1@dom.ain> <2@dom.ain> <3@dom.ain> <4@dom.ain> 7320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi <5@dom.ain> <6@dom.ain> <7@dom.ain> <8@dom.ain> <9@dom.ain> 7330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 7340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTest""") 7350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 7360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_no_split_long_header(self): 7370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 7380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi hstr = 'References: ' + 'x' * 80 7390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header(hstr, continuation_ws='\t') 7400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), """\ 7410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiReferences: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx""") 7420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 7430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_splitting_multiple_long_lines(self): 7440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 7450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi hstr = """\ 7460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom babylon.socal-raves.org (localhost [127.0.0.1]); by babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; for <mailman-admin@babylon.socal-raves.org>; Sat, 2 Feb 2002 17:00:06 -0800 (PST) 7470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfrom babylon.socal-raves.org (localhost [127.0.0.1]); by babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; for <mailman-admin@babylon.socal-raves.org>; Sat, 2 Feb 2002 17:00:06 -0800 (PST) 7480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfrom babylon.socal-raves.org (localhost [127.0.0.1]); by babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; for <mailman-admin@babylon.socal-raves.org>; Sat, 2 Feb 2002 17:00:06 -0800 (PST) 7490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""" 7500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header(hstr, continuation_ws='\t') 7510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), """\ 7520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom babylon.socal-raves.org (localhost [127.0.0.1]); 7530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tby babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; 7540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfor <mailman-admin@babylon.socal-raves.org>; 7550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tSat, 2 Feb 2002 17:00:06 -0800 (PST) 7560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfrom babylon.socal-raves.org (localhost [127.0.0.1]); 7570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tby babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; 7580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfor <mailman-admin@babylon.socal-raves.org>; 7590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tSat, 2 Feb 2002 17:00:06 -0800 (PST) 7600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfrom babylon.socal-raves.org (localhost [127.0.0.1]); 7610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tby babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; 7620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfor <mailman-admin@babylon.socal-raves.org>; 7630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tSat, 2 Feb 2002 17:00:06 -0800 (PST)""") 7640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 7650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_splitting_first_line_only_is_long(self): 7660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 7670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi hstr = """\ 7680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom modemcable093.139-201-24.que.mc.videotron.ca ([24.201.139.93] helo=cthulhu.gerg.ca) 7690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tby kronos.mems-exchange.org with esmtp (Exim 4.05) 7700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tid 17k4h5-00034i-00 7710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfor test@mems-exchange.org; Wed, 28 Aug 2002 11:25:20 -0400""" 7720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header(hstr, maxlinelen=78, header_name='Received', 7730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi continuation_ws='\t') 7740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), """\ 7750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom modemcable093.139-201-24.que.mc.videotron.ca ([24.201.139.93] 7760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\thelo=cthulhu.gerg.ca) 7770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tby kronos.mems-exchange.org with esmtp (Exim 4.05) 7780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tid 17k4h5-00034i-00 7790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfor test@mems-exchange.org; Wed, 28 Aug 2002 11:25:20 -0400""") 7800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 7810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_long_8bit_header(self): 7820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 7830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 7840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header('Britische Regierung gibt', 'iso-8859-1', 7850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi header_name='Subject') 7860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h.append('gr\xfcnes Licht f\xfcr Offshore-Windkraftprojekte') 7870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Subject'] = h 7880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.as_string(), """\ 7890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: =?iso-8859-1?q?Britische_Regierung_gibt?= =?iso-8859-1?q?gr=FCnes?= 7900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?_Licht_f=FCr_Offshore-Windkraftprojekte?= 7910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 7920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 7930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 7940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_long_8bit_header_no_charset(self): 7950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 7960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 7970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Reply-To'] = 'Britische Regierung gibt gr\xfcnes Licht f\xfcr Offshore-Windkraftprojekte <a-very-long-address@example.com>' 7980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.as_string(), """\ 7990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiReply-To: Britische Regierung gibt gr\xfcnes Licht f\xfcr Offshore-Windkraftprojekte <a-very-long-address@example.com> 8000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 8010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 8020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 8030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_long_to_header(self): 8040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 8050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi to = '"Someone Test #A" <someone@eecs.umich.edu>,<someone@eecs.umich.edu>,"Someone Test #B" <someone@umich.edu>, "Someone Test #C" <someone@eecs.umich.edu>, "Someone Test #D" <someone@eecs.umich.edu>' 8060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 8070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['To'] = to 8080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.as_string(0), '''\ 8090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTo: "Someone Test #A" <someone@eecs.umich.edu>, <someone@eecs.umich.edu>, 8100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "Someone Test #B" <someone@umich.edu>, 8110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "Someone Test #C" <someone@eecs.umich.edu>, 8120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "Someone Test #D" <someone@eecs.umich.edu> 8130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 8140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''') 8150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 8160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_long_line_after_append(self): 8170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 8180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = 'This is an example of string which has almost the limit of header length.' 8190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header(s) 8200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h.append('Add another line.') 8210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), """\ 8220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiThis is an example of string which has almost the limit of header length. 8230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Add another line.""") 8240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 8250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_shorter_line_with_append(self): 8260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 8270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = 'This is a shorter line.' 8280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header(s) 8290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h.append('Add another sentence. (Surprise?)') 8300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), 8310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'This is a shorter line. Add another sentence. (Surprise?)') 8320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 8330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_long_field_name(self): 8340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 8350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fn = 'X-Very-Very-Very-Long-Header-Name' 8360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi gs = "Die Mieter treten hier ein werden mit einem Foerderband komfortabel den Korridor entlang, an s\xfcdl\xfcndischen Wandgem\xe4lden vorbei, gegen die rotierenden Klingen bef\xf6rdert. " 8370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header(gs, 'iso-8859-1', header_name=fn) 8380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # BAW: this seems broken because the first line is too long 8390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), """\ 8400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi=?iso-8859-1?q?Die_Mieter_treten_hier_?= 8410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?ein_werden_mit_einem_Foerderband_komfortabel_den_Korridor_?= 8420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?entlang=2C_an_s=FCdl=FCndischen_Wandgem=E4lden_vorbei=2C_g?= 8430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?egen_die_rotierenden_Klingen_bef=F6rdert=2E_?=""") 8440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 8450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_long_received_header(self): 8460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = 'from FOO.TLD (vizworld.acl.foo.tld [123.452.678.9]) by hrothgar.la.mastaler.com (tmda-ofmipd) with ESMTP; Wed, 05 Mar 2003 18:10:18 -0700' 8470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 8480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Received-1'] = Header(h, continuation_ws='\t') 8490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Received-2'] = h 8500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.as_string(), """\ 8510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiReceived-1: from FOO.TLD (vizworld.acl.foo.tld [123.452.678.9]) by 8520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\throthgar.la.mastaler.com (tmda-ofmipd) with ESMTP; 8530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tWed, 05 Mar 2003 18:10:18 -0700 8540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiReceived-2: from FOO.TLD (vizworld.acl.foo.tld [123.452.678.9]) by 8550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi hrothgar.la.mastaler.com (tmda-ofmipd) with ESMTP; 8560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Wed, 05 Mar 2003 18:10:18 -0700 8570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 8580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 8590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 8600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_string_headerinst_eq(self): 8610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = '<15975.17901.207240.414604@sgigritzmann1.mathematik.tu-muenchen.de> (David Bremner\'s message of "Thu, 6 Mar 2003 13:58:21 +0100")' 8620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 8630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Received'] = Header(h, header_name='Received', 8640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi continuation_ws='\t') 8650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Received'] = h 8660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.ndiffAssertEqual(msg.as_string(), """\ 8670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiReceived: <15975.17901.207240.414604@sgigritzmann1.mathematik.tu-muenchen.de> 8680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\t(David Bremner's message of "Thu, 6 Mar 2003 13:58:21 +0100") 8690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiReceived: <15975.17901.207240.414604@sgigritzmann1.mathematik.tu-muenchen.de> 8700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi (David Bremner's message of "Thu, 6 Mar 2003 13:58:21 +0100") 8710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 8720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 8730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 8740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_long_unbreakable_lines_with_continuation(self): 8750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 8760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 8770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi t = """\ 8780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 8790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp""" 8800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Face-1'] = t 8810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Face-2'] = Header(t, header_name='Face-2') 8820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.as_string(), """\ 8830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFace-1: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 8840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp 8850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFace-2: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 8860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp 8870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 8880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 8890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 8900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_another_long_multiline_header(self): 8910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 8920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = '''\ 8930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiReceived: from siimage.com ([172.25.1.3]) by zima.siliconimage.com with Microsoft SMTPSVC(5.0.2195.4905); 8940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Wed, 16 Oct 2002 07:41:11 -0700''' 8950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 8960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.as_string(), '''\ 8970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiReceived: from siimage.com ([172.25.1.3]) by zima.siliconimage.com with 8980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Microsoft SMTPSVC(5.0.2195.4905); Wed, 16 Oct 2002 07:41:11 -0700 8990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''') 9010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_long_lines_with_different_header(self): 9030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 9040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = """\ 9050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiList-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/spamassassin-talk>, 9060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi <mailto:spamassassin-talk-request@lists.sourceforge.net?subject=unsubscribe>""" 9070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 9080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['List'] = h 9090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['List'] = Header(h, header_name='List') 9100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.as_string(), """\ 9110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiList: List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/spamassassin-talk>, 9120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi <mailto:spamassassin-talk-request@lists.sourceforge.net?subject=unsubscribe> 9130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiList: List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/spamassassin-talk>, 9140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi <mailto:spamassassin-talk-request@lists.sourceforge.net?subject=unsubscribe> 9150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 9170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Test mangling of "From " lines in the body of a message 9210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestFromMangling(unittest.TestCase): 9220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def setUp(self): 9230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.msg = Message() 9240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.msg['From'] = 'aaa@bbb.org' 9250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.msg.set_payload("""\ 9260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom the desk of A.A.A.: 9270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiBlah blah blah 9280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 9290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_mangled_from(self): 9310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = StringIO() 9320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = Generator(s, mangle_from_=True) 9330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g.flatten(self.msg) 9340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(s.getvalue(), """\ 9350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: aaa@bbb.org 9360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi>From the desk of A.A.A.: 9380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiBlah blah blah 9390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 9400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_dont_mangle_from(self): 9420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = StringIO() 9430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = Generator(s, mangle_from_=False) 9440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g.flatten(self.msg) 9450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(s.getvalue(), """\ 9460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: aaa@bbb.org 9470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom the desk of A.A.A.: 9490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiBlah blah blah 9500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 9510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_mangle_from_in_preamble_and_epilog(self): 9530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = StringIO() 9540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = Generator(s, mangle_from_=True) 9550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(textwrap.dedent("""\ 9560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi From: foo@bar.com 9570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Mime-Version: 1.0 9580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Content-Type: multipart/mixed; boundary=XXX 9590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi From somewhere unknown 9610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi --XXX 9630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Content-Type: text/plain 9640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi foo 9660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi --XXX-- 9680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi From somewhere unknowable 9700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """)) 9710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g.flatten(msg) 9720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len([1 for x in s.getvalue().split('\n') 9730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if x.startswith('>From ')]), 2) 9740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Test the basic MIMEAudio class 9770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestMIMEAudio(unittest.TestCase): 9780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def setUp(self): 9790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Make sure we pick up the audiotest.au that lives in email/test/data. 9800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # In Python, there's an audiotest.au living in Lib/test but that isn't 9810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # included in some binary distros that don't include the test 9820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # package. The trailing empty string on the .join() is significant 9830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # since findfile() will do a dirname(). 9840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi datadir = os.path.join(os.path.dirname(landmark), 'data', '') 9850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = open(findfile('audiotest.au', datadir), 'rb') 9860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 9870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._audiodata = fp.read() 9880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 9890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 9900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._au = MIMEAudio(self._audiodata) 9910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_guess_minor_type(self): 9930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(self._au.get_content_type(), 'audio/basic') 9940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_encoding(self): 9960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi payload = self._au.get_payload() 9970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(base64.decodestring(payload), self._audiodata) 9980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 9990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_checkSetMinor(self): 10000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi au = MIMEAudio(self._audiodata, 'fish') 10010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(au.get_content_type(), 'audio/fish') 10020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 10030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_add_header(self): 10040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 10050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless = self.assertTrue 10060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._au.add_header('Content-Disposition', 'attachment', 10070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi filename='audiotest.au') 10080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(self._au['content-disposition'], 10090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'attachment; filename="audiotest.au"') 10100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(self._au.get_params(header='content-disposition'), 10110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi [('attachment', ''), ('filename', 'audiotest.au')]) 10120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(self._au.get_param('filename', header='content-disposition'), 10130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'audiotest.au') 10140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi missing = [] 10150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(self._au.get_param('attachment', header='content-disposition'), '') 10160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(self._au.get_param('foo', failobj=missing, 10170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi header='content-disposition') is missing) 10180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Try some missing stuff 10190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(self._au.get_param('foobar', missing) is missing) 10200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(self._au.get_param('attachment', missing, 10210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi header='foobar') is missing) 10220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 10230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 10240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 10250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Test the basic MIMEImage class 10260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestMIMEImage(unittest.TestCase): 10270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def setUp(self): 10280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('PyBanner048.gif') 10290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 10300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._imgdata = fp.read() 10310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 10320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 10330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._im = MIMEImage(self._imgdata) 10340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 10350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_guess_minor_type(self): 10360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(self._im.get_content_type(), 'image/gif') 10370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 10380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_encoding(self): 10390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi payload = self._im.get_payload() 10400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(base64.decodestring(payload), self._imgdata) 10410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 10420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_checkSetMinor(self): 10430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi im = MIMEImage(self._imgdata, 'fish') 10440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(im.get_content_type(), 'image/fish') 10450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 10460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_add_header(self): 10470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 10480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless = self.assertTrue 10490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._im.add_header('Content-Disposition', 'attachment', 10500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi filename='dingusfish.gif') 10510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(self._im['content-disposition'], 10520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'attachment; filename="dingusfish.gif"') 10530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(self._im.get_params(header='content-disposition'), 10540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi [('attachment', ''), ('filename', 'dingusfish.gif')]) 10550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(self._im.get_param('filename', header='content-disposition'), 10560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'dingusfish.gif') 10570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi missing = [] 10580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(self._im.get_param('attachment', header='content-disposition'), '') 10590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(self._im.get_param('foo', failobj=missing, 10600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi header='content-disposition') is missing) 10610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Try some missing stuff 10620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(self._im.get_param('foobar', missing) is missing) 10630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(self._im.get_param('attachment', missing, 10640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi header='foobar') is missing) 10650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 10660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 10670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 10680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Test the basic MIMEText class 10690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestMIMEText(unittest.TestCase): 10700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def setUp(self): 10710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._msg = MIMEText('hello there') 10720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 10730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_types(self): 10740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 10750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless = self.assertTrue 10760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(self._msg.get_content_type(), 'text/plain') 10770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(self._msg.get_param('charset'), 'us-ascii') 10780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi missing = [] 10790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(self._msg.get_param('foobar', missing) is missing) 10800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(self._msg.get_param('charset', missing, header='foobar') 10810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi is missing) 10820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 10830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_payload(self): 10840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(self._msg.get_payload(), 'hello there') 10850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(not self._msg.is_multipart()) 10860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 10870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_charset(self): 10880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 10890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEText('hello there', _charset='us-ascii') 10900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_charset().input_charset, 'us-ascii') 10910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-type'], 'text/plain; charset="us-ascii"') 10920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 10930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_7bit_unicode_input(self): 10940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 10950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEText(u'hello there', _charset='us-ascii') 10960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_charset().input_charset, 'us-ascii') 10970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-type'], 'text/plain; charset="us-ascii"') 10980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 10990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_7bit_unicode_input_no_charset(self): 11000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 11010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEText(u'hello there') 11020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_charset(), 'us-ascii') 11030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-type'], 'text/plain; charset="us-ascii"') 11040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue('hello there' in msg.as_string()) 11050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 11060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_8bit_unicode_input(self): 11070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi teststr = u'\u043a\u0438\u0440\u0438\u043b\u0438\u0446\u0430' 11080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 11090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEText(teststr, _charset='utf-8') 11100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_charset().output_charset, 'utf-8') 11110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-type'], 'text/plain; charset="utf-8"') 11120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(decode=True), teststr.encode('utf-8')) 11130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 11140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_8bit_unicode_input_no_charset(self): 11150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi teststr = u'\u043a\u0438\u0440\u0438\u043b\u0438\u0446\u0430' 11160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertRaises(UnicodeEncodeError, MIMEText, teststr) 11170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 11180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 11190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 11200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Test complicated multipart/* messages 11210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestMultipart(TestEmailBase): 11220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def setUp(self): 11230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('PyBanner048.gif') 11240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 11250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi data = fp.read() 11260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 11270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 11280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 11290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container = MIMEBase('multipart', 'mixed', boundary='BOUNDARY') 11300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi image = MIMEImage(data, name='dingusfish.gif') 11310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi image.add_header('content-disposition', 'attachment', 11320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi filename='dingusfish.gif') 11330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi intro = MIMEText('''\ 11340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiHi there, 11350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 11360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiThis is the dingus fish. 11370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''') 11380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container.attach(intro) 11390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container.attach(image) 11400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container['From'] = 'Barry <barry@digicool.com>' 11410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container['To'] = 'Dingus Lovers <cravindogs@cravindogs.com>' 11420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container['Subject'] = 'Here is your dingus fish' 11430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 11440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi now = 987809702.54848599 11450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi timetuple = time.localtime(now) 11460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if timetuple[-1] == 0: 11470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi tzsecs = time.timezone 11480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 11490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi tzsecs = time.altzone 11500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if tzsecs > 0: 11510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sign = '-' 11520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 11530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sign = '+' 11540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi tzoffset = ' %s%04d' % (sign, tzsecs // 36) 11550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container['Date'] = time.strftime( 11560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi '%a, %d %b %Y %H:%M:%S', 11570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi time.localtime(now)) + tzoffset 11580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._msg = container 11590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._im = image 11600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._txt = intro 11610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 11620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_hierarchy(self): 11630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # convenience 11640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 11650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless = self.assertTrue 11660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi raises = self.assertRaises 11670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # tests 11680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = self._msg 11690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(m.is_multipart()) 11700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(m.get_content_type(), 'multipart/mixed') 11710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(m.get_payload()), 2) 11720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi raises(IndexError, m.get_payload, 2) 11730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m0 = m.get_payload(0) 11740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m1 = m.get_payload(1) 11750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(m0 is self._txt) 11760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(m1 is self._im) 11770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(m.get_payload(), [m0, m1]) 11780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(not m0.is_multipart()) 11790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(not m1.is_multipart()) 11800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 11810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_empty_multipart_idempotent(self): 11820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text = """\ 11830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: multipart/mixed; boundary="BOUNDARY" 11840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 11850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: A subject 11860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTo: aperson@dom.ain 11870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: bperson@dom.ain 11880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 11890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 11900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 11910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 11920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 11930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY-- 11940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""" 11950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Parser().parsestr(text) 11960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.ndiffAssertEqual(text, msg.as_string()) 11970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 11980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_no_parts_in_a_multipart_with_none_epilogue(self): 11990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer = MIMEBase('multipart', 'mixed') 12000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['Subject'] = 'A subject' 12010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['To'] = 'aperson@dom.ain' 12020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['From'] = 'bperson@dom.ain' 12030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.set_boundary('BOUNDARY') 12040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.ndiffAssertEqual(outer.as_string(), '''\ 12050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: multipart/mixed; boundary="BOUNDARY" 12060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 12070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: A subject 12080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTo: aperson@dom.ain 12090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: bperson@dom.ain 12100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 12120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY--''') 12140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_no_parts_in_a_multipart_with_empty_epilogue(self): 12160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer = MIMEBase('multipart', 'mixed') 12170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['Subject'] = 'A subject' 12180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['To'] = 'aperson@dom.ain' 12190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['From'] = 'bperson@dom.ain' 12200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.preamble = '' 12210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.epilogue = '' 12220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.set_boundary('BOUNDARY') 12230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.ndiffAssertEqual(outer.as_string(), '''\ 12240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: multipart/mixed; boundary="BOUNDARY" 12250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 12260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: A subject 12270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTo: aperson@dom.ain 12280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: bperson@dom.ain 12290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 12320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY-- 12340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''') 12350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_one_part_in_a_multipart(self): 12370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 12380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer = MIMEBase('multipart', 'mixed') 12390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['Subject'] = 'A subject' 12400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['To'] = 'aperson@dom.ain' 12410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['From'] = 'bperson@dom.ain' 12420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.set_boundary('BOUNDARY') 12430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEText('hello world') 12440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.attach(msg) 12450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(outer.as_string(), '''\ 12460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: multipart/mixed; boundary="BOUNDARY" 12470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 12480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: A subject 12490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTo: aperson@dom.ain 12500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: bperson@dom.ain 12510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 12530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset="us-ascii" 12540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 12550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 7bit 12560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yihello world 12580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY--''') 12590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_seq_parts_in_a_multipart_with_empty_preamble(self): 12610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 12620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer = MIMEBase('multipart', 'mixed') 12630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['Subject'] = 'A subject' 12640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['To'] = 'aperson@dom.ain' 12650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['From'] = 'bperson@dom.ain' 12660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.preamble = '' 12670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEText('hello world') 12680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.attach(msg) 12690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.set_boundary('BOUNDARY') 12700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(outer.as_string(), '''\ 12710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: multipart/mixed; boundary="BOUNDARY" 12720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 12730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: A subject 12740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTo: aperson@dom.ain 12750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: bperson@dom.ain 12760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 12790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset="us-ascii" 12800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 12810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 7bit 12820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yihello world 12840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY--''') 12850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 12870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_seq_parts_in_a_multipart_with_none_preamble(self): 12880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 12890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer = MIMEBase('multipart', 'mixed') 12900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['Subject'] = 'A subject' 12910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['To'] = 'aperson@dom.ain' 12920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['From'] = 'bperson@dom.ain' 12930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.preamble = None 12940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEText('hello world') 12950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.attach(msg) 12960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.set_boundary('BOUNDARY') 12970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(outer.as_string(), '''\ 12980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: multipart/mixed; boundary="BOUNDARY" 12990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 13000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: A subject 13010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTo: aperson@dom.ain 13020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: bperson@dom.ain 13030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 13040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 13050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset="us-ascii" 13060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 13070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 7bit 13080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 13090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yihello world 13100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY--''') 13110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 13120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 13130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_seq_parts_in_a_multipart_with_none_epilogue(self): 13140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 13150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer = MIMEBase('multipart', 'mixed') 13160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['Subject'] = 'A subject' 13170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['To'] = 'aperson@dom.ain' 13180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['From'] = 'bperson@dom.ain' 13190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.epilogue = None 13200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEText('hello world') 13210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.attach(msg) 13220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.set_boundary('BOUNDARY') 13230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(outer.as_string(), '''\ 13240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: multipart/mixed; boundary="BOUNDARY" 13250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 13260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: A subject 13270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTo: aperson@dom.ain 13280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: bperson@dom.ain 13290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 13300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 13310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset="us-ascii" 13320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 13330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 7bit 13340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 13350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yihello world 13360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY--''') 13370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 13380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 13390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_seq_parts_in_a_multipart_with_empty_epilogue(self): 13400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 13410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer = MIMEBase('multipart', 'mixed') 13420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['Subject'] = 'A subject' 13430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['To'] = 'aperson@dom.ain' 13440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['From'] = 'bperson@dom.ain' 13450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.epilogue = '' 13460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEText('hello world') 13470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.attach(msg) 13480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.set_boundary('BOUNDARY') 13490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(outer.as_string(), '''\ 13500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: multipart/mixed; boundary="BOUNDARY" 13510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 13520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: A subject 13530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTo: aperson@dom.ain 13540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: bperson@dom.ain 13550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 13560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 13570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset="us-ascii" 13580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 13590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 7bit 13600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 13610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yihello world 13620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY-- 13630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''') 13640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 13650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 13660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_seq_parts_in_a_multipart_with_nl_epilogue(self): 13670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 13680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer = MIMEBase('multipart', 'mixed') 13690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['Subject'] = 'A subject' 13700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['To'] = 'aperson@dom.ain' 13710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer['From'] = 'bperson@dom.ain' 13720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.epilogue = '\n' 13730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEText('hello world') 13740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.attach(msg) 13750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer.set_boundary('BOUNDARY') 13760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(outer.as_string(), '''\ 13770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: multipart/mixed; boundary="BOUNDARY" 13780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 13790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: A subject 13800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTo: aperson@dom.ain 13810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: bperson@dom.ain 13820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 13830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 13840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset="us-ascii" 13850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 13860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 7bit 13870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 13880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yihello world 13890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY-- 13900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 13910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''') 13920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 13930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_message_external_body(self): 13940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 13950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_36.txt') 13960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(msg.get_payload()), 2) 13970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg1 = msg.get_payload(1) 13980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg1.get_content_type(), 'multipart/alternative') 13990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(msg1.get_payload()), 2) 14000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for subpart in msg1.get_payload(): 14010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subpart.get_content_type(), 'message/external-body') 14020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(subpart.get_payload()), 1) 14030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi subsubpart = subpart.get_payload(0) 14040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subsubpart.get_content_type(), 'text/plain') 14050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_double_boundary(self): 14070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # msg_37.txt is a multipart that contains two dash-boundary's in a 14080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # row. Our interpretation of RFC 2046 calls for ignoring the second 14090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # and subsequent boundaries. 14100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_37.txt') 14110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(msg.get_payload()), 3) 14120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_nested_inner_contains_outer_boundary(self): 14140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 14150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # msg_38.txt has an inner part that contains outer boundaries. My 14160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # interpretation of RFC 2046 (based on sections 5.1 and 5.1.2) say 14170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # these are illegal and should be interpreted as unterminated inner 14180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # parts. 14190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_38.txt') 14200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sfp = StringIO() 14210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Iterators._structure(msg, sfp) 14220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(sfp.getvalue(), """\ 14230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yimultipart/mixed 14240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi multipart/mixed 14250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi multipart/alternative 14260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 14270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 14280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 14290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 14300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 14310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_nested_with_same_boundary(self): 14330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 14340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # msg 39.txt is similarly evil in that it's got inner parts that use 14350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # the same boundary as outer parts. Again, I believe the way this is 14360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # parsed is closest to the spirit of RFC 2046 14370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_39.txt') 14380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sfp = StringIO() 14390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Iterators._structure(msg, sfp) 14400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(sfp.getvalue(), """\ 14410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yimultipart/mixed 14420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi multipart/mixed 14430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi multipart/alternative 14440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi application/octet-stream 14450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi application/octet-stream 14460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 14470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 14480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_boundary_in_non_multipart(self): 14500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_40.txt') 14510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.as_string(), '''\ 14520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 14530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/html; boundary="--961284236552522269" 14540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi----961284236552522269 14560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/html; 14570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 7Bit 14580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi<html></html> 14600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi----961284236552522269-- 14620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''') 14630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_boundary_with_leading_space(self): 14650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 14660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string('''\ 14670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 14680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: multipart/mixed; boundary=" XXXX" 14690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi-- XXXX 14710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain 14720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi-- XXXX 14750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain 14760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi-- XXXX-- 14780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''') 14790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(msg.is_multipart()) 14800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_boundary(), ' XXXX') 14810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(msg.get_payload()), 2) 14820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_boundary_without_trailing_newline(self): 14840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = Parser().parsestr("""\ 14850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: multipart/mixed; boundary="===============0012394164==" 14860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 14870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--===============0012394164== 14890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: image/file1.jpg 14900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 14910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: base64 14920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiYXNkZg== 14940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--===============0012394164==--""") 14950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(m.get_payload(0).get_payload(), 'YXNkZg==') 14960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 14990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Test some badly formatted messages 15000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestNonConformant(TestEmailBase): 15010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_parse_missing_minor_type(self): 15020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 15030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_14.txt') 15040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_type(), 'text/plain') 15050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_maintype(), 'text') 15060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_subtype(), 'plain') 15070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 15080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_same_boundary_inner_outer(self): 15090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless = self.assertTrue 15100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_15.txt') 15110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # XXX We can probably eventually do better 15120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi inner = msg.get_payload(0) 15130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(hasattr(inner, 'defects')) 15140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(inner.defects), 1) 15150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(inner.defects[0], 15160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Errors.StartBoundaryNotFoundDefect)) 15170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 15180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_multipart_no_boundary(self): 15190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless = self.assertTrue 15200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_25.txt') 15210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(msg.get_payload(), str)) 15220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(msg.defects), 2) 15230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(msg.defects[0], Errors.NoBoundaryInMultipartDefect)) 15240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(msg.defects[1], 15250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Errors.MultipartInvariantViolationDefect)) 15260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 15270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_invalid_content_type(self): 15280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 15290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi neq = self.ndiffAssertEqual 15300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 15310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # RFC 2045, $5.2 says invalid yields text/plain 15320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Content-Type'] = 'text' 15330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_maintype(), 'text') 15340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_subtype(), 'plain') 15350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_type(), 'text/plain') 15360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Clear the old value and try something /really/ invalid 15370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del msg['content-type'] 15380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Content-Type'] = 'foo' 15390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_maintype(), 'text') 15400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_subtype(), 'plain') 15410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_type(), 'text/plain') 15420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Still, make sure that the message is idempotently generated 15430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = StringIO() 15440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = Generator(s) 15450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g.flatten(msg) 15460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi neq(s.getvalue(), 'Content-Type: foo\n\n') 15470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 15480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_no_start_boundary(self): 15490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 15500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_31.txt') 15510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(), """\ 15520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 15530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain 15540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 15550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yimessage 1 15560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 15570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 15580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain 15590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 15600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yimessage 2 15610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 15620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY-- 15630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 15640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 15650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_no_separating_blank_line(self): 15660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 15670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_35.txt') 15680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.as_string(), """\ 15690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: aperson@dom.ain 15700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTo: bperson@dom.ain 15710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: here's something interesting 15720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 15730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yicounter to RFC 2822, there's no separating newline here 15740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 15750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 15760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_lying_multipart(self): 15770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless = self.assertTrue 15780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_41.txt') 15790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(hasattr(msg, 'defects')) 15800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(msg.defects), 2) 15810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(msg.defects[0], Errors.NoBoundaryInMultipartDefect)) 15820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(msg.defects[1], 15830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Errors.MultipartInvariantViolationDefect)) 15840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 15850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_missing_start_boundary(self): 15860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outer = self._msgobj('msg_42.txt') 15870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # The message structure is: 15880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # 15890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # multipart/mixed 15900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # text/plain 15910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # message/rfc822 15920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # multipart/mixed [*] 15930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # 15940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # [*] This message is missing its start boundary 15950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi bad = outer.get_payload(1).get_payload(0) 15960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(len(bad.defects), 1) 15970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(isinstance(bad.defects[0], 15980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Errors.StartBoundaryNotFoundDefect)) 15990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 16000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_first_line_is_continuation_header(self): 16010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 16020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = ' Line 1\nLine 2\nLine 3' 16030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 16040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.keys(), []) 16050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(), 'Line 2\nLine 3') 16060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(msg.defects), 1) 16070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(isinstance(msg.defects[0], 16080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Errors.FirstHeaderLineIsContinuationDefect)) 16090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.defects[0].line, ' Line 1\n') 16100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 16110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 16120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 16130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 16140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Test RFC 2047 header encoding and decoding 16150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestRFC2047(unittest.TestCase): 16160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2047_multiline(self): 16170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 16180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = """Re: =?mac-iceland?q?r=8Aksm=9Arg=8Cs?= baz 16190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi foo bar =?mac-iceland?q?r=8Aksm=9Arg=8Cs?=""" 16200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dh = decode_header(s) 16210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(dh, [ 16220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('Re:', None), 16230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('r\x8aksm\x9arg\x8cs', 'mac-iceland'), 16240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('baz foo bar', None), 16250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('r\x8aksm\x9arg\x8cs', 'mac-iceland')]) 16260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(str(make_header(dh)), 16270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """Re: =?mac-iceland?q?r=8Aksm=9Arg=8Cs?= baz foo bar 16280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?mac-iceland?q?r=8Aksm=9Arg=8Cs?=""") 16290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 16300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_whitespace_eater_unicode(self): 16310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 16320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = '=?ISO-8859-1?Q?Andr=E9?= Pirard <pirard@dom.ain>' 16330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dh = decode_header(s) 16340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(dh, [('Andr\xe9', 'iso-8859-1'), ('Pirard <pirard@dom.ain>', None)]) 16350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi hu = unicode(make_header(dh)).encode('latin-1') 16360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(hu, 'Andr\xe9 Pirard <pirard@dom.ain>') 16370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 16380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_whitespace_eater_unicode_2(self): 16390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 16400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = 'The =?iso-8859-1?b?cXVpY2sgYnJvd24gZm94?= jumped over the =?iso-8859-1?b?bGF6eSBkb2c=?=' 16410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dh = decode_header(s) 16420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(dh, [('The', None), ('quick brown fox', 'iso-8859-1'), 16430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('jumped over the', None), ('lazy dog', 'iso-8859-1')]) 16440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi hu = make_header(dh).__unicode__() 16450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(hu, u'The quick brown fox jumped over the lazy dog') 16460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 16470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2047_without_whitespace(self): 16480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = 'Sm=?ISO-8859-1?B?9g==?=rg=?ISO-8859-1?B?5Q==?=sbord' 16490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dh = decode_header(s) 16500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(dh, [(s, None)]) 16510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 16520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2047_with_whitespace(self): 16530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = 'Sm =?ISO-8859-1?B?9g==?= rg =?ISO-8859-1?B?5Q==?= sbord' 16540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dh = decode_header(s) 16550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(dh, [('Sm', None), ('\xf6', 'iso-8859-1'), 16560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('rg', None), ('\xe5', 'iso-8859-1'), 16570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('sbord', None)]) 16580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 16590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2047_B_bad_padding(self): 16600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = '=?iso-8859-1?B?%s?=' 16610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi data = [ # only test complete bytes 16620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('dm==', 'v'), ('dm=', 'v'), ('dm', 'v'), 16630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('dmk=', 'vi'), ('dmk', 'vi') 16640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ] 16650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for q, a in data: 16660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dh = decode_header(s % q) 16670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(dh, [(a, 'iso-8859-1')]) 16680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 16690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2047_Q_invalid_digits(self): 16700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # issue 10004. 16710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = '=?iso-8659-1?Q?andr=e9=zz?=' 16720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(decode_header(s), 16730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi [(b'andr\xe9=zz', 'iso-8659-1')]) 16740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 16750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 16760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Test the MIMEMessage class 16770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestMIMEMessage(TestEmailBase): 16780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def setUp(self): 16790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('msg_11.txt') 16800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 16810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._text = fp.read() 16820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 16830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 16840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 16850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_type_error(self): 16860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertRaises(TypeError, MIMEMessage, 'a plain string') 16870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 16880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_valid_argument(self): 16890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 16900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless = self.assertTrue 16910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi subject = 'A sub-message' 16920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = Message() 16930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m['Subject'] = subject 16940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi r = MIMEMessage(m) 16950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(r.get_content_type(), 'message/rfc822') 16960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi payload = r.get_payload() 16970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(payload, list)) 16980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(payload), 1) 16990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi subpart = payload[0] 17000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(subpart is m) 17010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subpart['subject'], subject) 17020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 17030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_bad_multipart(self): 17040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 17050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg1 = Message() 17060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg1['Subject'] = 'subpart 1' 17070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg2 = Message() 17080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg2['Subject'] = 'subpart 2' 17090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi r = MIMEMessage(msg1) 17100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertRaises(Errors.MultipartConversionError, r.attach, msg2) 17110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 17120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_generate(self): 17130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # First craft the message to be encapsulated 17140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = Message() 17150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m['Subject'] = 'An enclosed message' 17160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m.set_payload('Here is the body of the message.\n') 17170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi r = MIMEMessage(m) 17180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi r['Subject'] = 'The enclosing message' 17190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = StringIO() 17200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = Generator(s) 17210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g.flatten(r) 17220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(s.getvalue(), """\ 17230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: message/rfc822 17240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 17250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: The enclosing message 17260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 17270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: An enclosed message 17280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 17290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiHere is the body of the message. 17300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 17310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 17320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_parse_message_rfc822(self): 17330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 17340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless = self.assertTrue 17350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_11.txt') 17360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_type(), 'message/rfc822') 17370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi payload = msg.get_payload() 17380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(payload, list)) 17390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(payload), 1) 17400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi submsg = payload[0] 17410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(isinstance(submsg, Message)) 17420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(submsg['subject'], 'An enclosed message') 17430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(submsg.get_payload(), 'Here is the body of the message.\n') 17440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 17450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_dsn(self): 17460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 17470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless = self.assertTrue 17480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # msg 16 is a Delivery Status Notification, see RFC 1894 17490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_16.txt') 17500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_type(), 'multipart/report') 17510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(msg.is_multipart()) 17520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(msg.get_payload()), 3) 17530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Subpart 1 is a text/plain, human readable section 17540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi subpart = msg.get_payload(0) 17550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subpart.get_content_type(), 'text/plain') 17560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subpart.get_payload(), """\ 17570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiThis report relates to a message you sent with the following header fields: 17580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 17590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Message-id: <002001c144a6$8752e060$56104586@oxy.edu> 17600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Date: Sun, 23 Sep 2001 20:10:55 -0700 17610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi From: "Ian T. Henry" <henryi@oxy.edu> 17620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi To: SoCal Raves <scr@socal-raves.org> 17630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Subject: [scr] yeah for Ians!! 17640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 17650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiYour message cannot be delivered to the following recipients: 17660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 17670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Recipient address: jangel1@cougar.noc.ucla.edu 17680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Reason: recipient reached disk quota 17690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 17700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 17710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Subpart 2 contains the machine parsable DSN information. It 17720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # consists of two blocks of headers, represented by two nested Message 17730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # objects. 17740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi subpart = msg.get_payload(1) 17750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subpart.get_content_type(), 'message/delivery-status') 17760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(subpart.get_payload()), 2) 17770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # message/delivery-status should treat each block as a bunch of 17780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # headers, i.e. a bunch of Message objects. 17790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dsn1 = subpart.get_payload(0) 17800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(dsn1, Message)) 17810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(dsn1['original-envelope-id'], '0GK500B4HD0888@cougar.noc.ucla.edu') 17820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(dsn1.get_param('dns', header='reporting-mta'), '') 17830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Try a missing one <wink> 17840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(dsn1.get_param('nsd', header='reporting-mta'), None) 17850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi dsn2 = subpart.get_payload(1) 17860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(dsn2, Message)) 17870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(dsn2['action'], 'failed') 17880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(dsn2.get_params(header='original-recipient'), 17890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi [('rfc822', ''), ('jangel1@cougar.noc.ucla.edu', '')]) 17900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(dsn2.get_param('rfc822', header='final-recipient'), '') 17910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Subpart 3 is the original message 17920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi subpart = msg.get_payload(2) 17930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subpart.get_content_type(), 'message/rfc822') 17940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi payload = subpart.get_payload() 17950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(payload, list)) 17960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(payload), 1) 17970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi subsubpart = payload[0] 17980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(subsubpart, Message)) 17990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subsubpart.get_content_type(), 'text/plain') 18000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subsubpart['message-id'], 18010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi '<002001c144a6$8752e060$56104586@oxy.edu>') 18020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 18030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_epilogue(self): 18040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 18050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('msg_21.txt') 18060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 18070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text = fp.read() 18080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 18090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 18100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 18110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['From'] = 'aperson@dom.ain' 18120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['To'] = 'bperson@dom.ain' 18130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Subject'] = 'Test' 18140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.preamble = 'MIME message' 18150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.epilogue = 'End of MIME message\n' 18160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg1 = MIMEText('One') 18170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg2 = MIMEText('Two') 18180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.add_header('Content-Type', 'multipart/mixed', boundary='BOUNDARY') 18190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.attach(msg1) 18200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.attach(msg2) 18210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sfp = StringIO() 18220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = Generator(sfp) 18230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g.flatten(msg) 18240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(sfp.getvalue(), text) 18250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 18260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_no_nl_preamble(self): 18270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 18280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 18290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['From'] = 'aperson@dom.ain' 18300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['To'] = 'bperson@dom.ain' 18310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Subject'] = 'Test' 18320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.preamble = 'MIME message' 18330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.epilogue = '' 18340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg1 = MIMEText('One') 18350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg2 = MIMEText('Two') 18360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.add_header('Content-Type', 'multipart/mixed', boundary='BOUNDARY') 18370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.attach(msg1) 18380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.attach(msg2) 18390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.as_string(), """\ 18400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: aperson@dom.ain 18410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTo: bperson@dom.ain 18420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: Test 18430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: multipart/mixed; boundary="BOUNDARY" 18440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 18450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME message 18460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 18470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset="us-ascii" 18480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 18490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 7bit 18500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 18510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiOne 18520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 18530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset="us-ascii" 18540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 18550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 7bit 18560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 18570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTwo 18580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY-- 18590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 18600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 18610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_default_type(self): 18620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 18630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('msg_30.txt') 18640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 18650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_file(fp) 18660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 18670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 18680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container1 = msg.get_payload(0) 18690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(container1.get_default_type(), 'message/rfc822') 18700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(container1.get_content_type(), 'message/rfc822') 18710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container2 = msg.get_payload(1) 18720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(container2.get_default_type(), 'message/rfc822') 18730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(container2.get_content_type(), 'message/rfc822') 18740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container1a = container1.get_payload(0) 18750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(container1a.get_default_type(), 'text/plain') 18760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(container1a.get_content_type(), 'text/plain') 18770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container2a = container2.get_payload(0) 18780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(container2a.get_default_type(), 'text/plain') 18790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(container2a.get_content_type(), 'text/plain') 18800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 18810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_default_type_with_explicit_container_type(self): 18820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 18830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('msg_28.txt') 18840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 18850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_file(fp) 18860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 18870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 18880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container1 = msg.get_payload(0) 18890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(container1.get_default_type(), 'message/rfc822') 18900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(container1.get_content_type(), 'message/rfc822') 18910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container2 = msg.get_payload(1) 18920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(container2.get_default_type(), 'message/rfc822') 18930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(container2.get_content_type(), 'message/rfc822') 18940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container1a = container1.get_payload(0) 18950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(container1a.get_default_type(), 'text/plain') 18960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(container1a.get_content_type(), 'text/plain') 18970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container2a = container2.get_payload(0) 18980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(container2a.get_default_type(), 'text/plain') 18990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(container2a.get_content_type(), 'text/plain') 19000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_default_type_non_parsed(self): 19020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 19030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi neq = self.ndiffAssertEqual 19040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Set up container 19050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container = MIMEMultipart('digest', 'BOUNDARY') 19060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container.epilogue = '' 19070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Set up subparts 19080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi subpart1a = MIMEText('message 1\n') 19090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi subpart2a = MIMEText('message 2\n') 19100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi subpart1 = MIMEMessage(subpart1a) 19110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi subpart2 = MIMEMessage(subpart2a) 19120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container.attach(subpart1) 19130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi container.attach(subpart2) 19140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subpart1.get_content_type(), 'message/rfc822') 19150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subpart1.get_default_type(), 'message/rfc822') 19160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subpart2.get_content_type(), 'message/rfc822') 19170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subpart2.get_default_type(), 'message/rfc822') 19180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi neq(container.as_string(0), '''\ 19190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: multipart/digest; boundary="BOUNDARY" 19200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 19210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 19230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: message/rfc822 19240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 19250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset="us-ascii" 19270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 19280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 7bit 19290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yimessage 1 19310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 19330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: message/rfc822 19340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 19350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset="us-ascii" 19370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 19380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 7bit 19390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yimessage 2 19410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY-- 19430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''') 19440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del subpart1['content-type'] 19450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del subpart1['mime-version'] 19460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del subpart2['content-type'] 19470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del subpart2['mime-version'] 19480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subpart1.get_content_type(), 'message/rfc822') 19490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subpart1.get_default_type(), 'message/rfc822') 19500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subpart2.get_content_type(), 'message/rfc822') 19510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subpart2.get_default_type(), 'message/rfc822') 19520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi neq(container.as_string(0), '''\ 19530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: multipart/digest; boundary="BOUNDARY" 19540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 19550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 19570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset="us-ascii" 19590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 19600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 7bit 19610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yimessage 1 19630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY 19650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset="us-ascii" 19670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 19680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 7bit 19690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yimessage 2 19710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi--BOUNDARY-- 19730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''') 19740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_mime_attachments_in_constructor(self): 19760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 19770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text1 = MIMEText('') 19780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text2 = MIMEText('') 19790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEMultipart(_subparts=(text1, text2)) 19800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(msg.get_payload()), 2) 19810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(0), text1) 19820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(1), text2) 19830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_default_multipart_constructor(self): 19850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = MIMEMultipart() 19860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(msg.is_multipart()) 19870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 19890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# A general test of parser->model->generator idempotency. IOW, read a message 19900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# in, parse it into a message object tree, then without touching the tree, 19910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# regenerate the plain text. The original text and the transformed text 19920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# should be identical. Note: that we ignore the Unix-From since that may 19930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# contain a changed date. 19940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestIdempotent(TestEmailBase): 19950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def _msgobj(self, filename): 19960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile(filename) 19970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 19980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi data = fp.read() 19990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 20000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 20010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(data) 20020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return msg, data 20030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def _idempotent(self, msg, text): 20050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 20060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = StringIO() 20070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = Generator(s, maxheaderlen=0) 20080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g.flatten(msg) 20090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(text, s.getvalue()) 20100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_parse_text_message(self): 20120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 20130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_01.txt') 20140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_type(), 'text/plain') 20150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_maintype(), 'text') 20160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_subtype(), 'plain') 20170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_params()[1], ('charset', 'us-ascii')) 20180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('charset'), 'us-ascii') 20190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.preamble, None) 20200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.epilogue, None) 20210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_parse_untyped_message(self): 20240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 20250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_03.txt') 20260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_type(), 'text/plain') 20270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_params(), None) 20280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('charset'), None) 20290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_simple_multipart(self): 20320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_04.txt') 20330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_MIME_digest(self): 20360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_02.txt') 20370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_long_header(self): 20400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_27.txt') 20410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_MIME_digest_with_part_headers(self): 20440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_28.txt') 20450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_mixed_with_image(self): 20480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_06.txt') 20490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_multipart_report(self): 20520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_05.txt') 20530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_dsn(self): 20560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_16.txt') 20570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_preamble_epilogue(self): 20600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_21.txt') 20610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_multipart_one_part(self): 20640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_23.txt') 20650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_multipart_no_parts(self): 20680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_24.txt') 20690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_no_start_boundary(self): 20720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_31.txt') 20730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_charset(self): 20760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_32.txt') 20770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_more_rfc2231_parameters(self): 20800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_33.txt') 20810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_text_plain_in_a_multipart_digest(self): 20840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_34.txt') 20850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_nested_multipart_mixeds(self): 20880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_12a.txt') 20890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_message_external_body_idempotent(self): 20920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_36.txt') 20930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._idempotent(msg, text) 20940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 20950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_content_type(self): 20960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 20970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless = self.assertTrue 20980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Get a message object and reset the seek pointer for other tests 20990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_05.txt') 21000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_type(), 'multipart/report') 21010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test the Content-Type: parameters 21020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi params = {} 21030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for pk, pv in msg.get_params(): 21040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi params[pk] = pv 21050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(params['report-type'], 'delivery-status') 21060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(params['boundary'], 'D1690A7AC1.996856090/mail.example.com') 21070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.preamble, 'This is a MIME-encapsulated message.\n') 21080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.epilogue, '\n') 21090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(msg.get_payload()), 3) 21100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Make sure the subparts are what we expect 21110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg1 = msg.get_payload(0) 21120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg1.get_content_type(), 'text/plain') 21130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg1.get_payload(), 'Yadda yadda yadda\n') 21140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg2 = msg.get_payload(1) 21150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg2.get_content_type(), 'text/plain') 21160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg2.get_payload(), 'Yadda yadda yadda\n') 21170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg3 = msg.get_payload(2) 21180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg3.get_content_type(), 'message/rfc822') 21190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(isinstance(msg3, Message)) 21200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi payload = msg3.get_payload() 21210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(payload, list)) 21220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(payload), 1) 21230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg4 = payload[0] 21240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(msg4, Message)) 21250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg4.get_payload(), 'Yadda yadda yadda\n') 21260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 21270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_parser(self): 21280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 21290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless = self.assertTrue 21300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg, text = self._msgobj('msg_06.txt') 21310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Check some of the outer headers 21320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_type(), 'message/rfc822') 21330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Make sure the payload is a list of exactly one sub-Message, and that 21340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # that submessage has a type of text/plain 21350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi payload = msg.get_payload() 21360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(payload, list)) 21370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(payload), 1) 21380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg1 = payload[0] 21390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(isinstance(msg1, Message)) 21400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg1.get_content_type(), 'text/plain') 21410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(isinstance(msg1.get_payload(), str)) 21420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg1.get_payload(), '\n') 21430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 21440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 21450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 21460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Test various other bits of the package's functionality 21470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestMiscellaneous(TestEmailBase): 21480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_message_from_string(self): 21490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('msg_01.txt') 21500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 21510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text = fp.read() 21520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 21530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 21540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(text) 21550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = StringIO() 21560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Don't wrap/continue long headers since we're trying to test 21570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # idempotency. 21580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = Generator(s, maxheaderlen=0) 21590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g.flatten(msg) 21600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(text, s.getvalue()) 21610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 21620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_message_from_file(self): 21630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('msg_01.txt') 21640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 21650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text = fp.read() 21660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.seek(0) 21670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_file(fp) 21680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = StringIO() 21690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Don't wrap/continue long headers since we're trying to test 21700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # idempotency. 21710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = Generator(s, maxheaderlen=0) 21720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g.flatten(msg) 21730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(text, s.getvalue()) 21740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 21750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 21760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 21770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_message_from_string_with_class(self): 21780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless = self.assertTrue 21790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('msg_01.txt') 21800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 21810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text = fp.read() 21820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 21830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 21840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Create a subclass 21850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class MyMessage(Message): 21860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 21870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 21880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(text, MyMessage) 21890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(msg, MyMessage)) 21900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Try something more complicated 21910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('msg_02.txt') 21920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 21930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text = fp.read() 21940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 21950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 21960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(text, MyMessage) 21970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for subpart in msg.walk(): 21980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(subpart, MyMessage)) 21990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 22000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_message_from_file_with_class(self): 22010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless = self.assertTrue 22020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Create a subclass 22030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi class MyMessage(Message): 22040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 22050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 22060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('msg_01.txt') 22070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 22080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_file(fp, MyMessage) 22090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 22100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 22110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(msg, MyMessage)) 22120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Try something more complicated 22130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('msg_02.txt') 22140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 22150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_file(fp, MyMessage) 22160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 22170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 22180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for subpart in msg.walk(): 22190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unless(isinstance(subpart, MyMessage)) 22200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 22210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test__all__(self): 22220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi module = __import__('email') 22230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi all = module.__all__ 22240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi all.sort() 22250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(all, [ 22260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Old names 22270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'Charset', 'Encoders', 'Errors', 'Generator', 22280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'Header', 'Iterators', 'MIMEAudio', 'MIMEBase', 22290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'MIMEImage', 'MIMEMessage', 'MIMEMultipart', 22300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'MIMENonMultipart', 'MIMEText', 'Message', 22310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'Parser', 'Utils', 'base64MIME', 22320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # new names 22330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'base64mime', 'charset', 'encoders', 'errors', 'generator', 22340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'header', 'iterators', 'message', 'message_from_file', 22350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'message_from_string', 'mime', 'parser', 22360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'quopriMIME', 'quoprimime', 'utils', 22370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ]) 22380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 22390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_formatdate(self): 22400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi now = time.time() 22410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(Utils.parsedate(Utils.formatdate(now))[:6], 22420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi time.gmtime(now)[:6]) 22430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 22440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_formatdate_localtime(self): 22450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi now = time.time() 22460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual( 22470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Utils.parsedate(Utils.formatdate(now, localtime=True))[:6], 22480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi time.localtime(now)[:6]) 22490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 22500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_formatdate_usegmt(self): 22510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi now = time.time() 22520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual( 22530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Utils.formatdate(now, localtime=False), 22540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi time.strftime('%a, %d %b %Y %H:%M:%S -0000', time.gmtime(now))) 22550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual( 22560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Utils.formatdate(now, localtime=False, usegmt=True), 22570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(now))) 22580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 22590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_parsedate_none(self): 22600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(Utils.parsedate(''), None) 22610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 22620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_parsedate_compact(self): 22630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # The FWS after the comma is optional 22640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(Utils.parsedate('Wed,3 Apr 2002 14:58:26 +0800'), 22650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Utils.parsedate('Wed, 3 Apr 2002 14:58:26 +0800')) 22660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 22670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_parsedate_no_dayofweek(self): 22680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 22690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(Utils.parsedate_tz('25 Feb 2003 13:47:26 -0800'), 22700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi (2003, 2, 25, 13, 47, 26, 0, 1, -1, -28800)) 22710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 22720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_parsedate_compact_no_dayofweek(self): 22730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 22740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(Utils.parsedate_tz('5 Feb 2003 13:47:26 -0800'), 22750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi (2003, 2, 5, 13, 47, 26, 0, 1, -1, -28800)) 22760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 22770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_parsedate_acceptable_to_time_functions(self): 22780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 22790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi timetup = Utils.parsedate('5 Feb 2003 13:47:26 -0800') 22800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi t = int(time.mktime(timetup)) 22810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(time.localtime(t)[:6], timetup[:6]) 22820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(int(time.strftime('%Y', timetup)), 2003) 22830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi timetup = Utils.parsedate_tz('5 Feb 2003 13:47:26 -0800') 22840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi t = int(time.mktime(timetup[:9])) 22850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(time.localtime(t)[:6], timetup[:6]) 22860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(int(time.strftime('%Y', timetup[:9])), 2003) 22870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 22880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_mktime_tz(self): 22890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(Utils.mktime_tz((1970, 1, 1, 0, 0, 0, 22900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi -1, -1, -1, 0)), 0) 22910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(Utils.mktime_tz((1970, 1, 1, 0, 0, 0, 22920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi -1, -1, -1, 1234)), -1234) 22930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 22940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_parsedate_y2k(self): 22950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """Test for parsing a date with a two-digit year. 22960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 22970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Parsing a date with a two-digit year should return the correct 22980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi four-digit year. RFC822 allows two-digit years, but RFC2822 (which 22990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi obsoletes RFC822) requires four-digit years. 23000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 23010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """ 23020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(Utils.parsedate_tz('25 Feb 03 13:47:26 -0800'), 23030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Utils.parsedate_tz('25 Feb 2003 13:47:26 -0800')) 23040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(Utils.parsedate_tz('25 Feb 71 13:47:26 -0800'), 23050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Utils.parsedate_tz('25 Feb 1971 13:47:26 -0800')) 23060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 23070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_parseaddr_empty(self): 23080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(Utils.parseaddr('<>'), ('', '')) 23090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(Utils.formataddr(Utils.parseaddr('<>')), '') 23100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 23110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_noquote_dump(self): 23120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual( 23130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Utils.formataddr(('A Silly Person', 'person@dom.ain')), 23140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'A Silly Person <person@dom.ain>') 23150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 23160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_escape_dump(self): 23170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual( 23180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Utils.formataddr(('A (Very) Silly Person', 'person@dom.ain')), 23190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi r'"A \(Very\) Silly Person" <person@dom.ain>') 23200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a = r'A \(Special\) Person' 23210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi b = 'person@dom.ain' 23220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(Utils.parseaddr(Utils.formataddr((a, b))), (a, b)) 23230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 23240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_escape_backslashes(self): 23250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual( 23260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Utils.formataddr(('Arthur \Backslash\ Foobar', 'person@dom.ain')), 23270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi r'"Arthur \\Backslash\\ Foobar" <person@dom.ain>') 23280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a = r'Arthur \Backslash\ Foobar' 23290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi b = 'person@dom.ain' 23300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(Utils.parseaddr(Utils.formataddr((a, b))), (a, b)) 23310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 23320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_name_with_dot(self): 23330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi x = 'John X. Doe <jxd@example.com>' 23340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi y = '"John X. Doe" <jxd@example.com>' 23350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi a, b = ('John X. Doe', 'jxd@example.com') 23360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(Utils.parseaddr(x), (a, b)) 23370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(Utils.parseaddr(y), (a, b)) 23380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # formataddr() quotes the name if there's a dot in it 23390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(Utils.formataddr((a, b)), y) 23400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 23410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_parseaddr_preserves_quoted_pairs_in_addresses(self): 23420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # issue 10005. Note that in the third test the second pair of 23430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # backslashes is not actually a quoted pair because it is not inside a 23440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # comment or quoted string: the address being parsed has a quoted 23450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # string containing a quoted backslash, followed by 'example' and two 23460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # backslashes, followed by another quoted string containing a space and 23470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # the word 'example'. parseaddr copies those two backslashes 23480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # literally. Per rfc5322 this is not technically correct since a \ may 23490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # not appear in an address outside of a quoted string. It is probably 23500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # a sensible Postel interpretation, though. 23510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 23520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(Utils.parseaddr('""example" example"@example.com'), 23530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('', '""example" example"@example.com')) 23540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(Utils.parseaddr('"\\"example\\" example"@example.com'), 23550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('', '"\\"example\\" example"@example.com')) 23560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(Utils.parseaddr('"\\\\"example\\\\" example"@example.com'), 23570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('', '"\\\\"example\\\\" example"@example.com')) 23580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 23590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_multiline_from_comment(self): 23600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi x = """\ 23610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFoo 23620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tBar <foo@example.com>""" 23630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(Utils.parseaddr(x), ('Foo Bar', 'foo@example.com')) 23640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 23650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_quote_dump(self): 23660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual( 23670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Utils.formataddr(('A Silly; Person', 'person@dom.ain')), 23680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi r'"A Silly; Person" <person@dom.ain>') 23690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 23700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_fix_eols(self): 23710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 23720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(Utils.fix_eols('hello'), 'hello') 23730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(Utils.fix_eols('hello\n'), 'hello\r\n') 23740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(Utils.fix_eols('hello\r'), 'hello\r\n') 23750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(Utils.fix_eols('hello\r\n'), 'hello\r\n') 23760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(Utils.fix_eols('hello\n\r'), 'hello\r\n\r\n') 23770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 23780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_charset_richcomparisons(self): 23790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 23800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ne = self.assertNotEqual 23810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi cset1 = Charset() 23820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi cset2 = Charset() 23830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(cset1, 'us-ascii') 23840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(cset1, 'US-ASCII') 23850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(cset1, 'Us-AsCiI') 23860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq('us-ascii', cset1) 23870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq('US-ASCII', cset1) 23880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq('Us-AsCiI', cset1) 23890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ne(cset1, 'usascii') 23900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ne(cset1, 'USASCII') 23910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ne(cset1, 'UsAsCiI') 23920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ne('usascii', cset1) 23930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ne('USASCII', cset1) 23940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ne('UsAsCiI', cset1) 23950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(cset1, cset2) 23960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(cset2, cset1) 23970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 23980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_getaddresses(self): 23990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 24000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(Utils.getaddresses(['aperson@dom.ain (Al Person)', 24010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'Bud Person <bperson@dom.ain>']), 24020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi [('Al Person', 'aperson@dom.ain'), 24030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('Bud Person', 'bperson@dom.ain')]) 24040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 24050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_getaddresses_nasty(self): 24060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 24070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(Utils.getaddresses(['foo: ;']), [('', '')]) 24080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(Utils.getaddresses( 24090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ['[]*-- =~$']), 24100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi [('', ''), ('', ''), ('', '*--')]) 24110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(Utils.getaddresses( 24120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ['foo: ;', '"Jason R. Mastaler" <jason@dom.ain>']), 24130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]) 24140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 24150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_getaddresses_embedded_comment(self): 24160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """Test proper handling of a nested comment""" 24170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 24180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi addrs = Utils.getaddresses(['User ((nested comment)) <foo@bar.com>']) 24190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(addrs[0][1], 'foo@bar.com') 24200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 24210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_utils_quote_unquote(self): 24220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 24230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 24240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.add_header('content-disposition', 'attachment', 24250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi filename='foo\\wacky"name') 24260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_filename(), 'foo\\wacky"name') 24270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 24280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_body_encoding_with_bogus_charset(self): 24290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charset = Charset('not a charset') 24300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(charset.get_body_encoding(), 'base64') 24310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 24320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_body_encoding_with_uppercase_charset(self): 24330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 24340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 24350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Content-Type'] = 'text/plain; charset=UTF-8' 24360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-type'], 'text/plain; charset=UTF-8') 24370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charsets = msg.get_charsets() 24380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(charsets), 1) 24390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(charsets[0], 'utf-8') 24400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charset = Charset(charsets[0]) 24410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(charset.get_body_encoding(), 'base64') 24420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_payload('hello world', charset=charset) 24430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(), 'aGVsbG8gd29ybGQ=\n') 24440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(decode=True), 'hello world') 24450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-transfer-encoding'], 'base64') 24460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Try another one 24470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 24480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Content-Type'] = 'text/plain; charset="US-ASCII"' 24490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charsets = msg.get_charsets() 24500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(charsets), 1) 24510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(charsets[0], 'us-ascii') 24520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charset = Charset(charsets[0]) 24530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(charset.get_body_encoding(), Encoders.encode_7or8bit) 24540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_payload('hello world', charset=charset) 24550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(), 'hello world') 24560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['content-transfer-encoding'], '7bit') 24570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 24580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_charsets_case_insensitive(self): 24590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi lc = Charset('us-ascii') 24600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi uc = Charset('US-ASCII') 24610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(lc.get_body_encoding(), uc.get_body_encoding()) 24620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 24630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_partial_falls_inside_message_delivery_status(self): 24640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 24650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # The Parser interface provides chunks of data to FeedParser in 8192 24660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # byte gulps. SF bug #1076485 found one of those chunks inside 24670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # message/delivery-status header block, which triggered an 24680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # unreadline() of NeedMoreData. 24690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_43.txt') 24700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sfp = StringIO() 24710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Iterators._structure(msg, sfp) 24720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(sfp.getvalue(), """\ 24730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yimultipart/report 24740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi message/delivery-status 24760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 24990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 25000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 25010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/plain 25020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi text/rfc822-headers 25030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 25040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 25050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 25060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 25070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Test the iterator/generators 25080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestIterators(TestEmailBase): 25090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_body_line_iterator(self): 25100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 25110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi neq = self.ndiffAssertEqual 25120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # First a simple non-multipart message 25130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_01.txt') 25140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi it = Iterators.body_line_iterator(msg) 25150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi lines = list(it) 25160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(lines), 6) 25170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi neq(EMPTYSTRING.join(lines), msg.get_payload()) 25180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Now a more complicated multipart 25190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_02.txt') 25200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi it = Iterators.body_line_iterator(msg) 25210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi lines = list(it) 25220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(lines), 43) 25230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('msg_19.txt') 25240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 25250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi neq(EMPTYSTRING.join(lines), fp.read()) 25260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 25270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 25280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 25290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_typed_subpart_iterator(self): 25300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 25310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_04.txt') 25320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi it = Iterators.typed_subpart_iterator(msg, 'text') 25330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi lines = [] 25340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi subparts = 0 25350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for subpart in it: 25360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi subparts += 1 25370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi lines.append(subpart.get_payload()) 25380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subparts, 2) 25390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(EMPTYSTRING.join(lines), """\ 25400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yia simple kind of mirror 25410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yito reflect upon our own 25420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yia simple kind of mirror 25430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yito reflect upon our own 25440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 25450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 25460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_typed_subpart_iterator_default_type(self): 25470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 25480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_03.txt') 25490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi it = Iterators.typed_subpart_iterator(msg, 'text', 'plain') 25500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi lines = [] 25510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi subparts = 0 25520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for subpart in it: 25530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi subparts += 1 25540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi lines.append(subpart.get_payload()) 25550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(subparts, 1) 25560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(EMPTYSTRING.join(lines), """\ 25570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 25580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiHi, 25590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 25600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiDo you like this message? 25610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 25620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi-Me 25630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 25640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 25650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_pushCR_LF(self): 25660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi '''FeedParser BufferedSubFile.push() assumed it received complete 25670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi line endings. A CR ending one push() followed by a LF starting 25680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi the next push() added an empty line. 25690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ''' 25700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi imt = [ 25710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ("a\r \n", 2), 25720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ("b", 0), 25730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ("c\n", 1), 25740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ("", 0), 25750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ("d\r\n", 1), 25760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ("e\r", 0), 25770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ("\nf", 1), 25780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ("\r\n", 1), 25790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ] 25800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi from email.feedparser import BufferedSubFile, NeedMoreData 25810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi bsf = BufferedSubFile() 25820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi om = [] 25830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi nt = 0 25840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for il, n in imt: 25850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi bsf.push(il) 25860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi nt += n 25870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi n1 = 0 25880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi while True: 25890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ol = bsf.readline() 25900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if ol == NeedMoreData: 25910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi break 25920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi om.append(ol) 25930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi n1 += 1 25940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(n == n1) 25950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(len(om) == nt) 25960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(''.join([il for il, n in imt]) == ''.join(om)) 25970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 25980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 25990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 26000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestParsers(TestEmailBase): 26010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_header_parser(self): 26020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 26030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Parse only the headers of a complex multipart MIME document 26040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('msg_02.txt') 26050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 26060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = HeaderParser().parse(fp) 26070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 26080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 26090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['from'], 'ppp-request@zzz.org') 26100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['to'], 'ppp@zzz.org') 26110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_type(), 'multipart/mixed') 26120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(msg.is_multipart()) 26130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(isinstance(msg.get_payload(), str)) 26140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 26150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_whitespace_continuation(self): 26160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 26170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # This message contains a line after the Subject: header that has only 26180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # whitespace, but it is not empty! 26190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string("""\ 26200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: aperson@dom.ain 26210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTo: bperson@dom.ain 26220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: the next line has a space on it 26230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\x20 26240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiDate: Mon, 8 Apr 2002 15:09:19 -0400 26250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMessage-ID: spam 26260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 26270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiHere's the message body 26280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 26290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['subject'], 'the next line has a space on it\n ') 26300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['message-id'], 'spam') 26310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(), "Here's the message body\n") 26320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 26330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_whitespace_continuation_last_header(self): 26340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 26350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Like the previous test, but the subject line is the last 26360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # header. 26370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string("""\ 26380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: aperson@dom.ain 26390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTo: bperson@dom.ain 26400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiDate: Mon, 8 Apr 2002 15:09:19 -0400 26410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMessage-ID: spam 26420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: the next line has a space on it 26430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\x20 26440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 26450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiHere's the message body 26460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 26470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['subject'], 'the next line has a space on it\n ') 26480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg['message-id'], 'spam') 26490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(), "Here's the message body\n") 26500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 26510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_crlf_separation(self): 26520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 26530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('msg_26.txt', mode='rb') 26540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 26550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Parser().parse(fp) 26560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 26570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 26580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(msg.get_payload()), 2) 26590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi part1 = msg.get_payload(0) 26600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(part1.get_content_type(), 'text/plain') 26610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(part1.get_payload(), 'Simple email with attachment.\r\n\r\n') 26620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi part2 = msg.get_payload(1) 26630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(part2.get_content_type(), 'application/riscos') 26640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 26650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_multipart_digest_with_extra_mime_headers(self): 26660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 26670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi neq = self.ndiffAssertEqual 26680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile('msg_28.txt') 26690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 26700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_file(fp) 26710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 26720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 26730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Structure is: 26740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # multipart/digest 26750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # message/rfc822 26760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # text/plain 26770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # message/rfc822 26780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # text/plain 26790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.is_multipart(), 1) 26800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(msg.get_payload()), 2) 26810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi part1 = msg.get_payload(0) 26820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(part1.get_content_type(), 'message/rfc822') 26830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(part1.is_multipart(), 1) 26840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(part1.get_payload()), 1) 26850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi part1a = part1.get_payload(0) 26860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(part1a.is_multipart(), 0) 26870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(part1a.get_content_type(), 'text/plain') 26880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi neq(part1a.get_payload(), 'message 1\n') 26890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # next message/rfc822 26900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi part2 = msg.get_payload(1) 26910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(part2.get_content_type(), 'message/rfc822') 26920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(part2.is_multipart(), 1) 26930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(part2.get_payload()), 1) 26940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi part2a = part2.get_payload(0) 26950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(part2a.is_multipart(), 0) 26960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(part2a.get_content_type(), 'text/plain') 26970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi neq(part2a.get_payload(), 'message 2\n') 26980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 26990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_three_lines(self): 27000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # A bug report by Andrew McNamara 27010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi lines = ['From: Andrew Person <aperson@dom.ain', 27020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'Subject: Test', 27030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'Date: Tue, 20 Aug 2002 16:43:45 +1000'] 27040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(NL.join(lines)) 27050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg['date'], 'Tue, 20 Aug 2002 16:43:45 +1000') 27060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 27070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_strip_line_feed_and_carriage_return_in_headers(self): 27080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 27090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # For [ 1002475 ] email message parser doesn't handle \r\n correctly 27100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi value1 = 'text' 27110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi value2 = 'more text' 27120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = 'Header: %s\r\nNext-Header: %s\r\n\r\nBody\r\n\r\n' % ( 27130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi value1, value2) 27140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 27150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get('Header'), value1) 27160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get('Next-Header'), value2) 27170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 27180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2822_header_syntax(self): 27190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 27200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = '>From: foo\nFrom: bar\n!"#QUX;~: zoo\n\nbody' 27210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 27220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(msg.keys()), 3) 27230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi keys = msg.keys() 27240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi keys.sort() 27250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(keys, ['!"#QUX;~', '>From', 'From']) 27260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(), 'body') 27270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 27280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2822_space_not_allowed_in_header(self): 27290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 27300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = '>From foo@example.com 11:25:53\nFrom: bar\n!"#QUX;~: zoo\n\nbody' 27310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 27320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(len(msg.keys()), 0) 27330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 27340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2822_one_character_header(self): 27350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 27360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = 'A: first header\nB: second header\nCC: third header\n\nbody' 27370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 27380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi headers = msg.keys() 27390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi headers.sort() 27400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(headers, ['A', 'B', 'CC']) 27410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_payload(), 'body') 27420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 27430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_CRLFLF_at_end_of_part(self): 27440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # issue 5610: feedparser should not eat two chars from body part ending 27450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # with "\r\n\n". 27460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = ( 27470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "From: foo@bar.com\n" 27480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "To: baz\n" 27490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "Mime-Version: 1.0\n" 27500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "Content-Type: multipart/mixed; boundary=BOUNDARY\n" 27510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "\n" 27520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "--BOUNDARY\n" 27530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "Content-Type: text/plain\n" 27540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "\n" 27550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "body ending with CRLF newline\r\n" 27560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "\n" 27570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi "--BOUNDARY--\n" 27580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ) 27590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 27600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(msg.get_payload(0).get_payload().endswith('\r\n')) 27610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 27620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 27630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestBase64(unittest.TestCase): 27640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_len(self): 27650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 27660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(base64MIME.base64_len('hello'), 27670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi len(base64MIME.encode('hello', eol=''))) 27680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for size in range(15): 27690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if size == 0 : bsize = 0 27700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi elif size <= 3 : bsize = 4 27710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi elif size <= 6 : bsize = 8 27720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi elif size <= 9 : bsize = 12 27730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi elif size <= 12: bsize = 16 27740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else : bsize = 20 27750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(base64MIME.base64_len('x'*size), bsize) 27760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 27770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_decode(self): 27780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 27790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(base64MIME.decode(''), '') 27800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(base64MIME.decode('aGVsbG8='), 'hello') 27810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(base64MIME.decode('aGVsbG8=', 'X'), 'hello') 27820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(base64MIME.decode('aGVsbG8NCndvcmxk\n', 'X'), 'helloXworld') 27830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 27840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_encode(self): 27850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 27860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(base64MIME.encode(''), '') 27870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(base64MIME.encode('hello'), 'aGVsbG8=\n') 27880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test the binary flag 27890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(base64MIME.encode('hello\n'), 'aGVsbG8K\n') 27900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(base64MIME.encode('hello\n', 0), 'aGVsbG8NCg==\n') 27910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test the maxlinelen arg 27920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(base64MIME.encode('xxxx ' * 20, maxlinelen=40), """\ 27930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YieHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg 27940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YieHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg 27950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YieHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg 27960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YieHh4eCB4eHh4IA== 27970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 27980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test the eol argument 27990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(base64MIME.encode('xxxx ' * 20, maxlinelen=40, eol='\r\n'), """\ 28000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YieHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg\r 28010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YieHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg\r 28020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YieHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg\r 28030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YieHh4eCB4eHh4IA==\r 28040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 28050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 28060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_header_encode(self): 28070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 28080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi he = base64MIME.header_encode 28090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(he('hello'), '=?iso-8859-1?b?aGVsbG8=?=') 28100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(he('hello\nworld'), '=?iso-8859-1?b?aGVsbG8NCndvcmxk?=') 28110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test the charset option 28120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(he('hello', charset='iso-8859-2'), '=?iso-8859-2?b?aGVsbG8=?=') 28130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test the keep_eols flag 28140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(he('hello\nworld', keep_eols=True), 28150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi '=?iso-8859-1?b?aGVsbG8Kd29ybGQ=?=') 28160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test the maxlinelen argument 28170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(he('xxxx ' * 20, maxlinelen=40), """\ 28180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi=?iso-8859-1?b?eHh4eCB4eHh4IHh4eHggeHg=?= 28190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?b?eHggeHh4eCB4eHh4IHh4eHg=?= 28200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?b?IHh4eHggeHh4eCB4eHh4IHg=?= 28210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?b?eHh4IHh4eHggeHh4eCB4eHg=?= 28220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?b?eCB4eHh4IHh4eHggeHh4eCA=?= 28230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?b?eHh4eCB4eHh4IHh4eHgg?=""") 28240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test the eol argument 28250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(he('xxxx ' * 20, maxlinelen=40, eol='\r\n'), """\ 28260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi=?iso-8859-1?b?eHh4eCB4eHh4IHh4eHggeHg=?=\r 28270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?b?eHggeHh4eCB4eHh4IHh4eHg=?=\r 28280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?b?IHh4eHggeHh4eCB4eHh4IHg=?=\r 28290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?b?eHh4IHh4eHggeHh4eCB4eHg=?=\r 28300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?b?eCB4eHh4IHh4eHggeHh4eCA=?=\r 28310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?b?eHh4eCB4eHh4IHh4eHgg?=""") 28320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 28330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 28340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 28350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestQuopri(unittest.TestCase): 28360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def setUp(self): 28370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.hlit = [chr(x) for x in range(ord('a'), ord('z')+1)] + \ 28380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi [chr(x) for x in range(ord('A'), ord('Z')+1)] + \ 28390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi [chr(x) for x in range(ord('0'), ord('9')+1)] + \ 28400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ['!', '*', '+', '-', '/', ' '] 28410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.hnon = [chr(x) for x in range(256) if chr(x) not in self.hlit] 28420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi assert len(self.hlit) + len(self.hnon) == 256 28430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.blit = [chr(x) for x in range(ord(' '), ord('~')+1)] + ['\t'] 28440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.blit.remove('=') 28450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.bnon = [chr(x) for x in range(256) if chr(x) not in self.blit] 28460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi assert len(self.blit) + len(self.bnon) == 256 28470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 28480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_header_quopri_check(self): 28490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for c in self.hlit: 28500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(quopriMIME.header_quopri_check(c)) 28510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for c in self.hnon: 28520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(quopriMIME.header_quopri_check(c)) 28530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 28540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_body_quopri_check(self): 28550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for c in self.blit: 28560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(quopriMIME.body_quopri_check(c)) 28570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for c in self.bnon: 28580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(quopriMIME.body_quopri_check(c)) 28590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 28600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_header_quopri_len(self): 28610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 28620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi hql = quopriMIME.header_quopri_len 28630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi enc = quopriMIME.header_encode 28640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for s in ('hello', 'h@e@l@l@o@'): 28650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Empty charset and no line-endings. 7 == RFC chrome 28660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(hql(s), len(enc(s, charset='', eol=''))-7) 28670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for c in self.hlit: 28680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(hql(c), 1) 28690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for c in self.hnon: 28700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(hql(c), 3) 28710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 28720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_body_quopri_len(self): 28730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 28740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi bql = quopriMIME.body_quopri_len 28750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for c in self.blit: 28760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(bql(c), 1) 28770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for c in self.bnon: 28780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(bql(c), 3) 28790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 28800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_quote_unquote_idempotent(self): 28810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for x in range(256): 28820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c = chr(x) 28830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(quopriMIME.unquote(quopriMIME.quote(c)), c) 28840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 28850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_header_encode(self): 28860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 28870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi he = quopriMIME.header_encode 28880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(he('hello'), '=?iso-8859-1?q?hello?=') 28890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(he('hello\nworld'), '=?iso-8859-1?q?hello=0D=0Aworld?=') 28900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test the charset option 28910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(he('hello', charset='iso-8859-2'), '=?iso-8859-2?q?hello?=') 28920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test the keep_eols flag 28930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(he('hello\nworld', keep_eols=True), '=?iso-8859-1?q?hello=0Aworld?=') 28940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test a non-ASCII character 28950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(he('hello\xc7there'), '=?iso-8859-1?q?hello=C7there?=') 28960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test the maxlinelen argument 28970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(he('xxxx ' * 20, maxlinelen=40), """\ 28980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi=?iso-8859-1?q?xxxx_xxxx_xxxx_xxxx_xx?= 28990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?xx_xxxx_xxxx_xxxx_xxxx?= 29000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?_xxxx_xxxx_xxxx_xxxx_x?= 29010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?xxx_xxxx_xxxx_xxxx_xxx?= 29020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?x_xxxx_xxxx_?=""") 29030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test the eol argument 29040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(he('xxxx ' * 20, maxlinelen=40, eol='\r\n'), """\ 29050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi=?iso-8859-1?q?xxxx_xxxx_xxxx_xxxx_xx?=\r 29060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?xx_xxxx_xxxx_xxxx_xxxx?=\r 29070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?_xxxx_xxxx_xxxx_xxxx_x?=\r 29080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?xxx_xxxx_xxxx_xxxx_xxx?=\r 29090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?x_xxxx_xxxx_?=""") 29100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 29110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_decode(self): 29120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 29130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(quopriMIME.decode(''), '') 29140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(quopriMIME.decode('hello'), 'hello') 29150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(quopriMIME.decode('hello', 'X'), 'hello') 29160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(quopriMIME.decode('hello\nworld', 'X'), 'helloXworld') 29170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 29180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_encode(self): 29190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 29200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(quopriMIME.encode(''), '') 29210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(quopriMIME.encode('hello'), 'hello') 29220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test the binary flag 29230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(quopriMIME.encode('hello\r\nworld'), 'hello\nworld') 29240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(quopriMIME.encode('hello\r\nworld', 0), 'hello\nworld') 29250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test the maxlinelen arg 29260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(quopriMIME.encode('xxxx ' * 20, maxlinelen=40), """\ 29270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yixxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx= 29280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxx= 29290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yix xxxx xxxx xxxx xxxx=20""") 29300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test the eol argument 29310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(quopriMIME.encode('xxxx ' * 20, maxlinelen=40, eol='\r\n'), """\ 29320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yixxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx=\r 29330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxx=\r 29340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yix xxxx xxxx xxxx xxxx=20""") 29350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(quopriMIME.encode("""\ 29360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yione line 29370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 29380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yitwo line"""), """\ 29390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yione line 29400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 29410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yitwo line""") 29420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 29430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 29440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 29450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Test the Charset class 29460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestCharset(unittest.TestCase): 29470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def tearDown(self): 29480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi from email import Charset as CharsetModule 29490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 29500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi del CharsetModule.CHARSETS['fake'] 29510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi except KeyError: 29520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 29530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 29540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_idempotent(self): 29550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 29560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Make sure us-ascii = no Unicode conversion 29570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c = Charset('us-ascii') 29580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = 'Hello World!' 29590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sp = c.to_splittable(s) 29600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(s, c.from_splittable(sp)) 29610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # test 8-bit idempotency with us-ascii 29620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = '\xa4\xa2\xa4\xa4\xa4\xa6\xa4\xa8\xa4\xaa' 29630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sp = c.to_splittable(s) 29640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(s, c.from_splittable(sp)) 29650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 29660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_body_encode(self): 29670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 29680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Try a charset with QP body encoding 29690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c = Charset('iso-8859-1') 29700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq('hello w=F6rld', c.body_encode('hello w\xf6rld')) 29710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Try a charset with Base64 body encoding 29720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c = Charset('utf-8') 29730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq('aGVsbG8gd29ybGQ=\n', c.body_encode('hello world')) 29740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Try a charset with None body encoding 29750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c = Charset('us-ascii') 29760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq('hello world', c.body_encode('hello world')) 29770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Try the convert argument, where input codec != output codec 29780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c = Charset('euc-jp') 29790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # With apologies to Tokio Kikuchi ;) 29800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 29810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq('\x1b$B5FCO;~IW\x1b(B', 29820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c.body_encode('\xb5\xc6\xc3\xcf\xbb\xfe\xc9\xd7')) 29830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq('\xb5\xc6\xc3\xcf\xbb\xfe\xc9\xd7', 29840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c.body_encode('\xb5\xc6\xc3\xcf\xbb\xfe\xc9\xd7', False)) 29850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi except LookupError: 29860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # We probably don't have the Japanese codecs installed 29870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 29880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Testing SF bug #625509, which we have to fake, since there are no 29890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # built-in encodings where the header encoding is QP but the body 29900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # encoding is not. 29910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi from email import Charset as CharsetModule 29920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi CharsetModule.add_charset('fake', CharsetModule.QP, None) 29930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi c = Charset('fake') 29940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq('hello w\xf6rld', c.body_encode('hello w\xf6rld')) 29950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 29960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_unicode_charset_name(self): 29970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charset = Charset(u'us-ascii') 29980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(str(charset), 'us-ascii') 29990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertRaises(Errors.CharsetError, Charset, 'asc\xffii') 30000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 30010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_codecs_aliases_accepted(self): 30020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charset = Charset('utf8') 30030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(str(charset), 'utf-8') 30040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 30050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 30060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Test multilingual MIME headers. 30070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestHeader(TestEmailBase): 30080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_simple(self): 30090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 30100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header('Hello World!') 30110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), 'Hello World!') 30120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h.append(' Goodbye World!') 30130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), 'Hello World! Goodbye World!') 30140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 30150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_simple_surprise(self): 30160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 30170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header('Hello World!') 30180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), 'Hello World!') 30190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h.append('Goodbye World!') 30200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), 'Hello World! Goodbye World!') 30210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 30220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_header_needs_no_decoding(self): 30230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = 'no decoding needed' 30240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(decode_header(h), [(h, None)]) 30250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 30260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_long(self): 30270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header("I am the very model of a modern Major-General; I've information vegetable, animal, and mineral; I know the kings of England, and I quote the fights historical from Marathon to Waterloo, in order categorical; I'm very well acquainted, too, with matters mathematical; I understand equations, both the simple and quadratical; about binomial theorem I'm teeming with a lot o' news, with many cheerful facts about the square of the hypotenuse.", 30280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi maxlinelen=76) 30290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for l in h.encode(splitchars=' ').split('\n '): 30300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertTrue(len(l) <= 76) 30310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 30320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_multilingual(self): 30330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 30340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g = Charset("iso-8859-1") 30350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi cz = Charset("iso-8859-2") 30360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi utf8 = Charset("utf-8") 30370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi g_head = "Die Mieter treten hier ein werden mit einem Foerderband komfortabel den Korridor entlang, an s\xfcdl\xfcndischen Wandgem\xe4lden vorbei, gegen die rotierenden Klingen bef\xf6rdert. " 30380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi cz_head = "Finan\xe8ni metropole se hroutily pod tlakem jejich d\xf9vtipu.. " 30390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi utf8_head = u"\u6b63\u78ba\u306b\u8a00\u3046\u3068\u7ffb\u8a33\u306f\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u4e00\u90e8\u306f\u30c9\u30a4\u30c4\u8a9e\u3067\u3059\u304c\u3001\u3042\u3068\u306f\u3067\u305f\u3089\u3081\u3067\u3059\u3002\u5b9f\u969b\u306b\u306f\u300cWenn ist das Nunstuck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput.\u300d\u3068\u8a00\u3063\u3066\u3044\u307e\u3059\u3002".encode("utf-8") 30400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header(g_head, g) 30410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h.append(cz_head, cz) 30420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h.append(utf8_head, utf8) 30430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi enc = h.encode() 30440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(enc, """\ 30450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi=?iso-8859-1?q?Die_Mieter_treten_hier_ein_werden_mit_einem_Foerderband_ko?= 30460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?mfortabel_den_Korridor_entlang=2C_an_s=FCdl=FCndischen_Wan?= 30470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?dgem=E4lden_vorbei=2C_gegen_die_rotierenden_Klingen_bef=F6?= 30480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-1?q?rdert=2E_?= =?iso-8859-2?q?Finan=E8ni_metropole_se_hroutily?= 30490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?iso-8859-2?q?_pod_tlakem_jejich_d=F9vtipu=2E=2E_?= =?utf-8?b?5q2j56K6?= 30500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?b?44Gr6KiA44GG44Go57+76Kiz44Gv44GV44KM44Gm44GE44G+44Gb44KT44CC?= 30510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?b?5LiA6YOo44Gv44OJ44Kk44OE6Kqe44Gn44GZ44GM44CB44GC44Go44Gv44Gn?= 30520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?b?44Gf44KJ44KB44Gn44GZ44CC5a6f6Zqb44Gr44Gv44CMV2VubiBpc3QgZGFz?= 30530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?q?_Nunstuck_git_und_Slotermeyer=3F_Ja!_Beiherhund_das_Oder_die_Fl?= 30540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?b?aXBwZXJ3YWxkdCBnZXJzcHV0LuOAjeOBqOiogOOBo+OBpuOBhOOBvuOBmQ==?= 30550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi =?utf-8?b?44CC?=""") 30560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(decode_header(enc), 30570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi [(g_head, "iso-8859-1"), (cz_head, "iso-8859-2"), 30580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi (utf8_head, "utf-8")]) 30590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ustr = unicode(h) 30600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(ustr.encode('utf-8'), 30610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'Die Mieter treten hier ein werden mit einem Foerderband ' 30620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'komfortabel den Korridor entlang, an s\xc3\xbcdl\xc3\xbcndischen ' 30630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'Wandgem\xc3\xa4lden vorbei, gegen die rotierenden Klingen ' 30640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'bef\xc3\xb6rdert. Finan\xc4\x8dni metropole se hroutily pod ' 30650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'tlakem jejich d\xc5\xafvtipu.. \xe6\xad\xa3\xe7\xa2\xba\xe3\x81' 30660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi '\xab\xe8\xa8\x80\xe3\x81\x86\xe3\x81\xa8\xe7\xbf\xbb\xe8\xa8\xb3' 30670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi '\xe3\x81\xaf\xe3\x81\x95\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x84\xe3' 30680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi '\x81\xbe\xe3\x81\x9b\xe3\x82\x93\xe3\x80\x82\xe4\xb8\x80\xe9\x83' 30690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi '\xa8\xe3\x81\xaf\xe3\x83\x89\xe3\x82\xa4\xe3\x83\x84\xe8\xaa\x9e' 30700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi '\xe3\x81\xa7\xe3\x81\x99\xe3\x81\x8c\xe3\x80\x81\xe3\x81\x82\xe3' 30710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi '\x81\xa8\xe3\x81\xaf\xe3\x81\xa7\xe3\x81\x9f\xe3\x82\x89\xe3\x82' 30720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi '\x81\xe3\x81\xa7\xe3\x81\x99\xe3\x80\x82\xe5\xae\x9f\xe9\x9a\x9b' 30730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi '\xe3\x81\xab\xe3\x81\xaf\xe3\x80\x8cWenn ist das Nunstuck git ' 30740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt ' 30750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'gersput.\xe3\x80\x8d\xe3\x81\xa8\xe8\xa8\x80\xe3\x81\xa3\xe3\x81' 30760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi '\xa6\xe3\x81\x84\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82') 30770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Test make_header() 30780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi newh = make_header(decode_header(enc)) 30790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(newh, enc) 30800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 30810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_header_ctor_default_args(self): 30820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 30830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header() 30840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h, '') 30850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h.append('foo', Charset('iso-8859-1')) 30860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h, '=?iso-8859-1?q?foo?=') 30870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 30880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_explicit_maxlinelen(self): 30890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 30900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi hstr = 'A very long line that must get split to something other than at the 76th character boundary to test the non-default behavior' 30910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header(hstr) 30920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), '''\ 30930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiA very long line that must get split to something other than at the 76th 30940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi character boundary to test the non-default behavior''') 30950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header(hstr, header_name='Subject') 30960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), '''\ 30970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiA very long line that must get split to something other than at the 30980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 76th character boundary to test the non-default behavior''') 30990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header(hstr, maxlinelen=1024, header_name='Subject') 31000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), hstr) 31010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 31020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_us_ascii_header(self): 31030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 31040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = 'hello' 31050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi x = decode_header(s) 31060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(x, [('hello', None)]) 31070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = make_header(x) 31080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(s, h.encode()) 31090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 31100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_string_charset(self): 31110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 31120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header() 31130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h.append('hello', 'iso-8859-1') 31140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h, '=?iso-8859-1?q?hello?=') 31150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 31160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi## def test_unicode_error(self): 31170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi## raises = self.assertRaises 31180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi## raises(UnicodeError, Header, u'[P\xf6stal]', 'us-ascii') 31190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi## raises(UnicodeError, Header, '[P\xf6stal]', 'us-ascii') 31200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi## h = Header() 31210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi## raises(UnicodeError, h.append, u'[P\xf6stal]', 'us-ascii') 31220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi## raises(UnicodeError, h.append, '[P\xf6stal]', 'us-ascii') 31230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi## raises(UnicodeError, Header, u'\u83ca\u5730\u6642\u592b', 'iso-8859-1') 31240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 31250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_utf8_shortest(self): 31260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 31270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header(u'p\xf6stal', 'utf-8') 31280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), '=?utf-8?q?p=C3=B6stal?=') 31290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header(u'\u83ca\u5730\u6642\u592b', 'utf-8') 31300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), '=?utf-8?b?6I+K5Zyw5pmC5aSr?=') 31310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 31320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_bad_8bit_header(self): 31330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi raises = self.assertRaises 31340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 31350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi x = 'Ynwp4dUEbay Auction Semiar- No Charge \x96 Earn Big' 31360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi raises(UnicodeError, Header, x) 31370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header() 31380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi raises(UnicodeError, h.append, x) 31390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(str(Header(x, errors='replace')), x) 31400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h.append(x, errors='replace') 31410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(str(h), x) 31420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 31430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_encoded_adjacent_nonencoded(self): 31440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 31450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = Header() 31460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h.append('hello', 'iso-8859-1') 31470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h.append('world') 31480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = h.encode() 31490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(s, '=?iso-8859-1?q?hello?= world') 31500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi h = make_header(decode_header(s)) 31510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(h.encode(), s) 31520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 31530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_whitespace_eater(self): 31540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 31550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = 'Subject: =?koi8-r?b?8NLP18XSy8EgzsEgxsnOwczYztk=?= =?koi8-r?q?=CA?= zz.' 31560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi parts = decode_header(s) 31570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(parts, [('Subject:', None), ('\xf0\xd2\xcf\xd7\xc5\xd2\xcb\xc1 \xce\xc1 \xc6\xc9\xce\xc1\xcc\xd8\xce\xd9\xca', 'koi8-r'), ('zz.', None)]) 31580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi hdr = make_header(parts) 31590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(hdr.encode(), 31600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'Subject: =?koi8-r?b?8NLP18XSy8EgzsEgxsnOwczYztnK?= zz.') 31610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 31620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_broken_base64_header(self): 31630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi raises = self.assertRaises 31640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi s = 'Subject: =?EUC-KR?B?CSixpLDtKSC/7Liuvsax4iC6uLmwMcijIKHaILzSwd/H0SC8+LCjwLsgv7W/+Mj3I ?=' 31650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi raises(Errors.HeaderParseError, decode_header, s) 31660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 31670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Issue 1078919 31680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_ascii_add_header(self): 31690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 31700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.add_header('Content-Disposition', 'attachment', 31710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi filename='bud.gif') 31720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual('attachment; filename="bud.gif"', 31730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Content-Disposition']) 31740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 31750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_nonascii_add_header_via_triple(self): 31760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 31770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.add_header('Content-Disposition', 'attachment', 31780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi filename=('iso-8859-1', '', 'Fu\xdfballer.ppt')) 31790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual( 31800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'attachment; filename*="iso-8859-1\'\'Fu%DFballer.ppt"', 31810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg['Content-Disposition']) 31820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 31830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_encode_unaliased_charset(self): 31840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Issue 1379416: when the charset has no output conversion, 31850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # output was accidentally getting coerced to unicode. 31860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi res = Header('abc','iso-8859-2').encode() 31870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(res, '=?iso-8859-2?q?abc?=') 31880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertIsInstance(res, str) 31890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 31900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 31910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Test RFC 2231 header parameters (en/de)coding 31920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestRFC2231(TestEmailBase): 31930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_get_param(self): 31940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 31950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_29.txt') 31960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('title'), 31970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('us-ascii', 'en', 'This is even more ***fun*** isn\'t it!')) 31980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('title', unquote=False), 31990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('us-ascii', 'en', '"This is even more ***fun*** isn\'t it!"')) 32000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 32010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_set_param(self): 32020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 32030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = Message() 32040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_param('title', 'This is even more ***fun*** isn\'t it!', 32050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charset='us-ascii') 32060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('title'), 32070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('us-ascii', '', 'This is even more ***fun*** isn\'t it!')) 32080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_param('title', 'This is even more ***fun*** isn\'t it!', 32090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charset='us-ascii', language='en') 32100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('title'), 32110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi ('us-ascii', 'en', 'This is even more ***fun*** isn\'t it!')) 32120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_01.txt') 32130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_param('title', 'This is even more ***fun*** isn\'t it!', 32140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charset='us-ascii', language='en') 32150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.ndiffAssertEqual(msg.as_string(), """\ 32160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiReturn-Path: <bbb@zzz.org> 32170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiDelivered-To: bbb@zzz.org 32180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiReceived: by mail.zzz.org (Postfix, from userid 889) 32190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) 32200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 32210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 7bit 32220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMessage-ID: <15090.61304.110929.45684@aaa.zzz.org> 32230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: bbb@ddd.com (John X. Doe) 32240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTo: bbb@zzz.org 32250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: This is a test message 32260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiDate: Fri, 4 May 2001 14:05:44 -0400 32270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset=us-ascii; 32280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi title*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21" 32290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 32300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 32310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiHi, 32320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 32330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiDo you like this message? 32340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 32350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi-Me 32360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 32370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 32380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_del_param(self): 32390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.ndiffAssertEqual 32400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_01.txt') 32410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_param('foo', 'bar', charset='us-ascii', language='en') 32420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.set_param('title', 'This is even more ***fun*** isn\'t it!', 32430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charset='us-ascii', language='en') 32440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.del_param('foo', header='Content-Type') 32450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.as_string(), """\ 32460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiReturn-Path: <bbb@zzz.org> 32470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiDelivered-To: bbb@zzz.org 32480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiReceived: by mail.zzz.org (Postfix, from userid 889) 32490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) 32500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMIME-Version: 1.0 32510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 7bit 32520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMessage-ID: <15090.61304.110929.45684@aaa.zzz.org> 32530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiFrom: bbb@ddd.com (John X. Doe) 32540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiTo: bbb@zzz.org 32550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSubject: This is a test message 32560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiDate: Fri, 4 May 2001 14:05:44 -0400 32570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset="us-ascii"; 32580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi title*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21" 32590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 32600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 32610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiHi, 32620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 32630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiDo you like this message? 32640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 32650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi-Me 32660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""") 32670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 32680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_get_content_charset(self): 32690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 32700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = self._msgobj('msg_32.txt') 32710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_content_charset(), 'us-ascii') 32720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 32730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_no_language_or_charset(self): 32740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = '''\ 32750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 8bit 32760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Disposition: inline; filename="file____C__DOCUMENTS_20AND_20SETTINGS_FABIEN_LOCAL_20SETTINGS_TEMP_nsmail.htm" 32770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/html; NAME*0=file____C__DOCUMENTS_20AND_20SETTINGS_FABIEN_LOCAL_20SETTINGS_TEM; NAME*1=P_nsmail.htm 32780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 32790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''' 32800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 32810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi param = msg.get_param('NAME') 32820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(isinstance(param, tuple)) 32830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual( 32840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi param, 32850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'file____C__DOCUMENTS_20AND_20SETTINGS_FABIEN_LOCAL_20SETTINGS_TEMP_nsmail.htm') 32860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 32870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_no_language_or_charset_in_filename(self): 32880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = '''\ 32890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Disposition: inline; 32900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*0*="''This%20is%20even%20more%20"; 32910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; 32920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*2="is it not.pdf" 32930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 32940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''' 32950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 32960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_filename(), 32970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'This is even more ***fun*** is it not.pdf') 32980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 32990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_no_language_or_charset_in_filename_encoded(self): 33000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = '''\ 33010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Disposition: inline; 33020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*0*="''This%20is%20even%20more%20"; 33030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; 33040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*2="is it not.pdf" 33050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 33060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''' 33070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 33080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_filename(), 33090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'This is even more ***fun*** is it not.pdf') 33100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 33110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_partly_encoded(self): 33120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = '''\ 33130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Disposition: inline; 33140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*0="''This%20is%20even%20more%20"; 33150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; 33160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*2="is it not.pdf" 33170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 33180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''' 33190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 33200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual( 33210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.get_filename(), 33220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'This%20is%20even%20more%20***fun*** is it not.pdf') 33230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 33240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_partly_nonencoded(self): 33250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = '''\ 33260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Disposition: inline; 33270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*0="This%20is%20even%20more%20"; 33280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*1="%2A%2A%2Afun%2A%2A%2A%20"; 33290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*2="is it not.pdf" 33300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 33310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''' 33320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 33330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual( 33340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg.get_filename(), 33350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20is it not.pdf') 33360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 33370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_no_language_or_charset_in_boundary(self): 33380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = '''\ 33390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: multipart/alternative; 33400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tboundary*0*="''This%20is%20even%20more%20"; 33410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tboundary*1*="%2A%2A%2Afun%2A%2A%2A%20"; 33420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tboundary*2="is it not.pdf" 33430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 33440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''' 33450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 33460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_boundary(), 33470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'This is even more ***fun*** is it not.pdf') 33480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 33490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_no_language_or_charset_in_charset(self): 33500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # This is a nonsensical charset value, but tests the code anyway 33510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = '''\ 33520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; 33530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tcharset*0*="This%20is%20even%20more%20"; 33540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tcharset*1*="%2A%2A%2Afun%2A%2A%2A%20"; 33550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tcharset*2="is it not.pdf" 33560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 33570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''' 33580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 33590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_charset(), 33600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'this is even more ***fun*** is it not.pdf') 33610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 33620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_bad_encoding_in_filename(self): 33630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = '''\ 33640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Disposition: inline; 33650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*0*="bogus'xx'This%20is%20even%20more%20"; 33660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; 33670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*2="is it not.pdf" 33680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 33690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''' 33700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 33710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_filename(), 33720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 'This is even more ***fun*** is it not.pdf') 33730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 33740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_bad_encoding_in_charset(self): 33750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = """\ 33760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset*=bogus''utf-8%E2%80%9D 33770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 33780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""" 33790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 33800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # This should return None because non-ascii characters in the charset 33810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # are not allowed. 33820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_charset(), None) 33830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 33840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_bad_character_in_charset(self): 33850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = """\ 33860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: text/plain; charset*=ascii''utf-8%E2%80%9D 33870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 33880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""" 33890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 33900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # This should return None because non-ascii characters in the charset 33910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # are not allowed. 33920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_content_charset(), None) 33930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 33940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_bad_character_in_filename(self): 33950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = '''\ 33960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Disposition: inline; 33970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*0*="ascii'xx'This%20is%20even%20more%20"; 33980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; 33990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tfilename*2*="is it not.pdf%E2" 34000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi''' 34020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 34030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_filename(), 34040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi u'This is even more ***fun*** is it not.pdf\ufffd') 34050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_unknown_encoding(self): 34070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = """\ 34080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Transfer-Encoding: 8bit 34090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Disposition: inline; filename*=X-UNKNOWN''myfile.txt 34100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""" 34120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 34130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(msg.get_filename(), 'myfile.txt') 34140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_single_tick_in_filename_extended(self): 34160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 34170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = """\ 34180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: application/x-foo; 34190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tname*0*=\"Frank's\"; name*1*=\" Document\" 34200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""" 34220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 34230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charset, language, s = msg.get_param('name') 34240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(charset, None) 34250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(language, None) 34260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(s, "Frank's Document") 34270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_single_tick_in_filename(self): 34290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = """\ 34300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: application/x-foo; name*0=\"Frank's\"; name*1=\" Document\" 34310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""" 34330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 34340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi param = msg.get_param('name') 34350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(isinstance(param, tuple)) 34360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(param, "Frank's Document") 34370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_tick_attack_extended(self): 34390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 34400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = """\ 34410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: application/x-foo; 34420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tname*0*=\"us-ascii'en-us'Frank's\"; name*1*=\" Document\" 34430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""" 34450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 34460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charset, language, s = msg.get_param('name') 34470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(charset, 'us-ascii') 34480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(language, 'en-us') 34490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(s, "Frank's Document") 34500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_tick_attack(self): 34520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = """\ 34530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: application/x-foo; 34540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tname*0=\"us-ascii'en-us'Frank's\"; name*1=\" Document\" 34550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""" 34570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 34580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi param = msg.get_param('name') 34590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertFalse(isinstance(param, tuple)) 34600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(param, "us-ascii'en-us'Frank's Document") 34610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_no_extended_values(self): 34630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 34640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = """\ 34650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: application/x-foo; name=\"Frank's Document\" 34660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""" 34680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 34690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(msg.get_param('name'), "Frank's Document") 34700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_encoded_then_unencoded_segments(self): 34720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 34730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = """\ 34740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: application/x-foo; 34750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tname*0*=\"us-ascii'en-us'My\"; 34760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tname*1=\" Document\"; 34770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tname*2*=\" For You\" 34780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""" 34800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 34810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charset, language, s = msg.get_param('name') 34820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(charset, 'us-ascii') 34830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(language, 'en-us') 34840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(s, 'My Document For You') 34850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_rfc2231_unencoded_then_encoded_segments(self): 34870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq = self.assertEqual 34880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi m = """\ 34890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiContent-Type: application/x-foo; 34900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tname*0=\"us-ascii'en-us'My\"; 34910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tname*1*=\" Document\"; 34920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi\tname*2*=\" For You\" 34930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 34940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""" 34950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(m) 34960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi charset, language, s = msg.get_param('name') 34970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(charset, 'us-ascii') 34980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(language, 'en-us') 34990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi eq(s, 'My Document For You') 35000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# Tests to ensure that signed parts of an email are completely preserved, as 35040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# required by RFC1847 section 2.1. Note that these are incomplete, because the 35050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi# email package does not currently always preserve the body. See issue 1670765. 35060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass TestSigned(TestEmailBase): 35070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def _msg_and_obj(self, filename): 35090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = openfile(findfile(filename)) 35100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 35110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi original = fp.read() 35120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi msg = email.message_from_string(original) 35130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi finally: 35140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp.close() 35150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return original, msg 35160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def _signed_parts_eq(self, original, result): 35180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Extract the first mime part of each message 35190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi import re 35200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi repart = re.compile(r'^--([^\n]+)\n(.*?)\n--\1$', re.S | re.M) 35210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi inpart = repart.search(original).group(2) 35220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi outpart = repart.search(result).group(2) 35230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.assertEqual(outpart, inpart) 35240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_long_headers_as_string(self): 35260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi original, msg = self._msg_and_obj('msg_45.txt') 35270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi result = msg.as_string() 35280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._signed_parts_eq(original, result) 35290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_long_headers_flatten(self): 35310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi original, msg = self._msg_and_obj('msg_45.txt') 35320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fp = StringIO() 35330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Generator(fp).flatten(msg) 35340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi result = fp.getvalue() 35350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._signed_parts_eq(original, result) 35360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef _testclasses(): 35400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi mod = sys.modules[__name__] 35410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')] 35420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef suite(): 35450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi suite = unittest.TestSuite() 35460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for testclass in _testclasses(): 35470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi suite.addTest(unittest.makeSuite(testclass)) 35480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return suite 35490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef test_main(): 35520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for testclass in _testclasses(): 35530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi run_unittest(testclass) 35540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 35570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiif __name__ == '__main__': 35580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unittest.main(defaultTest='suite') 3559