14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Copyright (C) 2001-2010 Python Software Foundation 24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Contact: email-sig@python.org 34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# email package unit tests 44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport os 64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport sys 74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport time 84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport base64 94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport difflib 104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport unittest 114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport warnings 124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom cStringIO import StringIO 134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport email 154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email.Charset import Charset 174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email.Header import Header, decode_header, make_header 184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email.Parser import Parser, HeaderParser 194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email.Generator import Generator, DecodedGenerator 204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email.Message import Message 214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email.MIMEAudio import MIMEAudio 224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email.MIMEText import MIMEText 234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email.MIMEImage import MIMEImage 244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email.MIMEBase import MIMEBase 254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email.MIMEMessage import MIMEMessage 264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email.MIMEMultipart import MIMEMultipart 274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email import Utils 284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email import Errors 294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email import Encoders 304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email import Iterators 314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email import base64MIME 324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email import quopriMIME 334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom test.test_support import findfile, run_unittest 354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom email.test import __file__ as landmark 364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmNL = '\n' 394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmEMPTYSTRING = '' 404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSPACE = ' ' 414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef openfile(filename, mode='r'): 454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm path = os.path.join(os.path.dirname(landmark), 'data', filename) 464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return open(path, mode) 474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Base test class 514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestEmailBase(unittest.TestCase): 524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def ndiffAssertEqual(self, first, second): 534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Like assertEqual except use ndiff for readable output.""" 544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if first != second: 554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sfirst = str(first) 564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ssecond = str(second) 574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm diff = difflib.ndiff(sfirst.splitlines(), ssecond.splitlines()) 584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = StringIO() 594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm print >> fp, NL, NL.join(diff) 604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise self.failureException, fp.getvalue() 614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _msgobj(self, filename): 634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile(findfile(filename)) 644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_file(fp) 664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return msg 694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test various aspects of the Message class's API 734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestMessageAPI(TestEmailBase): 744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_all(self): 754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_20.txt') 774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_all('cc'), ['ccc@zzz.org', 'ddd@zzz.org', 'eee@zzz.org']) 784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_all('xx', 'n/a'), 'n/a') 794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_getset_charset(self): 814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_charset(), None) 844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charset = Charset('iso-8859-1') 854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_charset(charset) 864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['mime-version'], '1.0') 874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_type(), 'text/plain') 884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-type'], 'text/plain; charset="iso-8859-1"') 894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('charset'), 'iso-8859-1') 904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-transfer-encoding'], 'quoted-printable') 914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_charset().input_charset, 'iso-8859-1') 924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Remove the charset 934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_charset(None) 944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_charset(), None) 954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-type'], 'text/plain') 964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Try adding a charset when there's already MIME headers present 974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['MIME-Version'] = '2.0' 994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Content-Type'] = 'text/x-weird' 1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Content-Transfer-Encoding'] = 'quinted-puntable' 1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_charset(charset) 1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['mime-version'], '2.0') 1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-type'], 'text/x-weird; charset="iso-8859-1"') 1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-transfer-encoding'], 'quinted-puntable') 1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_set_charset_from_string(self): 1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_charset('us-ascii') 1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_charset().input_charset, 'us-ascii') 1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-type'], 'text/plain; charset="us-ascii"') 1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_set_payload_with_charset(self): 1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charset = Charset('iso-8859-1') 1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_payload('This is a string payload', charset) 1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_charset().input_charset, 'iso-8859-1') 1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_charsets(self): 1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_08.txt') 1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charsets = msg.get_charsets() 1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(charsets, [None, 'us-ascii', 'iso-8859-1', 'iso-8859-2', 'koi8-r']) 1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_09.txt') 1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charsets = msg.get_charsets('dingbat') 1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(charsets, ['dingbat', 'us-ascii', 'iso-8859-1', 'dingbat', 1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'koi8-r']) 1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_12.txt') 1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charsets = msg.get_charsets() 1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(charsets, [None, 'us-ascii', 'iso-8859-1', None, 'iso-8859-2', 1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'iso-8859-3', 'us-ascii', 'koi8-r']) 1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_filename(self): 1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_04.txt') 1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm filenames = [p.get_filename() for p in msg.get_payload()] 1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(filenames, ['msg.txt', 'msg.txt']) 1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_07.txt') 1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subpart = msg.get_payload(1) 1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subpart.get_filename(), 'dingusfish.gif') 1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_filename_with_name_parameter(self): 1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_44.txt') 1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm filenames = [p.get_filename() for p in msg.get_payload()] 1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(filenames, ['msg.txt', 'msg.txt']) 1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_boundary(self): 1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_07.txt') 1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # No quotes! 1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_boundary(), 'BOUNDARY') 1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_set_boundary(self): 1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # This one has no existing boundary parameter, but the Content-Type: 1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # header appears fifth. 1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_01.txt') 1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_boundary('BOUNDARY') 1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm header, value = msg.items()[4] 1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(header.lower(), 'content-type') 1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(value, 'text/plain; charset="us-ascii"; boundary="BOUNDARY"') 1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # This one has a Content-Type: header, with a boundary, stuck in the 1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # middle of its headers. Make sure the order is preserved; it should 1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # be fifth. 1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_04.txt') 1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_boundary('BOUNDARY') 1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm header, value = msg.items()[4] 1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(header.lower(), 'content-type') 1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(value, 'multipart/mixed; boundary="BOUNDARY"') 1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # And this one has no Content-Type: header at all. 1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_03.txt') 1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertRaises(Errors.HeaderParseError, 1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_boundary, 'BOUNDARY') 1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_make_boundary(self): 1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEMultipart('form-data') 1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Note that when the boundary gets created is an implementation 1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # detail and might change. 1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.items()[0][1], 'multipart/form-data') 1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Trigger creation of boundary 1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.as_string() 1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.items()[0][1][:33], 1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'multipart/form-data; boundary="==') 1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # XXX: there ought to be tests of the uniqueness of the boundary, too. 1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_message_rfc822_only(self): 1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Issue 7970: message/rfc822 not in multipart parsed by 1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # HeaderParser caused an exception when flattened. 1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile(findfile('msg_46.txt')) 1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msgdata = fp.read() 1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm parser = email.Parser.HeaderParser() 1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = parser.parsestr(msgdata) 2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm out = StringIO() 2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm gen = email.Generator.Generator(out, True, 0) 2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm gen.flatten(msg, False) 2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(out.getvalue(), msgdata) 2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_decoded_payload(self): 2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_10.txt') 2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # The outer message is a multipart 2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(decode=True), None) 2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Subpart 1 is 7bit encoded 2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(0).get_payload(decode=True), 2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'This is a 7bit encoded message.\n') 2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Subpart 2 is quopri 2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(1).get_payload(decode=True), 2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm '\xa1This is a Quoted Printable encoded message!\n') 2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Subpart 3 is base64 2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(2).get_payload(decode=True), 2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'This is a Base64 encoded message.') 2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Subpart 4 is base64 with a trailing newline, which 2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # used to be stripped (issue 7143). 2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(3).get_payload(decode=True), 2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'This is a Base64 encoded message.\n') 2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Subpart 5 has no Content-Transfer-Encoding: header. 2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(4).get_payload(decode=True), 2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'This has no Content-Transfer-Encoding: header.\n') 2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_decoded_uu_payload(self): 2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_payload('begin 666 -\n+:&5L;&\\@=V]R;&0 \n \nend\n') 2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for cte in ('x-uuencode', 'uuencode', 'uue', 'x-uue'): 2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['content-transfer-encoding'] = cte 2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(decode=True), 'hello world') 2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Now try some bogus data 2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_payload('foo') 2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(decode=True), 'foo') 2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_decode_bogus_uu_payload_quietly(self): 2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_payload('begin 664 foo.txt\n%<W1F=0000H \n \nend\n') 2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Content-Transfer-Encoding'] = 'x-uuencode' 2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm old_stderr = sys.stderr 2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sys.stderr = sfp = StringIO() 2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # We don't care about the payload 2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.get_payload(decode=True) 2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sys.stderr = old_stderr 2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(sfp.getvalue(), '') 2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_decoded_generator(self): 2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_07.txt') 2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('msg_17.txt') 2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text = fp.read() 2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = StringIO() 2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g = DecodedGenerator(s) 2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g.flatten(msg) 2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(s.getvalue(), text) 2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test__contains__(self): 2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['From'] = 'Me' 2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['to'] = 'You' 2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Check for case insensitivity 2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue('from' in msg) 2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue('From' in msg) 2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue('FROM' in msg) 2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue('to' in msg) 2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue('To' in msg) 2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue('TO' in msg) 2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_as_string(self): 2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_01.txt') 2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('msg_01.txt') 2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # BAW 30-Mar-2009 Evil be here. So, the generator is broken with 2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # respect to long line breaking. It's also not idempotent when a 2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # header from a parsed message is continued with tabs rather than 2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # spaces. Before we fixed bug 1974 it was reversedly broken, 2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # i.e. headers that were continued with spaces got continued with 2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # tabs. For Python 2.x there's really no good fix and in Python 2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # 3.x all this stuff is re-written to be right(er). Chris Withers 2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # convinced me that using space as the default continuation 2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # character is less bad for more applications. 2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text = fp.read().replace('\t', ' ') 2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(text, msg.as_string()) 2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fullrepr = str(msg) 2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lines = fullrepr.split('\n') 2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(lines[0].startswith('From ')) 2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(text, NL.join(lines[1:])) 2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_bad_param(self): 3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string("Content-Type: blarg; baz; boo\n") 3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_param('baz'), '') 3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_missing_filename(self): 3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string("From: foo\n") 3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_filename(), None) 3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_bogus_filename(self): 3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string( 3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Content-Disposition: blarg; filename\n") 3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_filename(), '') 3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_missing_boundary(self): 3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string("From: foo\n") 3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_boundary(), None) 3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_params(self): 3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string( 3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'X-Header: foo=one; bar=two; baz=three\n') 3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_params(header='x-header'), 3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm [('foo', 'one'), ('bar', 'two'), ('baz', 'three')]) 3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string( 3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'X-Header: foo; bar=one; baz=two\n') 3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_params(header='x-header'), 3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm [('foo', ''), ('bar', 'one'), ('baz', 'two')]) 3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_params(), None) 3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string( 3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'X-Header: foo; bar="one"; baz=two\n') 3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_params(header='x-header'), 3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm [('foo', ''), ('bar', 'one'), ('baz', 'two')]) 3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_param_liberal(self): 3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Content-Type'] = 'Content-Type: Multipart/mixed; boundary = "CPIMSSMTPC06p5f3tG"' 3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_param('boundary'), 'CPIMSSMTPC06p5f3tG') 3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_param(self): 3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string( 3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "X-Header: foo=one; bar=two; baz=three\n") 3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('bar', header='x-header'), 'two') 3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('quuz', header='x-header'), None) 3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('quuz'), None) 3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string( 3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'X-Header: foo; bar="one"; baz=two\n') 3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('foo', header='x-header'), '') 3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('bar', header='x-header'), 'one') 3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('baz', header='x-header'), 'two') 3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # XXX: We are not RFC-2045 compliant! We cannot parse: 3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # msg["Content-Type"] = 'text/plain; weird="hey; dolly? [you] @ <\\"home\\">?"' 3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # msg.get_param("weird") 3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # yet. 3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_param_funky_continuation_lines(self): 3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_22.txt') 3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_payload(1).get_param('name'), 'wibble.JPG') 3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_param_with_semis_in_quotes(self): 3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string( 3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'Content-Type: image/pjpeg; name="Jim&&Jill"\n') 3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_param('name'), 'Jim&&Jill') 3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_param('name', unquote=False), 3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm '"Jim&&Jill"') 3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_param_with_quotes(self): 3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string( 3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'Content-Type: foo; bar*0="baz\\"foobar"; bar*1="\\"baz"') 3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_param('bar'), 'baz"foobar"baz') 3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string( 3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Content-Type: foo; bar*0=\"baz\\\"foobar\"; bar*1=\"\\\"baz\"") 3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_param('bar'), 'baz"foobar"baz') 3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_has_key(self): 3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string('Header: exists') 3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(msg.has_key('header')) 3764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(msg.has_key('Header')) 3774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(msg.has_key('HEADER')) 3784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertFalse(msg.has_key('headeri')) 3794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_set_param(self): 3814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 3824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 3834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_param('charset', 'iso-2022-jp') 3844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('charset'), 'iso-2022-jp') 3854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_param('importance', 'high value') 3864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('importance'), 'high value') 3874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('importance', unquote=False), '"high value"') 3884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_params(), [('text/plain', ''), 3894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('charset', 'iso-2022-jp'), 3904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('importance', 'high value')]) 3914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_params(unquote=False), [('text/plain', ''), 3924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('charset', '"iso-2022-jp"'), 3934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('importance', '"high value"')]) 3944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_param('charset', 'iso-9999-xx', header='X-Jimmy') 3954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('charset', header='X-Jimmy'), 'iso-9999-xx') 3964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_del_param(self): 3984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 3994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_05.txt') 4004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_params(), 4014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm [('multipart/report', ''), ('report-type', 'delivery-status'), 4024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('boundary', 'D1690A7AC1.996856090/mail.example.com')]) 4034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm old_val = msg.get_param("report-type") 4044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.del_param("report-type") 4054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_params(), 4064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm [('multipart/report', ''), 4074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('boundary', 'D1690A7AC1.996856090/mail.example.com')]) 4084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_param("report-type", old_val) 4094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_params(), 4104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm [('multipart/report', ''), 4114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('boundary', 'D1690A7AC1.996856090/mail.example.com'), 4124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('report-type', old_val)]) 4134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_del_param_on_other_header(self): 4154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 4164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.add_header('Content-Disposition', 'attachment', filename='bud.gif') 4174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.del_param('filename', 'content-disposition') 4184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg['content-disposition'], 'attachment') 4194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_set_type(self): 4214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 4224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 4234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertRaises(ValueError, msg.set_type, 'text') 4244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_type('text/plain') 4254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-type'], 'text/plain') 4264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_param('charset', 'us-ascii') 4274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-type'], 'text/plain; charset="us-ascii"') 4284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_type('text/html') 4294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-type'], 'text/html; charset="us-ascii"') 4304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_set_type_on_other_header(self): 4324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 4334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['X-Content-Type'] = 'text/plain' 4344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_type('application/octet-stream', 'X-Content-Type') 4354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg['x-content-type'], 'application/octet-stream') 4364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_type_missing(self): 4384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 4394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_type(), 'text/plain') 4404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_type_missing_with_default_type(self): 4424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 4434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_default_type('message/rfc822') 4444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_type(), 'message/rfc822') 4454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_type_from_message_implicit(self): 4474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_30.txt') 4484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_payload(0).get_content_type(), 4494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'message/rfc822') 4504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_type_from_message_explicit(self): 4524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_28.txt') 4534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_payload(0).get_content_type(), 4544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'message/rfc822') 4554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_type_from_message_text_plain_implicit(self): 4574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_03.txt') 4584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_type(), 'text/plain') 4594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_type_from_message_text_plain_explicit(self): 4614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_01.txt') 4624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_type(), 'text/plain') 4634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_maintype_missing(self): 4654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 4664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_maintype(), 'text') 4674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_maintype_missing_with_default_type(self): 4694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 4704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_default_type('message/rfc822') 4714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_maintype(), 'message') 4724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_maintype_from_message_implicit(self): 4744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_30.txt') 4754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_payload(0).get_content_maintype(), 'message') 4764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_maintype_from_message_explicit(self): 4784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_28.txt') 4794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_payload(0).get_content_maintype(), 'message') 4804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_maintype_from_message_text_plain_implicit(self): 4824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_03.txt') 4834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_maintype(), 'text') 4844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_maintype_from_message_text_plain_explicit(self): 4864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_01.txt') 4874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_maintype(), 'text') 4884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_subtype_missing(self): 4904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 4914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_subtype(), 'plain') 4924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_subtype_missing_with_default_type(self): 4944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 4954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_default_type('message/rfc822') 4964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_subtype(), 'rfc822') 4974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_subtype_from_message_implicit(self): 4994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_30.txt') 5004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_payload(0).get_content_subtype(), 'rfc822') 5014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_subtype_from_message_explicit(self): 5034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_28.txt') 5044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_payload(0).get_content_subtype(), 'rfc822') 5054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_subtype_from_message_text_plain_implicit(self): 5074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_03.txt') 5084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_subtype(), 'plain') 5094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_subtype_from_message_text_plain_explicit(self): 5114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_01.txt') 5124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_subtype(), 'plain') 5134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_maintype_error(self): 5154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 5164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Content-Type'] = 'no-slash-in-this-string' 5174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_maintype(), 'text') 5184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_subtype_error(self): 5204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 5214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Content-Type'] = 'no-slash-in-this-string' 5224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_subtype(), 'plain') 5234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_replace_header(self): 5254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 5264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 5274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.add_header('First', 'One') 5284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.add_header('Second', 'Two') 5294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.add_header('Third', 'Three') 5304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.keys(), ['First', 'Second', 'Third']) 5314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.values(), ['One', 'Two', 'Three']) 5324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.replace_header('Second', 'Twenty') 5334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.keys(), ['First', 'Second', 'Third']) 5344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.values(), ['One', 'Twenty', 'Three']) 5354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.add_header('First', 'Eleven') 5364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.replace_header('First', 'One Hundred') 5374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.keys(), ['First', 'Second', 'Third', 'First']) 5384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.values(), ['One Hundred', 'Twenty', 'Three', 'Eleven']) 5394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertRaises(KeyError, msg.replace_header, 'Fourth', 'Missing') 5404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_broken_base64_payload(self): 5424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm x = 'AwDp0P7//y6LwKEAcPa/6Q=9' 5434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 5444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['content-type'] = 'audio/x-midi' 5454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['content-transfer-encoding'] = 'base64' 5464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_payload(x) 5474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_payload(decode=True), x) 5484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_content_charset(self): 5504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 5514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_charset('us-ascii') 5524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual('us-ascii', msg.get_content_charset()) 5534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_charset(u'us-ascii') 5544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual('us-ascii', msg.get_content_charset()) 5554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Issue 5871: reject an attempt to embed a header inside a header value 5574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # (header injection attack). 5584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_embeded_header_via_Header_rejected(self): 5594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 5604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Dummy'] = Header('dummy\nX-Injected-Header: test') 5614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertRaises(Errors.HeaderParseError, msg.as_string) 5624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_embeded_header_via_string_rejected(self): 5644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 5654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Dummy'] = 'dummy\nX-Injected-Header: test' 5664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertRaises(Errors.HeaderParseError, msg.as_string) 5674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test the email.Encoders module 5704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestEncoders(unittest.TestCase): 5714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_encode_empty_payload(self): 5724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 5734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 5744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_charset('us-ascii') 5754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-transfer-encoding'], '7bit') 5764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_default_cte(self): 5784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 5794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # 7bit data and the default us-ascii _charset 5804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEText('hello world') 5814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-transfer-encoding'], '7bit') 5824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Similar, but with 8bit data 5834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEText('hello \xf8 world') 5844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-transfer-encoding'], '8bit') 5854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # And now with a different charset 5864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEText('hello \xf8 world', _charset='iso-8859-1') 5874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-transfer-encoding'], 'quoted-printable') 5884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_encode7or8bit(self): 5904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Make sure a charset whose input character set is 8bit but 5914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # whose output character set is 7bit gets a transfer-encoding 5924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # of 7bit. 5934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 5944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.MIMEText.MIMEText('\xca\xb8', _charset='euc-jp') 5954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-transfer-encoding'], '7bit') 5964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test long header wrapping 5994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestLongHeaders(TestEmailBase): 6004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_split_long_continuation(self): 6014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 6024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string("""\ 6034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: bug demonstration 6044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\t12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 6054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tmore text 6064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtest 6084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 6094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sfp = StringIO() 6104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g = Generator(sfp) 6114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g.flatten(msg) 6124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(sfp.getvalue(), """\ 6134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: bug demonstration 6144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 6154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm more text 6164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtest 6184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 6194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_another_long_almost_unsplittable_header(self): 6214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 6224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm hstr = """\ 6234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmbug demonstration 6244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\t12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 6254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tmore text""" 6264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header(hstr, continuation_ws='\t') 6274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), """\ 6284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmbug demonstration 6294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\t12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 6304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tmore text""") 6314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header(hstr) 6324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), """\ 6334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmbug demonstration 6344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789 6354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm more text""") 6364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_long_nonstring(self): 6384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 6394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g = Charset("iso-8859-1") 6404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm cz = Charset("iso-8859-2") 6414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm utf8 = Charset("utf-8") 6424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 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. " 6434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm cz_head = "Finan\xe8ni metropole se hroutily pod tlakem jejich d\xf9vtipu.. " 6444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 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") 6454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header(g_head, g, header_name='Subject') 6464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h.append(cz_head, cz) 6474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h.append(utf8_head, utf8) 6484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 6494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Subject'] = h 6504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sfp = StringIO() 6514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g = Generator(sfp) 6524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g.flatten(msg) 6534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(sfp.getvalue(), """\ 6544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: =?iso-8859-1?q?Die_Mieter_treten_hier_ein_werden_mit_einem_Foerd?= 6554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?erband_komfortabel_den_Korridor_entlang=2C_an_s=FCdl=FCndi?= 6564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?schen_Wandgem=E4lden_vorbei=2C_gegen_die_rotierenden_Kling?= 6574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?en_bef=F6rdert=2E_?= =?iso-8859-2?q?Finan=E8ni_met?= 6584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-2?q?ropole_se_hroutily_pod_tlakem_jejich_d=F9vtipu=2E=2E_?= 6594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?b?5q2j56K644Gr6KiA44GG44Go57+76Kiz44Gv44GV44KM44Gm44GE?= 6604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?b?44G+44Gb44KT44CC5LiA6YOo44Gv44OJ44Kk44OE6Kqe44Gn44GZ44GM44CB?= 6614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?b?44GC44Go44Gv44Gn44Gf44KJ44KB44Gn44GZ44CC5a6f6Zqb44Gr44Gv44CM?= 6624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?q?Wenn_ist_das_Nunstuck_git_und_Slotermeyer=3F_Ja!_Beiherhund_das?= 6634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?b?IE9kZXIgZGllIEZsaXBwZXJ3YWxkdCBnZXJzcHV0LuOAjeOBqOiogOOBow==?= 6644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?b?44Gm44GE44G+44GZ44CC?= 6654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 6674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), """\ 6684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm=?iso-8859-1?q?Die_Mieter_treten_hier_ein_werden_mit_einem_Foerd?= 6694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?erband_komfortabel_den_Korridor_entlang=2C_an_s=FCdl=FCndi?= 6704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?schen_Wandgem=E4lden_vorbei=2C_gegen_die_rotierenden_Kling?= 6714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?en_bef=F6rdert=2E_?= =?iso-8859-2?q?Finan=E8ni_met?= 6724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-2?q?ropole_se_hroutily_pod_tlakem_jejich_d=F9vtipu=2E=2E_?= 6734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?b?5q2j56K644Gr6KiA44GG44Go57+76Kiz44Gv44GV44KM44Gm44GE?= 6744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?b?44G+44Gb44KT44CC5LiA6YOo44Gv44OJ44Kk44OE6Kqe44Gn44GZ44GM44CB?= 6754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?b?44GC44Go44Gv44Gn44Gf44KJ44KB44Gn44GZ44CC5a6f6Zqb44Gr44Gv44CM?= 6764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?q?Wenn_ist_das_Nunstuck_git_und_Slotermeyer=3F_Ja!_Beiherhund_das?= 6774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?b?IE9kZXIgZGllIEZsaXBwZXJ3YWxkdCBnZXJzcHV0LuOAjeOBqOiogOOBow==?= 6784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?b?44Gm44GE44G+44GZ44CC?=""") 6794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_long_header_encode(self): 6814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 6824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header('wasnipoop; giraffes="very-long-necked-animals"; ' 6834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'spooge="yummy"; hippos="gargantuan"; marshmallows="gooey"', 6844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm header_name='X-Foobar-Spoink-Defrobnit') 6854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), '''\ 6864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmwasnipoop; giraffes="very-long-necked-animals"; 6874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm spooge="yummy"; hippos="gargantuan"; marshmallows="gooey"''') 6884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_long_header_encode_with_tab_continuation(self): 6904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 6914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header('wasnipoop; giraffes="very-long-necked-animals"; ' 6924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'spooge="yummy"; hippos="gargantuan"; marshmallows="gooey"', 6934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm header_name='X-Foobar-Spoink-Defrobnit', 6944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm continuation_ws='\t') 6954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), '''\ 6964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmwasnipoop; giraffes="very-long-necked-animals"; 6974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tspooge="yummy"; hippos="gargantuan"; marshmallows="gooey"''') 6984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_header_splitter(self): 7004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 7014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEText('') 7024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # It'd be great if we could use add_header() here, but that doesn't 7034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # guarantee an order of the parameters. 7044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['X-Foobar-Spoink-Defrobnit'] = ( 7054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'wasnipoop; giraffes="very-long-necked-animals"; ' 7064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'spooge="yummy"; hippos="gargantuan"; marshmallows="gooey"') 7074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sfp = StringIO() 7084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g = Generator(sfp) 7094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g.flatten(msg) 7104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(sfp.getvalue(), '''\ 7114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset="us-ascii" 7124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 7134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 7bit 7144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmX-Foobar-Spoink-Defrobnit: wasnipoop; giraffes="very-long-necked-animals"; 7154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm spooge="yummy"; hippos="gargantuan"; marshmallows="gooey" 7164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''') 7184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_no_semis_header_splitter(self): 7204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 7214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 7224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['From'] = 'test@dom.ain' 7234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['References'] = SPACE.join(['<%d@dom.ain>' % i for i in range(10)]) 7244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_payload('Test') 7254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sfp = StringIO() 7264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g = Generator(sfp) 7274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g.flatten(msg) 7284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(sfp.getvalue(), """\ 7294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: test@dom.ain 7304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReferences: <0@dom.ain> <1@dom.ain> <2@dom.ain> <3@dom.ain> <4@dom.ain> 7314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm <5@dom.ain> <6@dom.ain> <7@dom.ain> <8@dom.ain> <9@dom.ain> 7324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTest""") 7344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_no_split_long_header(self): 7364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 7374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm hstr = 'References: ' + 'x' * 80 7384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header(hstr, continuation_ws='\t') 7394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), """\ 7404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReferences: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx""") 7414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_splitting_multiple_long_lines(self): 7434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 7444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm hstr = """\ 7454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom 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) 7464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\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) 7474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\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) 7484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 7494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header(hstr, continuation_ws='\t') 7504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), """\ 7514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom babylon.socal-raves.org (localhost [127.0.0.1]); 7524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tby babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; 7534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfor <mailman-admin@babylon.socal-raves.org>; 7544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tSat, 2 Feb 2002 17:00:06 -0800 (PST) 7554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfrom babylon.socal-raves.org (localhost [127.0.0.1]); 7564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tby babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; 7574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfor <mailman-admin@babylon.socal-raves.org>; 7584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tSat, 2 Feb 2002 17:00:06 -0800 (PST) 7594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfrom babylon.socal-raves.org (localhost [127.0.0.1]); 7604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tby babylon.socal-raves.org (Postfix) with ESMTP id B570E51B81; 7614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfor <mailman-admin@babylon.socal-raves.org>; 7624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tSat, 2 Feb 2002 17:00:06 -0800 (PST)""") 7634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_splitting_first_line_only_is_long(self): 7654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 7664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm hstr = """\ 7674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom modemcable093.139-201-24.que.mc.videotron.ca ([24.201.139.93] helo=cthulhu.gerg.ca) 7684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tby kronos.mems-exchange.org with esmtp (Exim 4.05) 7694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tid 17k4h5-00034i-00 7704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfor test@mems-exchange.org; Wed, 28 Aug 2002 11:25:20 -0400""" 7714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header(hstr, maxlinelen=78, header_name='Received', 7724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm continuation_ws='\t') 7734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), """\ 7744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom modemcable093.139-201-24.que.mc.videotron.ca ([24.201.139.93] 7754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\thelo=cthulhu.gerg.ca) 7764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tby kronos.mems-exchange.org with esmtp (Exim 4.05) 7774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tid 17k4h5-00034i-00 7784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfor test@mems-exchange.org; Wed, 28 Aug 2002 11:25:20 -0400""") 7794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_long_8bit_header(self): 7814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 7824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 7834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header('Britische Regierung gibt', 'iso-8859-1', 7844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm header_name='Subject') 7854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h.append('gr\xfcnes Licht f\xfcr Offshore-Windkraftprojekte') 7864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Subject'] = h 7874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.as_string(), """\ 7884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: =?iso-8859-1?q?Britische_Regierung_gibt?= =?iso-8859-1?q?gr=FCnes?= 7894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?_Licht_f=FCr_Offshore-Windkraftprojekte?= 7904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 7924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_long_8bit_header_no_charset(self): 7944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 7954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 7964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Reply-To'] = 'Britische Regierung gibt gr\xfcnes Licht f\xfcr Offshore-Windkraftprojekte <a-very-long-address@example.com>' 7974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.as_string(), """\ 7984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReply-To: Britische Regierung gibt gr\xfcnes Licht f\xfcr Offshore-Windkraftprojekte <a-very-long-address@example.com> 7994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 8014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_long_to_header(self): 8034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 8044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 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>' 8054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 8064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['To'] = to 8074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.as_string(0), '''\ 8084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTo: "Someone Test #A" <someone@eecs.umich.edu>, <someone@eecs.umich.edu>, 8094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Someone Test #B" <someone@umich.edu>, 8104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Someone Test #C" <someone@eecs.umich.edu>, 8114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Someone Test #D" <someone@eecs.umich.edu> 8124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''') 8144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_long_line_after_append(self): 8164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 8174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = 'This is an example of string which has almost the limit of header length.' 8184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header(s) 8194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h.append('Add another line.') 8204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), """\ 8214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmThis is an example of string which has almost the limit of header length. 8224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Add another line.""") 8234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_shorter_line_with_append(self): 8254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 8264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = 'This is a shorter line.' 8274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header(s) 8284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h.append('Add another sentence. (Surprise?)') 8294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), 8304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'This is a shorter line. Add another sentence. (Surprise?)') 8314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_long_field_name(self): 8334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 8344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fn = 'X-Very-Very-Very-Long-Header-Name' 8354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 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. " 8364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header(gs, 'iso-8859-1', header_name=fn) 8374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # BAW: this seems broken because the first line is too long 8384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), """\ 8394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm=?iso-8859-1?q?Die_Mieter_treten_hier_?= 8404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?ein_werden_mit_einem_Foerderband_komfortabel_den_Korridor_?= 8414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?entlang=2C_an_s=FCdl=FCndischen_Wandgem=E4lden_vorbei=2C_g?= 8424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?egen_die_rotierenden_Klingen_bef=F6rdert=2E_?=""") 8434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_long_received_header(self): 8454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 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' 8464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 8474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Received-1'] = Header(h, continuation_ws='\t') 8484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Received-2'] = h 8494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.as_string(), """\ 8504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReceived-1: from FOO.TLD (vizworld.acl.foo.tld [123.452.678.9]) by 8514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\throthgar.la.mastaler.com (tmda-ofmipd) with ESMTP; 8524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tWed, 05 Mar 2003 18:10:18 -0700 8534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReceived-2: from FOO.TLD (vizworld.acl.foo.tld [123.452.678.9]) by 8544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm hrothgar.la.mastaler.com (tmda-ofmipd) with ESMTP; 8554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Wed, 05 Mar 2003 18:10:18 -0700 8564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 8584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_string_headerinst_eq(self): 8604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = '<15975.17901.207240.414604@sgigritzmann1.mathematik.tu-muenchen.de> (David Bremner\'s message of "Thu, 6 Mar 2003 13:58:21 +0100")' 8614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 8624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Received'] = Header(h, header_name='Received', 8634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm continuation_ws='\t') 8644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Received'] = h 8654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.ndiffAssertEqual(msg.as_string(), """\ 8664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReceived: <15975.17901.207240.414604@sgigritzmann1.mathematik.tu-muenchen.de> 8674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\t(David Bremner's message of "Thu, 6 Mar 2003 13:58:21 +0100") 8684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReceived: <15975.17901.207240.414604@sgigritzmann1.mathematik.tu-muenchen.de> 8694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (David Bremner's message of "Thu, 6 Mar 2003 13:58:21 +0100") 8704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 8724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_long_unbreakable_lines_with_continuation(self): 8744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 8754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 8764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm t = """\ 8774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 8784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp""" 8794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Face-1'] = t 8804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Face-2'] = Header(t, header_name='Face-2') 8814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.as_string(), """\ 8824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFace-1: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 8834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp 8844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFace-2: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEUAAAAkHiJeRUIcGBi9 8854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm locQDQ4zJykFBAXJfWDjAAACYUlEQVR4nF2TQY/jIAyFc6lydlG5x8Nyp1Y69wj1PN2I5gzp 8864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 8884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_another_long_multiline_header(self): 8904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 8914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = '''\ 8924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReceived: from siimage.com ([172.25.1.3]) by zima.siliconimage.com with Microsoft SMTPSVC(5.0.2195.4905); 8934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Wed, 16 Oct 2002 07:41:11 -0700''' 8944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 8954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.as_string(), '''\ 8964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReceived: from siimage.com ([172.25.1.3]) by zima.siliconimage.com with 8974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Microsoft SMTPSVC(5.0.2195.4905); Wed, 16 Oct 2002 07:41:11 -0700 8984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''') 9004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_long_lines_with_different_header(self): 9024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 9034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = """\ 9044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmList-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/spamassassin-talk>, 9054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm <mailto:spamassassin-talk-request@lists.sourceforge.net?subject=unsubscribe>""" 9064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 9074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['List'] = h 9084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['List'] = Header(h, header_name='List') 9094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.as_string(), """\ 9104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmList: List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/spamassassin-talk>, 9114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm <mailto:spamassassin-talk-request@lists.sourceforge.net?subject=unsubscribe> 9124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmList: List-Unsubscribe: <https://lists.sourceforge.net/lists/listinfo/spamassassin-talk>, 9134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm <mailto:spamassassin-talk-request@lists.sourceforge.net?subject=unsubscribe> 9144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 9164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test mangling of "From " lines in the body of a message 9204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestFromMangling(unittest.TestCase): 9214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def setUp(self): 9224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.msg = Message() 9234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.msg['From'] = 'aaa@bbb.org' 9244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.msg.set_payload("""\ 9254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom the desk of A.A.A.: 9264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmBlah blah blah 9274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 9284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_mangled_from(self): 9304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = StringIO() 9314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g = Generator(s, mangle_from_=True) 9324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g.flatten(self.msg) 9334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(s.getvalue(), """\ 9344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: aaa@bbb.org 9354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm>From the desk of A.A.A.: 9374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmBlah blah blah 9384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 9394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_dont_mangle_from(self): 9414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = StringIO() 9424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g = Generator(s, mangle_from_=False) 9434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g.flatten(self.msg) 9444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(s.getvalue(), """\ 9454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: aaa@bbb.org 9464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom the desk of A.A.A.: 9484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmBlah blah blah 9494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 9504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test the basic MIMEAudio class 9544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestMIMEAudio(unittest.TestCase): 9554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def setUp(self): 9564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Make sure we pick up the audiotest.au that lives in email/test/data. 9574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # In Python, there's an audiotest.au living in Lib/test but that isn't 9584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # included in some binary distros that don't include the test 9594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # package. The trailing empty string on the .join() is significant 9604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # since findfile() will do a dirname(). 9614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm datadir = os.path.join(os.path.dirname(landmark), 'data', '') 9624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = open(findfile('audiotest.au', datadir), 'rb') 9634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 9644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._audiodata = fp.read() 9654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 9664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 9674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._au = MIMEAudio(self._audiodata) 9684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_guess_minor_type(self): 9704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(self._au.get_content_type(), 'audio/basic') 9714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_encoding(self): 9734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm payload = self._au.get_payload() 9744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(base64.decodestring(payload), self._audiodata) 9754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_checkSetMinor(self): 9774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm au = MIMEAudio(self._audiodata, 'fish') 9784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(au.get_content_type(), 'audio/fish') 9794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 9804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_add_header(self): 9814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 9824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless = self.assertTrue 9834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._au.add_header('Content-Disposition', 'attachment', 9844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm filename='audiotest.au') 9854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(self._au['content-disposition'], 9864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'attachment; filename="audiotest.au"') 9874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(self._au.get_params(header='content-disposition'), 9884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm [('attachment', ''), ('filename', 'audiotest.au')]) 9894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(self._au.get_param('filename', header='content-disposition'), 9904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'audiotest.au') 9914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm missing = [] 9924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(self._au.get_param('attachment', header='content-disposition'), '') 9934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(self._au.get_param('foo', failobj=missing, 9944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm header='content-disposition') is missing) 9954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Try some missing stuff 9964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(self._au.get_param('foobar', missing) is missing) 9974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(self._au.get_param('attachment', missing, 9984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm header='foobar') is missing) 9994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test the basic MIMEImage class 10034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestMIMEImage(unittest.TestCase): 10044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def setUp(self): 10054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('PyBanner048.gif') 10064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 10074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._imgdata = fp.read() 10084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 10094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 10104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._im = MIMEImage(self._imgdata) 10114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_guess_minor_type(self): 10134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(self._im.get_content_type(), 'image/gif') 10144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_encoding(self): 10164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm payload = self._im.get_payload() 10174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(base64.decodestring(payload), self._imgdata) 10184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_checkSetMinor(self): 10204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm im = MIMEImage(self._imgdata, 'fish') 10214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(im.get_content_type(), 'image/fish') 10224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_add_header(self): 10244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 10254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless = self.assertTrue 10264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._im.add_header('Content-Disposition', 'attachment', 10274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm filename='dingusfish.gif') 10284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(self._im['content-disposition'], 10294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'attachment; filename="dingusfish.gif"') 10304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(self._im.get_params(header='content-disposition'), 10314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm [('attachment', ''), ('filename', 'dingusfish.gif')]) 10324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(self._im.get_param('filename', header='content-disposition'), 10334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'dingusfish.gif') 10344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm missing = [] 10354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(self._im.get_param('attachment', header='content-disposition'), '') 10364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(self._im.get_param('foo', failobj=missing, 10374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm header='content-disposition') is missing) 10384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Try some missing stuff 10394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(self._im.get_param('foobar', missing) is missing) 10404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(self._im.get_param('attachment', missing, 10414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm header='foobar') is missing) 10424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test the basic MIMEText class 10464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestMIMEText(unittest.TestCase): 10474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def setUp(self): 10484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._msg = MIMEText('hello there') 10494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_types(self): 10514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 10524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless = self.assertTrue 10534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(self._msg.get_content_type(), 'text/plain') 10544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(self._msg.get_param('charset'), 'us-ascii') 10554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm missing = [] 10564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(self._msg.get_param('foobar', missing) is missing) 10574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(self._msg.get_param('charset', missing, header='foobar') 10584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm is missing) 10594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_payload(self): 10614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(self._msg.get_payload(), 'hello there') 10624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(not self._msg.is_multipart()) 10634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_charset(self): 10654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 10664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEText('hello there', _charset='us-ascii') 10674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_charset().input_charset, 'us-ascii') 10684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-type'], 'text/plain; charset="us-ascii"') 10694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_7bit_unicode_input(self): 10714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 10724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEText(u'hello there', _charset='us-ascii') 10734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_charset().input_charset, 'us-ascii') 10744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-type'], 'text/plain; charset="us-ascii"') 10754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_7bit_unicode_input_no_charset(self): 10774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 10784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEText(u'hello there') 10794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_charset(), 'us-ascii') 10804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-type'], 'text/plain; charset="us-ascii"') 10814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue('hello there' in msg.as_string()) 10824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_8bit_unicode_input(self): 10844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm teststr = u'\u043a\u0438\u0440\u0438\u043b\u0438\u0446\u0430' 10854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 10864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEText(teststr, _charset='utf-8') 10874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_charset().output_charset, 'utf-8') 10884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-type'], 'text/plain; charset="utf-8"') 10894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(decode=True), teststr.encode('utf-8')) 10904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_8bit_unicode_input_no_charset(self): 10924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm teststr = u'\u043a\u0438\u0440\u0438\u043b\u0438\u0446\u0430' 10934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertRaises(UnicodeEncodeError, MIMEText, teststr) 10944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 10974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test complicated multipart/* messages 10984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestMultipart(TestEmailBase): 10994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def setUp(self): 11004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('PyBanner048.gif') 11014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 11024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm data = fp.read() 11034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 11044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 11054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container = MIMEBase('multipart', 'mixed', boundary='BOUNDARY') 11074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm image = MIMEImage(data, name='dingusfish.gif') 11084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm image.add_header('content-disposition', 'attachment', 11094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm filename='dingusfish.gif') 11104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm intro = MIMEText('''\ 11114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmHi there, 11124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmThis is the dingus fish. 11144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''') 11154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container.attach(intro) 11164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container.attach(image) 11174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container['From'] = 'Barry <barry@digicool.com>' 11184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container['To'] = 'Dingus Lovers <cravindogs@cravindogs.com>' 11194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container['Subject'] = 'Here is your dingus fish' 11204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm now = 987809702.54848599 11224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm timetuple = time.localtime(now) 11234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if timetuple[-1] == 0: 11244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm tzsecs = time.timezone 11254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 11264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm tzsecs = time.altzone 11274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if tzsecs > 0: 11284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sign = '-' 11294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 11304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sign = '+' 11314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm tzoffset = ' %s%04d' % (sign, tzsecs // 36) 11324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container['Date'] = time.strftime( 11334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm '%a, %d %b %Y %H:%M:%S', 11344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm time.localtime(now)) + tzoffset 11354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._msg = container 11364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._im = image 11374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._txt = intro 11384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_hierarchy(self): 11404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # convenience 11414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 11424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless = self.assertTrue 11434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raises = self.assertRaises 11444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # tests 11454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = self._msg 11464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(m.is_multipart()) 11474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(m.get_content_type(), 'multipart/mixed') 11484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(m.get_payload()), 2) 11494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raises(IndexError, m.get_payload, 2) 11504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m0 = m.get_payload(0) 11514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m1 = m.get_payload(1) 11524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(m0 is self._txt) 11534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(m1 is self._im) 11544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(m.get_payload(), [m0, m1]) 11554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(not m0.is_multipart()) 11564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(not m1.is_multipart()) 11574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_empty_multipart_idempotent(self): 11594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text = """\ 11604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: multipart/mixed; boundary="BOUNDARY" 11614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 11624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: A subject 11634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTo: aperson@dom.ain 11644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: bperson@dom.ain 11654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 11684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY-- 11714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 11724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Parser().parsestr(text) 11734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.ndiffAssertEqual(text, msg.as_string()) 11744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_no_parts_in_a_multipart_with_none_epilogue(self): 11764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer = MIMEBase('multipart', 'mixed') 11774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['Subject'] = 'A subject' 11784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['To'] = 'aperson@dom.ain' 11794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['From'] = 'bperson@dom.ain' 11804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.set_boundary('BOUNDARY') 11814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.ndiffAssertEqual(outer.as_string(), '''\ 11824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: multipart/mixed; boundary="BOUNDARY" 11834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 11844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: A subject 11854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTo: aperson@dom.ain 11864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: bperson@dom.ain 11874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 11894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY--''') 11914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 11924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_no_parts_in_a_multipart_with_empty_epilogue(self): 11934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer = MIMEBase('multipart', 'mixed') 11944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['Subject'] = 'A subject' 11954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['To'] = 'aperson@dom.ain' 11964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['From'] = 'bperson@dom.ain' 11974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.preamble = '' 11984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.epilogue = '' 11994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.set_boundary('BOUNDARY') 12004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.ndiffAssertEqual(outer.as_string(), '''\ 12014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: multipart/mixed; boundary="BOUNDARY" 12024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 12034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: A subject 12044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTo: aperson@dom.ain 12054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: bperson@dom.ain 12064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 12094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY-- 12114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''') 12124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_one_part_in_a_multipart(self): 12144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 12154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer = MIMEBase('multipart', 'mixed') 12164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['Subject'] = 'A subject' 12174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['To'] = 'aperson@dom.ain' 12184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['From'] = 'bperson@dom.ain' 12194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.set_boundary('BOUNDARY') 12204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEText('hello world') 12214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.attach(msg) 12224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(outer.as_string(), '''\ 12234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: multipart/mixed; boundary="BOUNDARY" 12244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 12254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: A subject 12264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTo: aperson@dom.ain 12274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: bperson@dom.ain 12284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 12304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset="us-ascii" 12314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 12324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 7bit 12334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhello world 12354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY--''') 12364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_seq_parts_in_a_multipart_with_empty_preamble(self): 12384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 12394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer = MIMEBase('multipart', 'mixed') 12404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['Subject'] = 'A subject' 12414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['To'] = 'aperson@dom.ain' 12424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['From'] = 'bperson@dom.ain' 12434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.preamble = '' 12444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEText('hello world') 12454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.attach(msg) 12464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.set_boundary('BOUNDARY') 12474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(outer.as_string(), '''\ 12484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: multipart/mixed; boundary="BOUNDARY" 12494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 12504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: A subject 12514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTo: aperson@dom.ain 12524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: bperson@dom.ain 12534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 12564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset="us-ascii" 12574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 12584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 7bit 12594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhello world 12614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY--''') 12624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_seq_parts_in_a_multipart_with_none_preamble(self): 12654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 12664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer = MIMEBase('multipart', 'mixed') 12674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['Subject'] = 'A subject' 12684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['To'] = 'aperson@dom.ain' 12694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['From'] = 'bperson@dom.ain' 12704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.preamble = None 12714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEText('hello world') 12724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.attach(msg) 12734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.set_boundary('BOUNDARY') 12744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(outer.as_string(), '''\ 12754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: multipart/mixed; boundary="BOUNDARY" 12764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 12774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: A subject 12784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTo: aperson@dom.ain 12794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: bperson@dom.ain 12804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 12824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset="us-ascii" 12834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 12844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 7bit 12854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhello world 12874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY--''') 12884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 12904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_seq_parts_in_a_multipart_with_none_epilogue(self): 12914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 12924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer = MIMEBase('multipart', 'mixed') 12934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['Subject'] = 'A subject' 12944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['To'] = 'aperson@dom.ain' 12954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['From'] = 'bperson@dom.ain' 12964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.epilogue = None 12974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEText('hello world') 12984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.attach(msg) 12994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.set_boundary('BOUNDARY') 13004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(outer.as_string(), '''\ 13014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: multipart/mixed; boundary="BOUNDARY" 13024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 13034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: A subject 13044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTo: aperson@dom.ain 13054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: bperson@dom.ain 13064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 13084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset="us-ascii" 13094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 13104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 7bit 13114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhello world 13134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY--''') 13144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_seq_parts_in_a_multipart_with_empty_epilogue(self): 13174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 13184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer = MIMEBase('multipart', 'mixed') 13194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['Subject'] = 'A subject' 13204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['To'] = 'aperson@dom.ain' 13214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['From'] = 'bperson@dom.ain' 13224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.epilogue = '' 13234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEText('hello world') 13244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.attach(msg) 13254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.set_boundary('BOUNDARY') 13264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(outer.as_string(), '''\ 13274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: multipart/mixed; boundary="BOUNDARY" 13284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 13294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: A subject 13304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTo: aperson@dom.ain 13314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: bperson@dom.ain 13324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 13344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset="us-ascii" 13354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 13364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 7bit 13374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhello world 13394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY-- 13404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''') 13414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_seq_parts_in_a_multipart_with_nl_epilogue(self): 13444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 13454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer = MIMEBase('multipart', 'mixed') 13464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['Subject'] = 'A subject' 13474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['To'] = 'aperson@dom.ain' 13484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer['From'] = 'bperson@dom.ain' 13494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.epilogue = '\n' 13504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEText('hello world') 13514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.attach(msg) 13524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer.set_boundary('BOUNDARY') 13534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(outer.as_string(), '''\ 13544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: multipart/mixed; boundary="BOUNDARY" 13554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 13564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: A subject 13574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTo: aperson@dom.ain 13584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: bperson@dom.ain 13594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 13614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset="us-ascii" 13624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 13634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 7bit 13644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhello world 13664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY-- 13674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''') 13694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_message_external_body(self): 13714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 13724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_36.txt') 13734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(msg.get_payload()), 2) 13744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg1 = msg.get_payload(1) 13754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg1.get_content_type(), 'multipart/alternative') 13764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(msg1.get_payload()), 2) 13774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for subpart in msg1.get_payload(): 13784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subpart.get_content_type(), 'message/external-body') 13794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(subpart.get_payload()), 1) 13804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subsubpart = subpart.get_payload(0) 13814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subsubpart.get_content_type(), 'text/plain') 13824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_double_boundary(self): 13844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # msg_37.txt is a multipart that contains two dash-boundary's in a 13854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # row. Our interpretation of RFC 2046 calls for ignoring the second 13864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # and subsequent boundaries. 13874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_37.txt') 13884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(len(msg.get_payload()), 3) 13894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 13904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_nested_inner_contains_outer_boundary(self): 13914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 13924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # msg_38.txt has an inner part that contains outer boundaries. My 13934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # interpretation of RFC 2046 (based on sections 5.1 and 5.1.2) say 13944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # these are illegal and should be interpreted as unterminated inner 13954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # parts. 13964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_38.txt') 13974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sfp = StringIO() 13984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Iterators._structure(msg, sfp) 13994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(sfp.getvalue(), """\ 14004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmultipart/mixed 14014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm multipart/mixed 14024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm multipart/alternative 14034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 14044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 14054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 14064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 14074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 14084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_nested_with_same_boundary(self): 14104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 14114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # msg 39.txt is similarly evil in that it's got inner parts that use 14124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # the same boundary as outer parts. Again, I believe the way this is 14134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # parsed is closest to the spirit of RFC 2046 14144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_39.txt') 14154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sfp = StringIO() 14164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Iterators._structure(msg, sfp) 14174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(sfp.getvalue(), """\ 14184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmultipart/mixed 14194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm multipart/mixed 14204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm multipart/alternative 14214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm application/octet-stream 14224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm application/octet-stream 14234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 14244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 14254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_boundary_in_non_multipart(self): 14274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_40.txt') 14284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.as_string(), '''\ 14294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 14304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/html; boundary="--961284236552522269" 14314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm----961284236552522269 14334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/html; 14344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 7Bit 14354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm<html></html> 14374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm----961284236552522269-- 14394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''') 14404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_boundary_with_leading_space(self): 14424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 14434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string('''\ 14444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 14454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: multipart/mixed; boundary=" XXXX" 14464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm-- XXXX 14484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain 14494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm-- XXXX 14524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain 14534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm-- XXXX-- 14554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''') 14564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(msg.is_multipart()) 14574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_boundary(), ' XXXX') 14584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(msg.get_payload()), 2) 14594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_boundary_without_trailing_newline(self): 14614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = Parser().parsestr("""\ 14624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: multipart/mixed; boundary="===============0012394164==" 14634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 14644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--===============0012394164== 14664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: image/file1.jpg 14674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 14684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: base64 14694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmYXNkZg== 14714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--===============0012394164==--""") 14724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(m.get_payload(0).get_payload(), 'YXNkZg==') 14734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test some badly formatted messages 14774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestNonConformant(TestEmailBase): 14784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_parse_missing_minor_type(self): 14794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 14804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_14.txt') 14814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_type(), 'text/plain') 14824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_maintype(), 'text') 14834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_subtype(), 'plain') 14844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_same_boundary_inner_outer(self): 14864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless = self.assertTrue 14874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_15.txt') 14884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # XXX We can probably eventually do better 14894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm inner = msg.get_payload(0) 14904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(hasattr(inner, 'defects')) 14914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(len(inner.defects), 1) 14924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(inner.defects[0], 14934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Errors.StartBoundaryNotFoundDefect)) 14944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 14954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_multipart_no_boundary(self): 14964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless = self.assertTrue 14974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_25.txt') 14984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(msg.get_payload(), str)) 14994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(len(msg.defects), 2) 15004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(msg.defects[0], Errors.NoBoundaryInMultipartDefect)) 15014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(msg.defects[1], 15024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Errors.MultipartInvariantViolationDefect)) 15034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_invalid_content_type(self): 15054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 15064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm neq = self.ndiffAssertEqual 15074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 15084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # RFC 2045, $5.2 says invalid yields text/plain 15094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Content-Type'] = 'text' 15104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_maintype(), 'text') 15114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_subtype(), 'plain') 15124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_type(), 'text/plain') 15134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Clear the old value and try something /really/ invalid 15144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm del msg['content-type'] 15154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Content-Type'] = 'foo' 15164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_maintype(), 'text') 15174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_subtype(), 'plain') 15184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_type(), 'text/plain') 15194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Still, make sure that the message is idempotently generated 15204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = StringIO() 15214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g = Generator(s) 15224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g.flatten(msg) 15234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm neq(s.getvalue(), 'Content-Type: foo\n\n') 15244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_no_start_boundary(self): 15264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 15274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_31.txt') 15284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(), """\ 15294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 15304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain 15314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmessage 1 15334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 15354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain 15364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmessage 2 15384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY-- 15404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 15414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_no_separating_blank_line(self): 15434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 15444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_35.txt') 15454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.as_string(), """\ 15464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: aperson@dom.ain 15474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTo: bperson@dom.ain 15484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: here's something interesting 15494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmcounter to RFC 2822, there's no separating newline here 15514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 15524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_lying_multipart(self): 15544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless = self.assertTrue 15554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_41.txt') 15564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(hasattr(msg, 'defects')) 15574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(len(msg.defects), 2) 15584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(msg.defects[0], Errors.NoBoundaryInMultipartDefect)) 15594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(msg.defects[1], 15604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Errors.MultipartInvariantViolationDefect)) 15614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_missing_start_boundary(self): 15634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outer = self._msgobj('msg_42.txt') 15644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # The message structure is: 15654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # 15664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # multipart/mixed 15674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # text/plain 15684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # message/rfc822 15694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # multipart/mixed [*] 15704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # 15714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # [*] This message is missing its start boundary 15724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm bad = outer.get_payload(1).get_payload(0) 15734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(len(bad.defects), 1) 15744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(isinstance(bad.defects[0], 15754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Errors.StartBoundaryNotFoundDefect)) 15764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_first_line_is_continuation_header(self): 15784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 15794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = ' Line 1\nLine 2\nLine 3' 15804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 15814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.keys(), []) 15824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(), 'Line 2\nLine 3') 15834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(msg.defects), 1) 15844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(isinstance(msg.defects[0], 15854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Errors.FirstHeaderLineIsContinuationDefect)) 15864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.defects[0].line, ' Line 1\n') 15874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 15914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test RFC 2047 header encoding and decoding 15924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestRFC2047(unittest.TestCase): 15934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2047_multiline(self): 15944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 15954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = """Re: =?mac-iceland?q?r=8Aksm=9Arg=8Cs?= baz 15964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm foo bar =?mac-iceland?q?r=8Aksm=9Arg=8Cs?=""" 15974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm dh = decode_header(s) 15984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(dh, [ 15994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('Re:', None), 16004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('r\x8aksm\x9arg\x8cs', 'mac-iceland'), 16014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('baz foo bar', None), 16024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('r\x8aksm\x9arg\x8cs', 'mac-iceland')]) 16034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(str(make_header(dh)), 16044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Re: =?mac-iceland?q?r=8Aksm=9Arg=8Cs?= baz foo bar 16054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?mac-iceland?q?r=8Aksm=9Arg=8Cs?=""") 16064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_whitespace_eater_unicode(self): 16084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 16094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = '=?ISO-8859-1?Q?Andr=E9?= Pirard <pirard@dom.ain>' 16104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm dh = decode_header(s) 16114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(dh, [('Andr\xe9', 'iso-8859-1'), ('Pirard <pirard@dom.ain>', None)]) 16124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm hu = unicode(make_header(dh)).encode('latin-1') 16134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(hu, 'Andr\xe9 Pirard <pirard@dom.ain>') 16144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_whitespace_eater_unicode_2(self): 16164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 16174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = 'The =?iso-8859-1?b?cXVpY2sgYnJvd24gZm94?= jumped over the =?iso-8859-1?b?bGF6eSBkb2c=?=' 16184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm dh = decode_header(s) 16194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(dh, [('The', None), ('quick brown fox', 'iso-8859-1'), 16204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('jumped over the', None), ('lazy dog', 'iso-8859-1')]) 16214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm hu = make_header(dh).__unicode__() 16224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(hu, u'The quick brown fox jumped over the lazy dog') 16234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2047_without_whitespace(self): 16254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = 'Sm=?ISO-8859-1?B?9g==?=rg=?ISO-8859-1?B?5Q==?=sbord' 16264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm dh = decode_header(s) 16274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(dh, [(s, None)]) 16284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2047_with_whitespace(self): 16304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = 'Sm =?ISO-8859-1?B?9g==?= rg =?ISO-8859-1?B?5Q==?= sbord' 16314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm dh = decode_header(s) 16324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(dh, [('Sm', None), ('\xf6', 'iso-8859-1'), 16334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('rg', None), ('\xe5', 'iso-8859-1'), 16344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('sbord', None)]) 16354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2047_B_bad_padding(self): 16374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = '=?iso-8859-1?B?%s?=' 16384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm data = [ # only test complete bytes 16394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('dm==', 'v'), ('dm=', 'v'), ('dm', 'v'), 16404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('dmk=', 'vi'), ('dmk', 'vi') 16414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ] 16424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for q, a in data: 16434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm dh = decode_header(s % q) 16444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(dh, [(a, 'iso-8859-1')]) 16454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2047_Q_invalid_digits(self): 16474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # issue 10004. 16484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = '=?iso-8659-1?Q?andr=e9=zz?=' 16494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(decode_header(s), 16504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm [(b'andr\xe9=zz', 'iso-8659-1')]) 16514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test the MIMEMessage class 16544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestMIMEMessage(TestEmailBase): 16554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def setUp(self): 16564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('msg_11.txt') 16574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 16584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._text = fp.read() 16594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 16604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 16614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_type_error(self): 16634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertRaises(TypeError, MIMEMessage, 'a plain string') 16644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_valid_argument(self): 16664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 16674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless = self.assertTrue 16684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subject = 'A sub-message' 16694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = Message() 16704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m['Subject'] = subject 16714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm r = MIMEMessage(m) 16724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(r.get_content_type(), 'message/rfc822') 16734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm payload = r.get_payload() 16744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(payload, list)) 16754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(payload), 1) 16764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subpart = payload[0] 16774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(subpart is m) 16784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subpart['subject'], subject) 16794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_bad_multipart(self): 16814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 16824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg1 = Message() 16834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg1['Subject'] = 'subpart 1' 16844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg2 = Message() 16854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg2['Subject'] = 'subpart 2' 16864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm r = MIMEMessage(msg1) 16874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertRaises(Errors.MultipartConversionError, r.attach, msg2) 16884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 16894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_generate(self): 16904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # First craft the message to be encapsulated 16914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = Message() 16924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m['Subject'] = 'An enclosed message' 16934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m.set_payload('Here is the body of the message.\n') 16944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm r = MIMEMessage(m) 16954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm r['Subject'] = 'The enclosing message' 16964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = StringIO() 16974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g = Generator(s) 16984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g.flatten(r) 16994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(s.getvalue(), """\ 17004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: message/rfc822 17014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 17024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: The enclosing message 17034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 17044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: An enclosed message 17054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 17064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmHere is the body of the message. 17074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 17084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 17094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_parse_message_rfc822(self): 17104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 17114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless = self.assertTrue 17124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_11.txt') 17134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_type(), 'message/rfc822') 17144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm payload = msg.get_payload() 17154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(payload, list)) 17164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(payload), 1) 17174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm submsg = payload[0] 17184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(isinstance(submsg, Message)) 17194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(submsg['subject'], 'An enclosed message') 17204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(submsg.get_payload(), 'Here is the body of the message.\n') 17214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 17224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_dsn(self): 17234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 17244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless = self.assertTrue 17254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # msg 16 is a Delivery Status Notification, see RFC 1894 17264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_16.txt') 17274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_type(), 'multipart/report') 17284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(msg.is_multipart()) 17294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(msg.get_payload()), 3) 17304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Subpart 1 is a text/plain, human readable section 17314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subpart = msg.get_payload(0) 17324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subpart.get_content_type(), 'text/plain') 17334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subpart.get_payload(), """\ 17344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmThis report relates to a message you sent with the following header fields: 17354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 17364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Message-id: <002001c144a6$8752e060$56104586@oxy.edu> 17374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Date: Sun, 23 Sep 2001 20:10:55 -0700 17384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm From: "Ian T. Henry" <henryi@oxy.edu> 17394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm To: SoCal Raves <scr@socal-raves.org> 17404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Subject: [scr] yeah for Ians!! 17414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 17424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmYour message cannot be delivered to the following recipients: 17434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 17444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Recipient address: jangel1@cougar.noc.ucla.edu 17454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Reason: recipient reached disk quota 17464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 17474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 17484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Subpart 2 contains the machine parsable DSN information. It 17494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # consists of two blocks of headers, represented by two nested Message 17504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # objects. 17514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subpart = msg.get_payload(1) 17524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subpart.get_content_type(), 'message/delivery-status') 17534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(subpart.get_payload()), 2) 17544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # message/delivery-status should treat each block as a bunch of 17554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # headers, i.e. a bunch of Message objects. 17564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm dsn1 = subpart.get_payload(0) 17574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(dsn1, Message)) 17584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(dsn1['original-envelope-id'], '0GK500B4HD0888@cougar.noc.ucla.edu') 17594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(dsn1.get_param('dns', header='reporting-mta'), '') 17604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Try a missing one <wink> 17614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(dsn1.get_param('nsd', header='reporting-mta'), None) 17624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm dsn2 = subpart.get_payload(1) 17634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(dsn2, Message)) 17644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(dsn2['action'], 'failed') 17654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(dsn2.get_params(header='original-recipient'), 17664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm [('rfc822', ''), ('jangel1@cougar.noc.ucla.edu', '')]) 17674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(dsn2.get_param('rfc822', header='final-recipient'), '') 17684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Subpart 3 is the original message 17694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subpart = msg.get_payload(2) 17704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subpart.get_content_type(), 'message/rfc822') 17714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm payload = subpart.get_payload() 17724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(payload, list)) 17734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(payload), 1) 17744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subsubpart = payload[0] 17754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(subsubpart, Message)) 17764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subsubpart.get_content_type(), 'text/plain') 17774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subsubpart['message-id'], 17784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm '<002001c144a6$8752e060$56104586@oxy.edu>') 17794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 17804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_epilogue(self): 17814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 17824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('msg_21.txt') 17834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 17844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text = fp.read() 17854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 17864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 17874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 17884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['From'] = 'aperson@dom.ain' 17894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['To'] = 'bperson@dom.ain' 17904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Subject'] = 'Test' 17914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.preamble = 'MIME message' 17924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.epilogue = 'End of MIME message\n' 17934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg1 = MIMEText('One') 17944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg2 = MIMEText('Two') 17954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.add_header('Content-Type', 'multipart/mixed', boundary='BOUNDARY') 17964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.attach(msg1) 17974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.attach(msg2) 17984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sfp = StringIO() 17994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g = Generator(sfp) 18004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g.flatten(msg) 18014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(sfp.getvalue(), text) 18024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 18034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_no_nl_preamble(self): 18044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 18054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 18064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['From'] = 'aperson@dom.ain' 18074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['To'] = 'bperson@dom.ain' 18084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Subject'] = 'Test' 18094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.preamble = 'MIME message' 18104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.epilogue = '' 18114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg1 = MIMEText('One') 18124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg2 = MIMEText('Two') 18134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.add_header('Content-Type', 'multipart/mixed', boundary='BOUNDARY') 18144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.attach(msg1) 18154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.attach(msg2) 18164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.as_string(), """\ 18174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: aperson@dom.ain 18184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTo: bperson@dom.ain 18194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: Test 18204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: multipart/mixed; boundary="BOUNDARY" 18214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 18224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME message 18234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 18244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset="us-ascii" 18254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 18264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 7bit 18274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 18284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmOne 18294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 18304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset="us-ascii" 18314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 18324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 7bit 18334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 18344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTwo 18354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY-- 18364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 18374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 18384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_default_type(self): 18394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 18404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('msg_30.txt') 18414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 18424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_file(fp) 18434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 18444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 18454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container1 = msg.get_payload(0) 18464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(container1.get_default_type(), 'message/rfc822') 18474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(container1.get_content_type(), 'message/rfc822') 18484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container2 = msg.get_payload(1) 18494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(container2.get_default_type(), 'message/rfc822') 18504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(container2.get_content_type(), 'message/rfc822') 18514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container1a = container1.get_payload(0) 18524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(container1a.get_default_type(), 'text/plain') 18534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(container1a.get_content_type(), 'text/plain') 18544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container2a = container2.get_payload(0) 18554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(container2a.get_default_type(), 'text/plain') 18564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(container2a.get_content_type(), 'text/plain') 18574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 18584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_default_type_with_explicit_container_type(self): 18594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 18604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('msg_28.txt') 18614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 18624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_file(fp) 18634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 18644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 18654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container1 = msg.get_payload(0) 18664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(container1.get_default_type(), 'message/rfc822') 18674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(container1.get_content_type(), 'message/rfc822') 18684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container2 = msg.get_payload(1) 18694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(container2.get_default_type(), 'message/rfc822') 18704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(container2.get_content_type(), 'message/rfc822') 18714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container1a = container1.get_payload(0) 18724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(container1a.get_default_type(), 'text/plain') 18734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(container1a.get_content_type(), 'text/plain') 18744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container2a = container2.get_payload(0) 18754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(container2a.get_default_type(), 'text/plain') 18764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(container2a.get_content_type(), 'text/plain') 18774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 18784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_default_type_non_parsed(self): 18794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 18804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm neq = self.ndiffAssertEqual 18814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Set up container 18824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container = MIMEMultipart('digest', 'BOUNDARY') 18834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container.epilogue = '' 18844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Set up subparts 18854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subpart1a = MIMEText('message 1\n') 18864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subpart2a = MIMEText('message 2\n') 18874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subpart1 = MIMEMessage(subpart1a) 18884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subpart2 = MIMEMessage(subpart2a) 18894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container.attach(subpart1) 18904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm container.attach(subpart2) 18914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subpart1.get_content_type(), 'message/rfc822') 18924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subpart1.get_default_type(), 'message/rfc822') 18934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subpart2.get_content_type(), 'message/rfc822') 18944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subpart2.get_default_type(), 'message/rfc822') 18954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm neq(container.as_string(0), '''\ 18964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: multipart/digest; boundary="BOUNDARY" 18974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 18984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 18994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 19004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: message/rfc822 19014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 19024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset="us-ascii" 19044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 19054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 7bit 19064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmessage 1 19084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 19104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: message/rfc822 19114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 19124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset="us-ascii" 19144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 19154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 7bit 19164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmessage 2 19184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY-- 19204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''') 19214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm del subpart1['content-type'] 19224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm del subpart1['mime-version'] 19234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm del subpart2['content-type'] 19244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm del subpart2['mime-version'] 19254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subpart1.get_content_type(), 'message/rfc822') 19264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subpart1.get_default_type(), 'message/rfc822') 19274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subpart2.get_content_type(), 'message/rfc822') 19284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subpart2.get_default_type(), 'message/rfc822') 19294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm neq(container.as_string(0), '''\ 19304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: multipart/digest; boundary="BOUNDARY" 19314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 19324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 19344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset="us-ascii" 19364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 19374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 7bit 19384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmessage 1 19404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY 19424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset="us-ascii" 19444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 19454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 7bit 19464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmessage 2 19484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm--BOUNDARY-- 19504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''') 19514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_mime_attachments_in_constructor(self): 19534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 19544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text1 = MIMEText('') 19554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text2 = MIMEText('') 19564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEMultipart(_subparts=(text1, text2)) 19574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(msg.get_payload()), 2) 19584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(0), text1) 19594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(1), text2) 19604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_default_multipart_constructor(self): 19624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = MIMEMultipart() 19634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(msg.is_multipart()) 19644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# A general test of parser->model->generator idempotency. IOW, read a message 19674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# in, parse it into a message object tree, then without touching the tree, 19684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# regenerate the plain text. The original text and the transformed text 19694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# should be identical. Note: that we ignore the Unix-From since that may 19704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# contain a changed date. 19714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestIdempotent(TestEmailBase): 19724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _msgobj(self, filename): 19734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile(filename) 19744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 19754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm data = fp.read() 19764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 19774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 19784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(data) 19794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return msg, data 19804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _idempotent(self, msg, text): 19824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 19834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = StringIO() 19844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g = Generator(s, maxheaderlen=0) 19854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g.flatten(msg) 19864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(text, s.getvalue()) 19874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 19884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_parse_text_message(self): 19894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 19904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_01.txt') 19914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_type(), 'text/plain') 19924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_maintype(), 'text') 19934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_subtype(), 'plain') 19944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_params()[1], ('charset', 'us-ascii')) 19954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('charset'), 'us-ascii') 19964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.preamble, None) 19974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.epilogue, None) 19984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 19994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_parse_untyped_message(self): 20014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 20024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_03.txt') 20034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_type(), 'text/plain') 20044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_params(), None) 20054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('charset'), None) 20064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_simple_multipart(self): 20094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_04.txt') 20104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_MIME_digest(self): 20134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_02.txt') 20144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_long_header(self): 20174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_27.txt') 20184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_MIME_digest_with_part_headers(self): 20214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_28.txt') 20224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_mixed_with_image(self): 20254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_06.txt') 20264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_multipart_report(self): 20294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_05.txt') 20304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_dsn(self): 20334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_16.txt') 20344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_preamble_epilogue(self): 20374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_21.txt') 20384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_multipart_one_part(self): 20414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_23.txt') 20424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_multipart_no_parts(self): 20454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_24.txt') 20464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_no_start_boundary(self): 20494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_31.txt') 20504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_charset(self): 20534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_32.txt') 20544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_more_rfc2231_parameters(self): 20574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_33.txt') 20584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_text_plain_in_a_multipart_digest(self): 20614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_34.txt') 20624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_nested_multipart_mixeds(self): 20654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_12a.txt') 20664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_message_external_body_idempotent(self): 20694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_36.txt') 20704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._idempotent(msg, text) 20714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 20724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_content_type(self): 20734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 20744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless = self.assertTrue 20754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Get a message object and reset the seek pointer for other tests 20764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_05.txt') 20774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_type(), 'multipart/report') 20784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the Content-Type: parameters 20794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm params = {} 20804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for pk, pv in msg.get_params(): 20814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm params[pk] = pv 20824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(params['report-type'], 'delivery-status') 20834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(params['boundary'], 'D1690A7AC1.996856090/mail.example.com') 20844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.preamble, 'This is a MIME-encapsulated message.\n') 20854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.epilogue, '\n') 20864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(msg.get_payload()), 3) 20874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Make sure the subparts are what we expect 20884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg1 = msg.get_payload(0) 20894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg1.get_content_type(), 'text/plain') 20904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg1.get_payload(), 'Yadda yadda yadda\n') 20914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg2 = msg.get_payload(1) 20924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg2.get_content_type(), 'text/plain') 20934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg2.get_payload(), 'Yadda yadda yadda\n') 20944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg3 = msg.get_payload(2) 20954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg3.get_content_type(), 'message/rfc822') 20964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(isinstance(msg3, Message)) 20974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm payload = msg3.get_payload() 20984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(payload, list)) 20994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(payload), 1) 21004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg4 = payload[0] 21014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(msg4, Message)) 21024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg4.get_payload(), 'Yadda yadda yadda\n') 21034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 21044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_parser(self): 21054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 21064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless = self.assertTrue 21074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg, text = self._msgobj('msg_06.txt') 21084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Check some of the outer headers 21094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_type(), 'message/rfc822') 21104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Make sure the payload is a list of exactly one sub-Message, and that 21114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # that submessage has a type of text/plain 21124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm payload = msg.get_payload() 21134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(payload, list)) 21144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(payload), 1) 21154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg1 = payload[0] 21164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(isinstance(msg1, Message)) 21174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg1.get_content_type(), 'text/plain') 21184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(isinstance(msg1.get_payload(), str)) 21194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg1.get_payload(), '\n') 21204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 21214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 21224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 21234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test various other bits of the package's functionality 21244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestMiscellaneous(TestEmailBase): 21254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_message_from_string(self): 21264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('msg_01.txt') 21274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 21284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text = fp.read() 21294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 21304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 21314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(text) 21324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = StringIO() 21334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Don't wrap/continue long headers since we're trying to test 21344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # idempotency. 21354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g = Generator(s, maxheaderlen=0) 21364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g.flatten(msg) 21374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(text, s.getvalue()) 21384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 21394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_message_from_file(self): 21404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('msg_01.txt') 21414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 21424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text = fp.read() 21434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.seek(0) 21444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_file(fp) 21454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = StringIO() 21464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Don't wrap/continue long headers since we're trying to test 21474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # idempotency. 21484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g = Generator(s, maxheaderlen=0) 21494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g.flatten(msg) 21504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(text, s.getvalue()) 21514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 21524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 21534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 21544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_message_from_string_with_class(self): 21554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless = self.assertTrue 21564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('msg_01.txt') 21574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 21584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text = fp.read() 21594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 21604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 21614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Create a subclass 21624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class MyMessage(Message): 21634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 21644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 21654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(text, MyMessage) 21664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(msg, MyMessage)) 21674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Try something more complicated 21684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('msg_02.txt') 21694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 21704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text = fp.read() 21714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 21724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 21734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(text, MyMessage) 21744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for subpart in msg.walk(): 21754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(subpart, MyMessage)) 21764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 21774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_message_from_file_with_class(self): 21784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless = self.assertTrue 21794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Create a subclass 21804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class MyMessage(Message): 21814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 21824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 21834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('msg_01.txt') 21844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 21854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_file(fp, MyMessage) 21864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 21874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 21884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(msg, MyMessage)) 21894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Try something more complicated 21904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('msg_02.txt') 21914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 21924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_file(fp, MyMessage) 21934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 21944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 21954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for subpart in msg.walk(): 21964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unless(isinstance(subpart, MyMessage)) 21974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 21984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test__all__(self): 21994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module = __import__('email') 22004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm all = module.__all__ 22014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm all.sort() 22024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(all, [ 22034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Old names 22044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'Charset', 'Encoders', 'Errors', 'Generator', 22054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'Header', 'Iterators', 'MIMEAudio', 'MIMEBase', 22064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'MIMEImage', 'MIMEMessage', 'MIMEMultipart', 22074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'MIMENonMultipart', 'MIMEText', 'Message', 22084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'Parser', 'Utils', 'base64MIME', 22094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # new names 22104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'base64mime', 'charset', 'encoders', 'errors', 'generator', 22114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'header', 'iterators', 'message', 'message_from_file', 22124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'message_from_string', 'mime', 'parser', 22134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'quopriMIME', 'quoprimime', 'utils', 22144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ]) 22154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 22164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_formatdate(self): 22174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm now = time.time() 22184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(Utils.parsedate(Utils.formatdate(now))[:6], 22194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm time.gmtime(now)[:6]) 22204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 22214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_formatdate_localtime(self): 22224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm now = time.time() 22234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual( 22244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Utils.parsedate(Utils.formatdate(now, localtime=True))[:6], 22254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm time.localtime(now)[:6]) 22264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 22274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_formatdate_usegmt(self): 22284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm now = time.time() 22294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual( 22304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Utils.formatdate(now, localtime=False), 22314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm time.strftime('%a, %d %b %Y %H:%M:%S -0000', time.gmtime(now))) 22324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual( 22334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Utils.formatdate(now, localtime=False, usegmt=True), 22344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(now))) 22354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 22364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_parsedate_none(self): 22374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(Utils.parsedate(''), None) 22384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 22394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_parsedate_compact(self): 22404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # The FWS after the comma is optional 22414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(Utils.parsedate('Wed,3 Apr 2002 14:58:26 +0800'), 22424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Utils.parsedate('Wed, 3 Apr 2002 14:58:26 +0800')) 22434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 22444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_parsedate_no_dayofweek(self): 22454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 22464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(Utils.parsedate_tz('25 Feb 2003 13:47:26 -0800'), 22474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (2003, 2, 25, 13, 47, 26, 0, 1, -1, -28800)) 22484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 22494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_parsedate_compact_no_dayofweek(self): 22504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 22514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(Utils.parsedate_tz('5 Feb 2003 13:47:26 -0800'), 22524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (2003, 2, 5, 13, 47, 26, 0, 1, -1, -28800)) 22534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 22544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_parsedate_acceptable_to_time_functions(self): 22554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 22564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm timetup = Utils.parsedate('5 Feb 2003 13:47:26 -0800') 22574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm t = int(time.mktime(timetup)) 22584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(time.localtime(t)[:6], timetup[:6]) 22594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(int(time.strftime('%Y', timetup)), 2003) 22604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm timetup = Utils.parsedate_tz('5 Feb 2003 13:47:26 -0800') 22614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm t = int(time.mktime(timetup[:9])) 22624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(time.localtime(t)[:6], timetup[:6]) 22634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(int(time.strftime('%Y', timetup[:9])), 2003) 22644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 22654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_parsedate_y2k(self): 22664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Test for parsing a date with a two-digit year. 22674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 22684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Parsing a date with a two-digit year should return the correct 22694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm four-digit year. RFC822 allows two-digit years, but RFC2822 (which 22704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm obsoletes RFC822) requires four-digit years. 22714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 22724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 22734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(Utils.parsedate_tz('25 Feb 03 13:47:26 -0800'), 22744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Utils.parsedate_tz('25 Feb 2003 13:47:26 -0800')) 22754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(Utils.parsedate_tz('25 Feb 71 13:47:26 -0800'), 22764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Utils.parsedate_tz('25 Feb 1971 13:47:26 -0800')) 22774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 22784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_parseaddr_empty(self): 22794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(Utils.parseaddr('<>'), ('', '')) 22804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(Utils.formataddr(Utils.parseaddr('<>')), '') 22814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 22824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_noquote_dump(self): 22834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual( 22844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Utils.formataddr(('A Silly Person', 'person@dom.ain')), 22854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'A Silly Person <person@dom.ain>') 22864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 22874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_escape_dump(self): 22884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual( 22894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Utils.formataddr(('A (Very) Silly Person', 'person@dom.ain')), 22904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm r'"A \(Very\) Silly Person" <person@dom.ain>') 22914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm a = r'A \(Special\) Person' 22924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm b = 'person@dom.ain' 22934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(Utils.parseaddr(Utils.formataddr((a, b))), (a, b)) 22944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 22954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_escape_backslashes(self): 22964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual( 22974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Utils.formataddr(('Arthur \Backslash\ Foobar', 'person@dom.ain')), 22984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm r'"Arthur \\Backslash\\ Foobar" <person@dom.ain>') 22994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm a = r'Arthur \Backslash\ Foobar' 23004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm b = 'person@dom.ain' 23014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(Utils.parseaddr(Utils.formataddr((a, b))), (a, b)) 23024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 23034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_name_with_dot(self): 23044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm x = 'John X. Doe <jxd@example.com>' 23054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm y = '"John X. Doe" <jxd@example.com>' 23064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm a, b = ('John X. Doe', 'jxd@example.com') 23074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(Utils.parseaddr(x), (a, b)) 23084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(Utils.parseaddr(y), (a, b)) 23094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # formataddr() quotes the name if there's a dot in it 23104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(Utils.formataddr((a, b)), y) 23114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 23124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_parseaddr_preserves_quoted_pairs_in_addresses(self): 23134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # issue 10005. Note that in the third test the second pair of 23144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # backslashes is not actually a quoted pair because it is not inside a 23154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # comment or quoted string: the address being parsed has a quoted 23164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # string containing a quoted backslash, followed by 'example' and two 23174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # backslashes, followed by another quoted string containing a space and 23184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # the word 'example'. parseaddr copies those two backslashes 23194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # literally. Per rfc5322 this is not technically correct since a \ may 23204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # not appear in an address outside of a quoted string. It is probably 23214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # a sensible Postel interpretation, though. 23224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 23234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(Utils.parseaddr('""example" example"@example.com'), 23244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('', '""example" example"@example.com')) 23254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(Utils.parseaddr('"\\"example\\" example"@example.com'), 23264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('', '"\\"example\\" example"@example.com')) 23274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(Utils.parseaddr('"\\\\"example\\\\" example"@example.com'), 23284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('', '"\\\\"example\\\\" example"@example.com')) 23294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 23304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_multiline_from_comment(self): 23314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm x = """\ 23324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFoo 23334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tBar <foo@example.com>""" 23344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(Utils.parseaddr(x), ('Foo Bar', 'foo@example.com')) 23354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 23364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_quote_dump(self): 23374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual( 23384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Utils.formataddr(('A Silly; Person', 'person@dom.ain')), 23394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm r'"A Silly; Person" <person@dom.ain>') 23404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 23414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_fix_eols(self): 23424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 23434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(Utils.fix_eols('hello'), 'hello') 23444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(Utils.fix_eols('hello\n'), 'hello\r\n') 23454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(Utils.fix_eols('hello\r'), 'hello\r\n') 23464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(Utils.fix_eols('hello\r\n'), 'hello\r\n') 23474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(Utils.fix_eols('hello\n\r'), 'hello\r\n\r\n') 23484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 23494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_charset_richcomparisons(self): 23504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 23514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ne = self.assertNotEqual 23524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm cset1 = Charset() 23534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm cset2 = Charset() 23544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(cset1, 'us-ascii') 23554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(cset1, 'US-ASCII') 23564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(cset1, 'Us-AsCiI') 23574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq('us-ascii', cset1) 23584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq('US-ASCII', cset1) 23594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq('Us-AsCiI', cset1) 23604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ne(cset1, 'usascii') 23614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ne(cset1, 'USASCII') 23624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ne(cset1, 'UsAsCiI') 23634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ne('usascii', cset1) 23644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ne('USASCII', cset1) 23654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ne('UsAsCiI', cset1) 23664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(cset1, cset2) 23674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(cset2, cset1) 23684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 23694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_getaddresses(self): 23704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 23714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(Utils.getaddresses(['aperson@dom.ain (Al Person)', 23724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'Bud Person <bperson@dom.ain>']), 23734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm [('Al Person', 'aperson@dom.ain'), 23744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('Bud Person', 'bperson@dom.ain')]) 23754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 23764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_getaddresses_nasty(self): 23774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 23784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(Utils.getaddresses(['foo: ;']), [('', '')]) 23794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(Utils.getaddresses( 23804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ['[]*-- =~$']), 23814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm [('', ''), ('', ''), ('', '*--')]) 23824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(Utils.getaddresses( 23834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ['foo: ;', '"Jason R. Mastaler" <jason@dom.ain>']), 23844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]) 23854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 23864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_getaddresses_embedded_comment(self): 23874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Test proper handling of a nested comment""" 23884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 23894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm addrs = Utils.getaddresses(['User ((nested comment)) <foo@bar.com>']) 23904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(addrs[0][1], 'foo@bar.com') 23914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 23924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_utils_quote_unquote(self): 23934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 23944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 23954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.add_header('content-disposition', 'attachment', 23964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm filename='foo\\wacky"name') 23974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_filename(), 'foo\\wacky"name') 23984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 23994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_body_encoding_with_bogus_charset(self): 24004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charset = Charset('not a charset') 24014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(charset.get_body_encoding(), 'base64') 24024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 24034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_body_encoding_with_uppercase_charset(self): 24044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 24054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 24064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Content-Type'] = 'text/plain; charset=UTF-8' 24074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-type'], 'text/plain; charset=UTF-8') 24084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charsets = msg.get_charsets() 24094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(charsets), 1) 24104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(charsets[0], 'utf-8') 24114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charset = Charset(charsets[0]) 24124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(charset.get_body_encoding(), 'base64') 24134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_payload('hello world', charset=charset) 24144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(), 'aGVsbG8gd29ybGQ=\n') 24154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(decode=True), 'hello world') 24164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-transfer-encoding'], 'base64') 24174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Try another one 24184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 24194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Content-Type'] = 'text/plain; charset="US-ASCII"' 24204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charsets = msg.get_charsets() 24214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(charsets), 1) 24224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(charsets[0], 'us-ascii') 24234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charset = Charset(charsets[0]) 24244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(charset.get_body_encoding(), Encoders.encode_7or8bit) 24254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_payload('hello world', charset=charset) 24264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(), 'hello world') 24274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['content-transfer-encoding'], '7bit') 24284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 24294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_charsets_case_insensitive(self): 24304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lc = Charset('us-ascii') 24314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm uc = Charset('US-ASCII') 24324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(lc.get_body_encoding(), uc.get_body_encoding()) 24334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 24344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_partial_falls_inside_message_delivery_status(self): 24354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 24364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # The Parser interface provides chunks of data to FeedParser in 8192 24374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # byte gulps. SF bug #1076485 found one of those chunks inside 24384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # message/delivery-status header block, which triggered an 24394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # unreadline() of NeedMoreData. 24404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_43.txt') 24414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sfp = StringIO() 24424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Iterators._structure(msg, sfp) 24434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(sfp.getvalue(), """\ 24444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmmultipart/report 24454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm message/delivery-status 24474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/plain 24734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text/rfc822-headers 24744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 24754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 24764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 24774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 24784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test the iterator/generators 24794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestIterators(TestEmailBase): 24804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_body_line_iterator(self): 24814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 24824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm neq = self.ndiffAssertEqual 24834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # First a simple non-multipart message 24844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_01.txt') 24854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm it = Iterators.body_line_iterator(msg) 24864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lines = list(it) 24874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(lines), 6) 24884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm neq(EMPTYSTRING.join(lines), msg.get_payload()) 24894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Now a more complicated multipart 24904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_02.txt') 24914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm it = Iterators.body_line_iterator(msg) 24924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lines = list(it) 24934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(lines), 43) 24944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('msg_19.txt') 24954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 24964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm neq(EMPTYSTRING.join(lines), fp.read()) 24974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 24984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 24994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 25004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_typed_subpart_iterator(self): 25014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 25024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_04.txt') 25034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm it = Iterators.typed_subpart_iterator(msg, 'text') 25044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lines = [] 25054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subparts = 0 25064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for subpart in it: 25074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subparts += 1 25084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lines.append(subpart.get_payload()) 25094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subparts, 2) 25104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(EMPTYSTRING.join(lines), """\ 25114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylma simple kind of mirror 25124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmto reflect upon our own 25134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylma simple kind of mirror 25144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmto reflect upon our own 25154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 25164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 25174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_typed_subpart_iterator_default_type(self): 25184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 25194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_03.txt') 25204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm it = Iterators.typed_subpart_iterator(msg, 'text', 'plain') 25214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lines = [] 25224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subparts = 0 25234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for subpart in it: 25244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subparts += 1 25254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lines.append(subpart.get_payload()) 25264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(subparts, 1) 25274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(EMPTYSTRING.join(lines), """\ 25284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 25294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmHi, 25304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 25314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmDo you like this message? 25324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 25334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm-Me 25344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 25354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 25364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_pushCR_LF(self): 25374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm '''FeedParser BufferedSubFile.push() assumed it received complete 25384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm line endings. A CR ending one push() followed by a LF starting 25394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm the next push() added an empty line. 25404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ''' 25414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm imt = [ 25424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ("a\r \n", 2), 25434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ("b", 0), 25444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ("c\n", 1), 25454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ("", 0), 25464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ("d\r\n", 1), 25474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ("e\r", 0), 25484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ("\nf", 1), 25494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ("\r\n", 1), 25504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ] 25514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm from email.feedparser import BufferedSubFile, NeedMoreData 25524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm bsf = BufferedSubFile() 25534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm om = [] 25544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm nt = 0 25554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for il, n in imt: 25564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm bsf.push(il) 25574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm nt += n 25584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm n1 = 0 25594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm while True: 25604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ol = bsf.readline() 25614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if ol == NeedMoreData: 25624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break 25634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm om.append(ol) 25644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm n1 += 1 25654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(n == n1) 25664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(len(om) == nt) 25674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(''.join([il for il, n in imt]) == ''.join(om)) 25684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 25694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 25704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 25714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestParsers(TestEmailBase): 25724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_header_parser(self): 25734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 25744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Parse only the headers of a complex multipart MIME document 25754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('msg_02.txt') 25764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 25774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = HeaderParser().parse(fp) 25784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 25794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 25804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['from'], 'ppp-request@zzz.org') 25814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['to'], 'ppp@zzz.org') 25824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_type(), 'multipart/mixed') 25834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertFalse(msg.is_multipart()) 25844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(isinstance(msg.get_payload(), str)) 25854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 25864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_whitespace_continuation(self): 25874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 25884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # This message contains a line after the Subject: header that has only 25894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # whitespace, but it is not empty! 25904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string("""\ 25914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: aperson@dom.ain 25924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTo: bperson@dom.ain 25934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: the next line has a space on it 25944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\x20 25954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmDate: Mon, 8 Apr 2002 15:09:19 -0400 25964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMessage-ID: spam 25974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 25984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmHere's the message body 25994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 26004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['subject'], 'the next line has a space on it\n ') 26014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['message-id'], 'spam') 26024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(), "Here's the message body\n") 26034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 26044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_whitespace_continuation_last_header(self): 26054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 26064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Like the previous test, but the subject line is the last 26074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # header. 26084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string("""\ 26094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: aperson@dom.ain 26104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTo: bperson@dom.ain 26114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmDate: Mon, 8 Apr 2002 15:09:19 -0400 26124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMessage-ID: spam 26134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: the next line has a space on it 26144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\x20 26154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 26164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmHere's the message body 26174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 26184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['subject'], 'the next line has a space on it\n ') 26194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg['message-id'], 'spam') 26204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(), "Here's the message body\n") 26214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 26224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_crlf_separation(self): 26234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 26244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('msg_26.txt', mode='rb') 26254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 26264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Parser().parse(fp) 26274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 26284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 26294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(msg.get_payload()), 2) 26304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm part1 = msg.get_payload(0) 26314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(part1.get_content_type(), 'text/plain') 26324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(part1.get_payload(), 'Simple email with attachment.\r\n\r\n') 26334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm part2 = msg.get_payload(1) 26344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(part2.get_content_type(), 'application/riscos') 26354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 26364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_multipart_digest_with_extra_mime_headers(self): 26374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 26384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm neq = self.ndiffAssertEqual 26394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile('msg_28.txt') 26404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 26414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_file(fp) 26424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 26434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 26444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Structure is: 26454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # multipart/digest 26464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # message/rfc822 26474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # text/plain 26484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # message/rfc822 26494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # text/plain 26504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.is_multipart(), 1) 26514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(msg.get_payload()), 2) 26524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm part1 = msg.get_payload(0) 26534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(part1.get_content_type(), 'message/rfc822') 26544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(part1.is_multipart(), 1) 26554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(part1.get_payload()), 1) 26564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm part1a = part1.get_payload(0) 26574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(part1a.is_multipart(), 0) 26584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(part1a.get_content_type(), 'text/plain') 26594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm neq(part1a.get_payload(), 'message 1\n') 26604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # next message/rfc822 26614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm part2 = msg.get_payload(1) 26624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(part2.get_content_type(), 'message/rfc822') 26634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(part2.is_multipart(), 1) 26644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(part2.get_payload()), 1) 26654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm part2a = part2.get_payload(0) 26664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(part2a.is_multipart(), 0) 26674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(part2a.get_content_type(), 'text/plain') 26684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm neq(part2a.get_payload(), 'message 2\n') 26694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 26704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_three_lines(self): 26714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # A bug report by Andrew McNamara 26724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lines = ['From: Andrew Person <aperson@dom.ain', 26734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'Subject: Test', 26744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'Date: Tue, 20 Aug 2002 16:43:45 +1000'] 26754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(NL.join(lines)) 26764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg['date'], 'Tue, 20 Aug 2002 16:43:45 +1000') 26774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 26784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_strip_line_feed_and_carriage_return_in_headers(self): 26794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 26804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # For [ 1002475 ] email message parser doesn't handle \r\n correctly 26814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm value1 = 'text' 26824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm value2 = 'more text' 26834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = 'Header: %s\r\nNext-Header: %s\r\n\r\nBody\r\n\r\n' % ( 26844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm value1, value2) 26854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 26864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get('Header'), value1) 26874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get('Next-Header'), value2) 26884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 26894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2822_header_syntax(self): 26904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 26914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = '>From: foo\nFrom: bar\n!"#QUX;~: zoo\n\nbody' 26924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 26934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(msg.keys()), 3) 26944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm keys = msg.keys() 26954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm keys.sort() 26964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(keys, ['!"#QUX;~', '>From', 'From']) 26974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(), 'body') 26984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 26994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2822_space_not_allowed_in_header(self): 27004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 27014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = '>From foo@example.com 11:25:53\nFrom: bar\n!"#QUX;~: zoo\n\nbody' 27024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 27034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(len(msg.keys()), 0) 27044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 27054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2822_one_character_header(self): 27064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 27074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = 'A: first header\nB: second header\nCC: third header\n\nbody' 27084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 27094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm headers = msg.keys() 27104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm headers.sort() 27114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(headers, ['A', 'B', 'CC']) 27124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_payload(), 'body') 27134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 27144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_CRLFLF_at_end_of_part(self): 27154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # issue 5610: feedparser should not eat two chars from body part ending 27164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # with "\r\n\n". 27174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = ( 27184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "From: foo@bar.com\n" 27194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "To: baz\n" 27204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Mime-Version: 1.0\n" 27214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Content-Type: multipart/mixed; boundary=BOUNDARY\n" 27224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "\n" 27234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "--BOUNDARY\n" 27244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Content-Type: text/plain\n" 27254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "\n" 27264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "body ending with CRLF newline\r\n" 27274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "\n" 27284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "--BOUNDARY--\n" 27294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ) 27304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 27314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(msg.get_payload(0).get_payload().endswith('\r\n')) 27324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 27334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 27344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestBase64(unittest.TestCase): 27354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_len(self): 27364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 27374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(base64MIME.base64_len('hello'), 27384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm len(base64MIME.encode('hello', eol=''))) 27394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for size in range(15): 27404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if size == 0 : bsize = 0 27414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm elif size <= 3 : bsize = 4 27424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm elif size <= 6 : bsize = 8 27434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm elif size <= 9 : bsize = 12 27444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm elif size <= 12: bsize = 16 27454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else : bsize = 20 27464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(base64MIME.base64_len('x'*size), bsize) 27474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 27484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_decode(self): 27494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 27504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(base64MIME.decode(''), '') 27514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(base64MIME.decode('aGVsbG8='), 'hello') 27524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(base64MIME.decode('aGVsbG8=', 'X'), 'hello') 27534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(base64MIME.decode('aGVsbG8NCndvcmxk\n', 'X'), 'helloXworld') 27544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 27554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_encode(self): 27564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 27574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(base64MIME.encode(''), '') 27584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(base64MIME.encode('hello'), 'aGVsbG8=\n') 27594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the binary flag 27604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(base64MIME.encode('hello\n'), 'aGVsbG8K\n') 27614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(base64MIME.encode('hello\n', 0), 'aGVsbG8NCg==\n') 27624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the maxlinelen arg 27634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(base64MIME.encode('xxxx ' * 20, maxlinelen=40), """\ 27644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmeHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg 27654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmeHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg 27664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmeHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg 27674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmeHh4eCB4eHh4IA== 27684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 27694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the eol argument 27704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(base64MIME.encode('xxxx ' * 20, maxlinelen=40, eol='\r\n'), """\ 27714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmeHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg\r 27724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmeHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg\r 27734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmeHh4eCB4eHh4IHh4eHggeHh4eCB4eHh4IHh4eHgg\r 27744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmeHh4eCB4eHh4IA==\r 27754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 27764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 27774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_header_encode(self): 27784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 27794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm he = base64MIME.header_encode 27804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(he('hello'), '=?iso-8859-1?b?aGVsbG8=?=') 27814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(he('hello\nworld'), '=?iso-8859-1?b?aGVsbG8NCndvcmxk?=') 27824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the charset option 27834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(he('hello', charset='iso-8859-2'), '=?iso-8859-2?b?aGVsbG8=?=') 27844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the keep_eols flag 27854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(he('hello\nworld', keep_eols=True), 27864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm '=?iso-8859-1?b?aGVsbG8Kd29ybGQ=?=') 27874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the maxlinelen argument 27884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(he('xxxx ' * 20, maxlinelen=40), """\ 27894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm=?iso-8859-1?b?eHh4eCB4eHh4IHh4eHggeHg=?= 27904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?b?eHggeHh4eCB4eHh4IHh4eHg=?= 27914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?b?IHh4eHggeHh4eCB4eHh4IHg=?= 27924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?b?eHh4IHh4eHggeHh4eCB4eHg=?= 27934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?b?eCB4eHh4IHh4eHggeHh4eCA=?= 27944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?b?eHh4eCB4eHh4IHh4eHgg?=""") 27954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the eol argument 27964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(he('xxxx ' * 20, maxlinelen=40, eol='\r\n'), """\ 27974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm=?iso-8859-1?b?eHh4eCB4eHh4IHh4eHggeHg=?=\r 27984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?b?eHggeHh4eCB4eHh4IHh4eHg=?=\r 27994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?b?IHh4eHggeHh4eCB4eHh4IHg=?=\r 28004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?b?eHh4IHh4eHggeHh4eCB4eHg=?=\r 28014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?b?eCB4eHh4IHh4eHggeHh4eCA=?=\r 28024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?b?eHh4eCB4eHh4IHh4eHgg?=""") 28034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 28044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 28054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 28064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestQuopri(unittest.TestCase): 28074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def setUp(self): 28084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.hlit = [chr(x) for x in range(ord('a'), ord('z')+1)] + \ 28094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm [chr(x) for x in range(ord('A'), ord('Z')+1)] + \ 28104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm [chr(x) for x in range(ord('0'), ord('9')+1)] + \ 28114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ['!', '*', '+', '-', '/', ' '] 28124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.hnon = [chr(x) for x in range(256) if chr(x) not in self.hlit] 28134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm assert len(self.hlit) + len(self.hnon) == 256 28144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.blit = [chr(x) for x in range(ord(' '), ord('~')+1)] + ['\t'] 28154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.blit.remove('=') 28164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.bnon = [chr(x) for x in range(256) if chr(x) not in self.blit] 28174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm assert len(self.blit) + len(self.bnon) == 256 28184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 28194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_header_quopri_check(self): 28204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for c in self.hlit: 28214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertFalse(quopriMIME.header_quopri_check(c)) 28224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for c in self.hnon: 28234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(quopriMIME.header_quopri_check(c)) 28244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 28254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_body_quopri_check(self): 28264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for c in self.blit: 28274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertFalse(quopriMIME.body_quopri_check(c)) 28284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for c in self.bnon: 28294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(quopriMIME.body_quopri_check(c)) 28304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 28314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_header_quopri_len(self): 28324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 28334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm hql = quopriMIME.header_quopri_len 28344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm enc = quopriMIME.header_encode 28354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for s in ('hello', 'h@e@l@l@o@'): 28364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Empty charset and no line-endings. 7 == RFC chrome 28374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(hql(s), len(enc(s, charset='', eol=''))-7) 28384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for c in self.hlit: 28394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(hql(c), 1) 28404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for c in self.hnon: 28414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(hql(c), 3) 28424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 28434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_body_quopri_len(self): 28444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 28454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm bql = quopriMIME.body_quopri_len 28464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for c in self.blit: 28474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(bql(c), 1) 28484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for c in self.bnon: 28494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(bql(c), 3) 28504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 28514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_quote_unquote_idempotent(self): 28524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for x in range(256): 28534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm c = chr(x) 28544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(quopriMIME.unquote(quopriMIME.quote(c)), c) 28554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 28564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_header_encode(self): 28574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 28584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm he = quopriMIME.header_encode 28594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(he('hello'), '=?iso-8859-1?q?hello?=') 28604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(he('hello\nworld'), '=?iso-8859-1?q?hello=0D=0Aworld?=') 28614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the charset option 28624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(he('hello', charset='iso-8859-2'), '=?iso-8859-2?q?hello?=') 28634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the keep_eols flag 28644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(he('hello\nworld', keep_eols=True), '=?iso-8859-1?q?hello=0Aworld?=') 28654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test a non-ASCII character 28664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(he('hello\xc7there'), '=?iso-8859-1?q?hello=C7there?=') 28674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the maxlinelen argument 28684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(he('xxxx ' * 20, maxlinelen=40), """\ 28694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm=?iso-8859-1?q?xxxx_xxxx_xxxx_xxxx_xx?= 28704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?xx_xxxx_xxxx_xxxx_xxxx?= 28714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?_xxxx_xxxx_xxxx_xxxx_x?= 28724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?xxx_xxxx_xxxx_xxxx_xxx?= 28734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?x_xxxx_xxxx_?=""") 28744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the eol argument 28754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(he('xxxx ' * 20, maxlinelen=40, eol='\r\n'), """\ 28764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm=?iso-8859-1?q?xxxx_xxxx_xxxx_xxxx_xx?=\r 28774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?xx_xxxx_xxxx_xxxx_xxxx?=\r 28784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?_xxxx_xxxx_xxxx_xxxx_x?=\r 28794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?xxx_xxxx_xxxx_xxxx_xxx?=\r 28804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?x_xxxx_xxxx_?=""") 28814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 28824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_decode(self): 28834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 28844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(quopriMIME.decode(''), '') 28854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(quopriMIME.decode('hello'), 'hello') 28864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(quopriMIME.decode('hello', 'X'), 'hello') 28874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(quopriMIME.decode('hello\nworld', 'X'), 'helloXworld') 28884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 28894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_encode(self): 28904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 28914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(quopriMIME.encode(''), '') 28924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(quopriMIME.encode('hello'), 'hello') 28934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the binary flag 28944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(quopriMIME.encode('hello\r\nworld'), 'hello\nworld') 28954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(quopriMIME.encode('hello\r\nworld', 0), 'hello\nworld') 28964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the maxlinelen arg 28974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(quopriMIME.encode('xxxx ' * 20, maxlinelen=40), """\ 28984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmxxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx= 28994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxx= 29004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmx xxxx xxxx xxxx xxxx=20""") 29014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test the eol argument 29024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(quopriMIME.encode('xxxx ' * 20, maxlinelen=40, eol='\r\n'), """\ 29034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmxxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx=\r 29044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxx=\r 29054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmx xxxx xxxx xxxx xxxx=20""") 29064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(quopriMIME.encode("""\ 29074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmone line 29084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 29094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtwo line"""), """\ 29104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmone line 29114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 29124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtwo line""") 29134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 29144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 29154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 29164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test the Charset class 29174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestCharset(unittest.TestCase): 29184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def tearDown(self): 29194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm from email import Charset as CharsetModule 29204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 29214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm del CharsetModule.CHARSETS['fake'] 29224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except KeyError: 29234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 29244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 29254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_idempotent(self): 29264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 29274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Make sure us-ascii = no Unicode conversion 29284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm c = Charset('us-ascii') 29294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = 'Hello World!' 29304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sp = c.to_splittable(s) 29314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(s, c.from_splittable(sp)) 29324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # test 8-bit idempotency with us-ascii 29334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = '\xa4\xa2\xa4\xa4\xa4\xa6\xa4\xa8\xa4\xaa' 29344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sp = c.to_splittable(s) 29354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(s, c.from_splittable(sp)) 29364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 29374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_body_encode(self): 29384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 29394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Try a charset with QP body encoding 29404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm c = Charset('iso-8859-1') 29414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq('hello w=F6rld', c.body_encode('hello w\xf6rld')) 29424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Try a charset with Base64 body encoding 29434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm c = Charset('utf-8') 29444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq('aGVsbG8gd29ybGQ=\n', c.body_encode('hello world')) 29454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Try a charset with None body encoding 29464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm c = Charset('us-ascii') 29474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq('hello world', c.body_encode('hello world')) 29484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Try the convert argument, where input codec != output codec 29494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm c = Charset('euc-jp') 29504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # With apologies to Tokio Kikuchi ;) 29514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 29524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq('\x1b$B5FCO;~IW\x1b(B', 29534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm c.body_encode('\xb5\xc6\xc3\xcf\xbb\xfe\xc9\xd7')) 29544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq('\xb5\xc6\xc3\xcf\xbb\xfe\xc9\xd7', 29554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm c.body_encode('\xb5\xc6\xc3\xcf\xbb\xfe\xc9\xd7', False)) 29564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except LookupError: 29574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # We probably don't have the Japanese codecs installed 29584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 29594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Testing SF bug #625509, which we have to fake, since there are no 29604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # built-in encodings where the header encoding is QP but the body 29614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # encoding is not. 29624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm from email import Charset as CharsetModule 29634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm CharsetModule.add_charset('fake', CharsetModule.QP, None) 29644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm c = Charset('fake') 29654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq('hello w\xf6rld', c.body_encode('hello w\xf6rld')) 29664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 29674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_unicode_charset_name(self): 29684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charset = Charset(u'us-ascii') 29694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(str(charset), 'us-ascii') 29704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertRaises(Errors.CharsetError, Charset, 'asc\xffii') 29714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 29724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_codecs_aliases_accepted(self): 29734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charset = Charset('utf8') 29744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(str(charset), 'utf-8') 29754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 29764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 29774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test multilingual MIME headers. 29784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestHeader(TestEmailBase): 29794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_simple(self): 29804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 29814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header('Hello World!') 29824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), 'Hello World!') 29834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h.append(' Goodbye World!') 29844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), 'Hello World! Goodbye World!') 29854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 29864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_simple_surprise(self): 29874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 29884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header('Hello World!') 29894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), 'Hello World!') 29904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h.append('Goodbye World!') 29914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), 'Hello World! Goodbye World!') 29924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 29934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_header_needs_no_decoding(self): 29944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = 'no decoding needed' 29954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(decode_header(h), [(h, None)]) 29964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 29974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_long(self): 29984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 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.", 29994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm maxlinelen=76) 30004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for l in h.encode(splitchars=' ').split('\n '): 30014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(len(l) <= 76) 30024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 30034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_multilingual(self): 30044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 30054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm g = Charset("iso-8859-1") 30064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm cz = Charset("iso-8859-2") 30074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm utf8 = Charset("utf-8") 30084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 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. " 30094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm cz_head = "Finan\xe8ni metropole se hroutily pod tlakem jejich d\xf9vtipu.. " 30104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 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") 30114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header(g_head, g) 30124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h.append(cz_head, cz) 30134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h.append(utf8_head, utf8) 30144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm enc = h.encode() 30154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(enc, """\ 30164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm=?iso-8859-1?q?Die_Mieter_treten_hier_ein_werden_mit_einem_Foerderband_ko?= 30174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?mfortabel_den_Korridor_entlang=2C_an_s=FCdl=FCndischen_Wan?= 30184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?dgem=E4lden_vorbei=2C_gegen_die_rotierenden_Klingen_bef=F6?= 30194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-1?q?rdert=2E_?= =?iso-8859-2?q?Finan=E8ni_metropole_se_hroutily?= 30204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?iso-8859-2?q?_pod_tlakem_jejich_d=F9vtipu=2E=2E_?= =?utf-8?b?5q2j56K6?= 30214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?b?44Gr6KiA44GG44Go57+76Kiz44Gv44GV44KM44Gm44GE44G+44Gb44KT44CC?= 30224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?b?5LiA6YOo44Gv44OJ44Kk44OE6Kqe44Gn44GZ44GM44CB44GC44Go44Gv44Gn?= 30234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?b?44Gf44KJ44KB44Gn44GZ44CC5a6f6Zqb44Gr44Gv44CMV2VubiBpc3QgZGFz?= 30244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?q?_Nunstuck_git_und_Slotermeyer=3F_Ja!_Beiherhund_das_Oder_die_Fl?= 30254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?b?aXBwZXJ3YWxkdCBnZXJzcHV0LuOAjeOBqOiogOOBo+OBpuOBhOOBvuOBmQ==?= 30264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm =?utf-8?b?44CC?=""") 30274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(decode_header(enc), 30284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm [(g_head, "iso-8859-1"), (cz_head, "iso-8859-2"), 30294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (utf8_head, "utf-8")]) 30304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ustr = unicode(h) 30314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(ustr.encode('utf-8'), 30324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'Die Mieter treten hier ein werden mit einem Foerderband ' 30334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'komfortabel den Korridor entlang, an s\xc3\xbcdl\xc3\xbcndischen ' 30344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'Wandgem\xc3\xa4lden vorbei, gegen die rotierenden Klingen ' 30354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'bef\xc3\xb6rdert. Finan\xc4\x8dni metropole se hroutily pod ' 30364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'tlakem jejich d\xc5\xafvtipu.. \xe6\xad\xa3\xe7\xa2\xba\xe3\x81' 30374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm '\xab\xe8\xa8\x80\xe3\x81\x86\xe3\x81\xa8\xe7\xbf\xbb\xe8\xa8\xb3' 30384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm '\xe3\x81\xaf\xe3\x81\x95\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x84\xe3' 30394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm '\x81\xbe\xe3\x81\x9b\xe3\x82\x93\xe3\x80\x82\xe4\xb8\x80\xe9\x83' 30404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm '\xa8\xe3\x81\xaf\xe3\x83\x89\xe3\x82\xa4\xe3\x83\x84\xe8\xaa\x9e' 30414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm '\xe3\x81\xa7\xe3\x81\x99\xe3\x81\x8c\xe3\x80\x81\xe3\x81\x82\xe3' 30424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm '\x81\xa8\xe3\x81\xaf\xe3\x81\xa7\xe3\x81\x9f\xe3\x82\x89\xe3\x82' 30434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm '\x81\xe3\x81\xa7\xe3\x81\x99\xe3\x80\x82\xe5\xae\x9f\xe9\x9a\x9b' 30444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm '\xe3\x81\xab\xe3\x81\xaf\xe3\x80\x8cWenn ist das Nunstuck git ' 30454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt ' 30464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'gersput.\xe3\x80\x8d\xe3\x81\xa8\xe8\xa8\x80\xe3\x81\xa3\xe3\x81' 30474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm '\xa6\xe3\x81\x84\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82') 30484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Test make_header() 30494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm newh = make_header(decode_header(enc)) 30504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(newh, enc) 30514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 30524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_header_ctor_default_args(self): 30534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 30544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header() 30554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h, '') 30564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h.append('foo', Charset('iso-8859-1')) 30574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h, '=?iso-8859-1?q?foo?=') 30584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 30594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_explicit_maxlinelen(self): 30604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 30614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm hstr = 'A very long line that must get split to something other than at the 76th character boundary to test the non-default behavior' 30624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header(hstr) 30634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), '''\ 30644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmA very long line that must get split to something other than at the 76th 30654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm character boundary to test the non-default behavior''') 30664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header(hstr, header_name='Subject') 30674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), '''\ 30684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmA very long line that must get split to something other than at the 30694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 76th character boundary to test the non-default behavior''') 30704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header(hstr, maxlinelen=1024, header_name='Subject') 30714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), hstr) 30724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 30734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_us_ascii_header(self): 30744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 30754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = 'hello' 30764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm x = decode_header(s) 30774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(x, [('hello', None)]) 30784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = make_header(x) 30794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(s, h.encode()) 30804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 30814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_string_charset(self): 30824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 30834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header() 30844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h.append('hello', 'iso-8859-1') 30854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h, '=?iso-8859-1?q?hello?=') 30864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 30874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm## def test_unicode_error(self): 30884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm## raises = self.assertRaises 30894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm## raises(UnicodeError, Header, u'[P\xf6stal]', 'us-ascii') 30904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm## raises(UnicodeError, Header, '[P\xf6stal]', 'us-ascii') 30914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm## h = Header() 30924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm## raises(UnicodeError, h.append, u'[P\xf6stal]', 'us-ascii') 30934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm## raises(UnicodeError, h.append, '[P\xf6stal]', 'us-ascii') 30944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm## raises(UnicodeError, Header, u'\u83ca\u5730\u6642\u592b', 'iso-8859-1') 30954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 30964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_utf8_shortest(self): 30974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 30984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header(u'p\xf6stal', 'utf-8') 30994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), '=?utf-8?q?p=C3=B6stal?=') 31004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header(u'\u83ca\u5730\u6642\u592b', 'utf-8') 31014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), '=?utf-8?b?6I+K5Zyw5pmC5aSr?=') 31024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 31034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_bad_8bit_header(self): 31044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raises = self.assertRaises 31054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 31064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm x = 'Ynwp4dUEbay Auction Semiar- No Charge \x96 Earn Big' 31074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raises(UnicodeError, Header, x) 31084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header() 31094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raises(UnicodeError, h.append, x) 31104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(str(Header(x, errors='replace')), x) 31114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h.append(x, errors='replace') 31124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(str(h), x) 31134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 31144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_encoded_adjacent_nonencoded(self): 31154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 31164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = Header() 31174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h.append('hello', 'iso-8859-1') 31184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h.append('world') 31194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = h.encode() 31204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(s, '=?iso-8859-1?q?hello?= world') 31214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm h = make_header(decode_header(s)) 31224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(h.encode(), s) 31234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 31244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_whitespace_eater(self): 31254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 31264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = 'Subject: =?koi8-r?b?8NLP18XSy8EgzsEgxsnOwczYztk=?= =?koi8-r?q?=CA?= zz.' 31274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm parts = decode_header(s) 31284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 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)]) 31294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm hdr = make_header(parts) 31304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(hdr.encode(), 31314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'Subject: =?koi8-r?b?8NLP18XSy8EgzsEgxsnOwczYztnK?= zz.') 31324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 31334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_broken_base64_header(self): 31344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raises = self.assertRaises 31354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = 'Subject: =?EUC-KR?B?CSixpLDtKSC/7Liuvsax4iC6uLmwMcijIKHaILzSwd/H0SC8+LCjwLsgv7W/+Mj3I ?=' 31364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raises(Errors.HeaderParseError, decode_header, s) 31374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 31384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Issue 1078919 31394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_ascii_add_header(self): 31404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 31414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.add_header('Content-Disposition', 'attachment', 31424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm filename='bud.gif') 31434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual('attachment; filename="bud.gif"', 31444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Content-Disposition']) 31454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 31464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_nonascii_add_header_via_triple(self): 31474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 31484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.add_header('Content-Disposition', 'attachment', 31494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm filename=('iso-8859-1', '', 'Fu\xdfballer.ppt')) 31504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual( 31514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'attachment; filename*="iso-8859-1\'\'Fu%DFballer.ppt"', 31524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg['Content-Disposition']) 31534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 31544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_encode_unaliased_charset(self): 31554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Issue 1379416: when the charset has no output conversion, 31564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # output was accidentally getting coerced to unicode. 31574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm res = Header('abc','iso-8859-2').encode() 31584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(res, '=?iso-8859-2?q?abc?=') 31594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertIsInstance(res, str) 31604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 31614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 31624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test RFC 2231 header parameters (en/de)coding 31634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestRFC2231(TestEmailBase): 31644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_get_param(self): 31654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 31664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_29.txt') 31674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('title'), 31684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('us-ascii', 'en', 'This is even more ***fun*** isn\'t it!')) 31694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('title', unquote=False), 31704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('us-ascii', 'en', '"This is even more ***fun*** isn\'t it!"')) 31714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 31724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_set_param(self): 31734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 31744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = Message() 31754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_param('title', 'This is even more ***fun*** isn\'t it!', 31764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charset='us-ascii') 31774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('title'), 31784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('us-ascii', '', 'This is even more ***fun*** isn\'t it!')) 31794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_param('title', 'This is even more ***fun*** isn\'t it!', 31804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charset='us-ascii', language='en') 31814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('title'), 31824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ('us-ascii', 'en', 'This is even more ***fun*** isn\'t it!')) 31834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_01.txt') 31844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_param('title', 'This is even more ***fun*** isn\'t it!', 31854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charset='us-ascii', language='en') 31864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.ndiffAssertEqual(msg.as_string(), """\ 31874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReturn-Path: <bbb@zzz.org> 31884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmDelivered-To: bbb@zzz.org 31894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReceived: by mail.zzz.org (Postfix, from userid 889) 31904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) 31914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 31924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 7bit 31934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMessage-ID: <15090.61304.110929.45684@aaa.zzz.org> 31944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: bbb@ddd.com (John X. Doe) 31954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTo: bbb@zzz.org 31964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: This is a test message 31974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmDate: Fri, 4 May 2001 14:05:44 -0400 31984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset=us-ascii; 31994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm title*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21" 32004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmHi, 32034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmDo you like this message? 32054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm-Me 32074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 32084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_del_param(self): 32104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.ndiffAssertEqual 32114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_01.txt') 32124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_param('foo', 'bar', charset='us-ascii', language='en') 32134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.set_param('title', 'This is even more ***fun*** isn\'t it!', 32144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charset='us-ascii', language='en') 32154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.del_param('foo', header='Content-Type') 32164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.as_string(), """\ 32174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReturn-Path: <bbb@zzz.org> 32184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmDelivered-To: bbb@zzz.org 32194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReceived: by mail.zzz.org (Postfix, from userid 889) 32204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT) 32214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMIME-Version: 1.0 32224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 7bit 32234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmMessage-ID: <15090.61304.110929.45684@aaa.zzz.org> 32244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmFrom: bbb@ddd.com (John X. Doe) 32254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmTo: bbb@zzz.org 32264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSubject: This is a test message 32274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmDate: Fri, 4 May 2001 14:05:44 -0400 32284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset="us-ascii"; 32294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm title*="us-ascii'en'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20isn%27t%20it%21" 32304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmHi, 32334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmDo you like this message? 32354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm-Me 32374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""") 32384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_get_content_charset(self): 32404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 32414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = self._msgobj('msg_32.txt') 32424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_content_charset(), 'us-ascii') 32434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_no_language_or_charset(self): 32454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = '''\ 32464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 8bit 32474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Disposition: inline; filename="file____C__DOCUMENTS_20AND_20SETTINGS_FABIEN_LOCAL_20SETTINGS_TEMP_nsmail.htm" 32484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/html; NAME*0=file____C__DOCUMENTS_20AND_20SETTINGS_FABIEN_LOCAL_20SETTINGS_TEM; NAME*1=P_nsmail.htm 32494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''' 32514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 32524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm param = msg.get_param('NAME') 32534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertFalse(isinstance(param, tuple)) 32544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual( 32554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm param, 32564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'file____C__DOCUMENTS_20AND_20SETTINGS_FABIEN_LOCAL_20SETTINGS_TEMP_nsmail.htm') 32574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_no_language_or_charset_in_filename(self): 32594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = '''\ 32604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Disposition: inline; 32614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*0*="''This%20is%20even%20more%20"; 32624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; 32634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*2="is it not.pdf" 32644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''' 32664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 32674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_filename(), 32684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'This is even more ***fun*** is it not.pdf') 32694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_no_language_or_charset_in_filename_encoded(self): 32714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = '''\ 32724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Disposition: inline; 32734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*0*="''This%20is%20even%20more%20"; 32744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; 32754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*2="is it not.pdf" 32764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''' 32784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 32794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_filename(), 32804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'This is even more ***fun*** is it not.pdf') 32814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_partly_encoded(self): 32834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = '''\ 32844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Disposition: inline; 32854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*0="''This%20is%20even%20more%20"; 32864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; 32874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*2="is it not.pdf" 32884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''' 32904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 32914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual( 32924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.get_filename(), 32934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'This%20is%20even%20more%20***fun*** is it not.pdf') 32944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 32954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_partly_nonencoded(self): 32964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = '''\ 32974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Disposition: inline; 32984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*0="This%20is%20even%20more%20"; 32994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*1="%2A%2A%2Afun%2A%2A%2A%20"; 33004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*2="is it not.pdf" 33014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''' 33034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 33044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual( 33054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg.get_filename(), 33064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20is it not.pdf') 33074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_no_language_or_charset_in_boundary(self): 33094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = '''\ 33104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: multipart/alternative; 33114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tboundary*0*="''This%20is%20even%20more%20"; 33124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tboundary*1*="%2A%2A%2Afun%2A%2A%2A%20"; 33134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tboundary*2="is it not.pdf" 33144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''' 33164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 33174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_boundary(), 33184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'This is even more ***fun*** is it not.pdf') 33194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_no_language_or_charset_in_charset(self): 33214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # This is a nonsensical charset value, but tests the code anyway 33224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = '''\ 33234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; 33244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tcharset*0*="This%20is%20even%20more%20"; 33254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tcharset*1*="%2A%2A%2Afun%2A%2A%2A%20"; 33264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tcharset*2="is it not.pdf" 33274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''' 33294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 33304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_charset(), 33314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'this is even more ***fun*** is it not.pdf') 33324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_bad_encoding_in_filename(self): 33344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = '''\ 33354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Disposition: inline; 33364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*0*="bogus'xx'This%20is%20even%20more%20"; 33374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; 33384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*2="is it not.pdf" 33394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''' 33414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 33424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_filename(), 33434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'This is even more ***fun*** is it not.pdf') 33444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_bad_encoding_in_charset(self): 33464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = """\ 33474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset*=bogus''utf-8%E2%80%9D 33484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 33504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 33514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # This should return None because non-ascii characters in the charset 33524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # are not allowed. 33534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_charset(), None) 33544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_bad_character_in_charset(self): 33564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = """\ 33574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: text/plain; charset*=ascii''utf-8%E2%80%9D 33584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 33604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 33614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # This should return None because non-ascii characters in the charset 33624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # are not allowed. 33634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_content_charset(), None) 33644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_bad_character_in_filename(self): 33664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = '''\ 33674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Disposition: inline; 33684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*0*="ascii'xx'This%20is%20even%20more%20"; 33694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20"; 33704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tfilename*2*="is it not.pdf%E2" 33714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm''' 33734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 33744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_filename(), 33754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm u'This is even more ***fun*** is it not.pdf\ufffd') 33764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_unknown_encoding(self): 33784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = """\ 33794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Transfer-Encoding: 8bit 33804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Disposition: inline; filename*=X-UNKNOWN''myfile.txt 33814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 33834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 33844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(msg.get_filename(), 'myfile.txt') 33854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_single_tick_in_filename_extended(self): 33874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 33884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = """\ 33894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: application/x-foo; 33904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tname*0*=\"Frank's\"; name*1*=\" Document\" 33914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 33934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 33944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charset, language, s = msg.get_param('name') 33954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(charset, None) 33964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(language, None) 33974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(s, "Frank's Document") 33984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 33994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_single_tick_in_filename(self): 34004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = """\ 34014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: application/x-foo; name*0=\"Frank's\"; name*1=\" Document\" 34024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 34044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 34054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm param = msg.get_param('name') 34064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertFalse(isinstance(param, tuple)) 34074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(param, "Frank's Document") 34084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_tick_attack_extended(self): 34104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 34114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = """\ 34124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: application/x-foo; 34134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tname*0*=\"us-ascii'en-us'Frank's\"; name*1*=\" Document\" 34144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 34164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 34174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charset, language, s = msg.get_param('name') 34184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(charset, 'us-ascii') 34194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(language, 'en-us') 34204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(s, "Frank's Document") 34214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_tick_attack(self): 34234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = """\ 34244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: application/x-foo; 34254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tname*0=\"us-ascii'en-us'Frank's\"; name*1=\" Document\" 34264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 34284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 34294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm param = msg.get_param('name') 34304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertFalse(isinstance(param, tuple)) 34314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(param, "us-ascii'en-us'Frank's Document") 34324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_no_extended_values(self): 34344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 34354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = """\ 34364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: application/x-foo; name=\"Frank's Document\" 34374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 34394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 34404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(msg.get_param('name'), "Frank's Document") 34414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_encoded_then_unencoded_segments(self): 34434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 34444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = """\ 34454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: application/x-foo; 34464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tname*0*=\"us-ascii'en-us'My\"; 34474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tname*1=\" Document\"; 34484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tname*2*=\" For You\" 34494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 34514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 34524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charset, language, s = msg.get_param('name') 34534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(charset, 'us-ascii') 34544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(language, 'en-us') 34554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(s, 'My Document For You') 34564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_rfc2231_unencoded_then_encoded_segments(self): 34584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq = self.assertEqual 34594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = """\ 34604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmContent-Type: application/x-foo; 34614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tname*0=\"us-ascii'en-us'My\"; 34624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tname*1*=\" Document\"; 34634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\tname*2*=\" For You\" 34644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 34664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(m) 34674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm charset, language, s = msg.get_param('name') 34684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(charset, 'us-ascii') 34694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(language, 'en-us') 34704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm eq(s, 'My Document For You') 34714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Tests to ensure that signed parts of an email are completely preserved, as 34754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# required by RFC1847 section 2.1. Note that these are incomplete, because the 34764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# email package does not currently always preserve the body. See issue 1670765. 34774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestSigned(TestEmailBase): 34784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _msg_and_obj(self, filename): 34804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = openfile(findfile(filename)) 34814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 34824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm original = fp.read() 34834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msg = email.message_from_string(original) 34844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finally: 34854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp.close() 34864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return original, msg 34874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _signed_parts_eq(self, original, result): 34894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Extract the first mime part of each message 34904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm import re 34914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm repart = re.compile(r'^--([^\n]+)\n(.*?)\n--\1$', re.S | re.M) 34924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm inpart = repart.search(original).group(2) 34934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm outpart = repart.search(result).group(2) 34944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(outpart, inpart) 34954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_long_headers_as_string(self): 34974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm original, msg = self._msg_and_obj('msg_45.txt') 34984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result = msg.as_string() 34994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._signed_parts_eq(original, result) 35004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 35014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_long_headers_flatten(self): 35024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm original, msg = self._msg_and_obj('msg_45.txt') 35034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = StringIO() 35044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Generator(fp).flatten(msg) 35054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result = fp.getvalue() 35064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._signed_parts_eq(original, result) 35074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 35084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 35094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 35104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef _testclasses(): 35114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm mod = sys.modules[__name__] 35124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')] 35134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 35144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 35154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef suite(): 35164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm suite = unittest.TestSuite() 35174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for testclass in _testclasses(): 35184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm suite.addTest(unittest.makeSuite(testclass)) 35194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return suite 35204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 35214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 35224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef test_main(): 35234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for testclass in _testclasses(): 35244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm run_unittest(testclass) 35254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 35264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 35274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 35284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmif __name__ == '__main__': 35294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm unittest.main(defaultTest='suite') 3530