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&amp;&amp;Jill"\n')
3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(msg.get_param('name'), 'Jim&amp;&amp;Jill')
3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(msg.get_param('name', unquote=False),
3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         '"Jim&amp;&amp;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