10b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murrayimport datetime
20b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murrayimport textwrap
30b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murrayimport unittest
40b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murrayfrom email import errors
50b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murrayfrom email import policy
6dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murrayfrom email.message import Message
71be413e366be7bed676074b7f395b2a20a10ac47R David Murrayfrom test.test_email import TestEmailBase, parameterize
8ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murrayfrom email import headerregistry
9ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murrayfrom email.headerregistry import Address, Group
100b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
110b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
1297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David MurrayDITTO = object()
1397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
1497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
150b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murrayclass TestHeaderRegistry(TestEmailBase):
160b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
170b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_arbitrary_name_unstructured(self):
18ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        factory = headerregistry.HeaderRegistry()
190b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = factory('foobar', 'test')
20ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        self.assertIsInstance(h, headerregistry.BaseHeader)
21ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        self.assertIsInstance(h, headerregistry.UnstructuredHeader)
220b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
230b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_name_case_ignored(self):
24ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        factory = headerregistry.HeaderRegistry()
250b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        # Whitebox check that test is valid
260b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertNotIn('Subject', factory.registry)
270b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = factory('Subject', 'test')
28ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        self.assertIsInstance(h, headerregistry.BaseHeader)
29ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        self.assertIsInstance(h, headerregistry.UniqueUnstructuredHeader)
300b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
310b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    class FooBase:
320b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        def __init__(self, *args, **kw):
330b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            pass
340b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
350b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_override_default_base_class(self):
36ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        factory = headerregistry.HeaderRegistry(base_class=self.FooBase)
370b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = factory('foobar', 'test')
380b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertIsInstance(h, self.FooBase)
39ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        self.assertIsInstance(h, headerregistry.UnstructuredHeader)
400b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
410b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    class FooDefault:
42ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        parse = headerregistry.UnstructuredHeader.parse
430b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
440b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_override_default_class(self):
45ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        factory = headerregistry.HeaderRegistry(default_class=self.FooDefault)
460b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = factory('foobar', 'test')
47ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        self.assertIsInstance(h, headerregistry.BaseHeader)
480b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertIsInstance(h, self.FooDefault)
490b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
500b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_override_default_class_only_overrides_default(self):
51ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        factory = headerregistry.HeaderRegistry(default_class=self.FooDefault)
520b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = factory('subject', 'test')
53ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        self.assertIsInstance(h, headerregistry.BaseHeader)
54ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        self.assertIsInstance(h, headerregistry.UniqueUnstructuredHeader)
550b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
560b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_dont_use_default_map(self):
57ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        factory = headerregistry.HeaderRegistry(use_default_map=False)
580b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = factory('subject', 'test')
59ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        self.assertIsInstance(h, headerregistry.BaseHeader)
60ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        self.assertIsInstance(h, headerregistry.UnstructuredHeader)
610b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
620b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_map_to_type(self):
63ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        factory = headerregistry.HeaderRegistry()
640b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h1 = factory('foobar', 'test')
65ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        factory.map_to_type('foobar', headerregistry.UniqueUnstructuredHeader)
660b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h2 = factory('foobar', 'test')
67ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        self.assertIsInstance(h1, headerregistry.BaseHeader)
68ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        self.assertIsInstance(h1, headerregistry.UnstructuredHeader)
69ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        self.assertIsInstance(h2, headerregistry.BaseHeader)
70ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        self.assertIsInstance(h2, headerregistry.UniqueUnstructuredHeader)
710b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
720b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
730b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murrayclass TestHeaderBase(TestEmailBase):
740b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
75ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray    factory = headerregistry.HeaderRegistry()
760b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
770b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def make_header(self, name, value):
780b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        return self.factory(name, value)
790b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
800b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
810b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murrayclass TestBaseHeaderFeatures(TestHeaderBase):
820b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
830b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_str(self):
840b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('subject', 'this is a test')
850b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertIsInstance(h, str)
860b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h, 'this is a test')
870b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(h), 'this is a test')
880b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
890b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_substr(self):
900b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('subject', 'this is a test')
910b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h[5:7], 'is')
920b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
930b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_has_name(self):
940b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('subject', 'this is a test')
950b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.name, 'subject')
960b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
970b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def _test_attr_ro(self, attr):
980b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('subject', 'this is a test')
990b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        with self.assertRaises(AttributeError):
1000b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            setattr(h, attr, 'foo')
1010b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
1020b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_name_read_only(self):
1030b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self._test_attr_ro('name')
1040b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
1050b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_defects_read_only(self):
1060b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self._test_attr_ro('defects')
1070b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
1080b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_defects_is_tuple(self):
1090b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('subject', 'this is a test')
1100b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(len(h.defects), 0)
1110b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertIsInstance(h.defects, tuple)
1120b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        # Make sure it is still true when there are defects.
1130b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('date', '')
1140b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(len(h.defects), 1)
1150b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertIsInstance(h.defects, tuple)
1160b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
1170b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    # XXX: FIXME
1180b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    #def test_CR_in_value(self):
1190b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    #    # XXX: this also re-raises the issue of embedded headers,
1200b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    #    # need test and solution for that.
1210b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    #    value = '\r'.join(['this is', ' a test'])
1220b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    #    h = self.make_header('subject', value)
1230b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    #    self.assertEqual(h, value)
1240b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    #    self.assertDefectsEqual(h.defects, [errors.ObsoleteHeaderDefect])
1250b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
12665171b28e77f589a490335c8749a24151e1d8817R David Murray
12765171b28e77f589a490335c8749a24151e1d8817R David Murray@parameterize
12865171b28e77f589a490335c8749a24151e1d8817R David Murrayclass TestUnstructuredHeader(TestHeaderBase):
12965171b28e77f589a490335c8749a24151e1d8817R David Murray
13065171b28e77f589a490335c8749a24151e1d8817R David Murray    def string_as_value(self,
13165171b28e77f589a490335c8749a24151e1d8817R David Murray                        source,
13265171b28e77f589a490335c8749a24151e1d8817R David Murray                        decoded,
13365171b28e77f589a490335c8749a24151e1d8817R David Murray                        *args):
13465171b28e77f589a490335c8749a24151e1d8817R David Murray        l = len(args)
13565171b28e77f589a490335c8749a24151e1d8817R David Murray        defects = args[0] if l>0 else []
13665171b28e77f589a490335c8749a24151e1d8817R David Murray        header = 'Subject:' + (' ' if source else '')
13765171b28e77f589a490335c8749a24151e1d8817R David Murray        folded = header + (args[1] if l>1 else source) + '\n'
13865171b28e77f589a490335c8749a24151e1d8817R David Murray        h = self.make_header('Subject', source)
13965171b28e77f589a490335c8749a24151e1d8817R David Murray        self.assertEqual(h, decoded)
14065171b28e77f589a490335c8749a24151e1d8817R David Murray        self.assertDefectsEqual(h.defects, defects)
14165171b28e77f589a490335c8749a24151e1d8817R David Murray        self.assertEqual(h.fold(policy=policy.default), folded)
14265171b28e77f589a490335c8749a24151e1d8817R David Murray
14365171b28e77f589a490335c8749a24151e1d8817R David Murray    string_params = {
14465171b28e77f589a490335c8749a24151e1d8817R David Murray
14565171b28e77f589a490335c8749a24151e1d8817R David Murray        'rfc2047_simple_quopri': (
14665171b28e77f589a490335c8749a24151e1d8817R David Murray            '=?utf-8?q?this_is_a_test?=',
14765171b28e77f589a490335c8749a24151e1d8817R David Murray            'this is a test',
14865171b28e77f589a490335c8749a24151e1d8817R David Murray            [],
14965171b28e77f589a490335c8749a24151e1d8817R David Murray            'this is a test'),
15065171b28e77f589a490335c8749a24151e1d8817R David Murray
15165171b28e77f589a490335c8749a24151e1d8817R David Murray        'rfc2047_gb2312_base64': (
15265171b28e77f589a490335c8749a24151e1d8817R David Murray            '=?gb2312?b?1eLKx9bQzsSy4srUo6E=?=',
15365171b28e77f589a490335c8749a24151e1d8817R David Murray            '\u8fd9\u662f\u4e2d\u6587\u6d4b\u8bd5\uff01',
15465171b28e77f589a490335c8749a24151e1d8817R David Murray            [],
15565171b28e77f589a490335c8749a24151e1d8817R David Murray            '=?utf-8?b?6L+Z5piv5Lit5paH5rWL6K+V77yB?='),
15665171b28e77f589a490335c8749a24151e1d8817R David Murray
15765171b28e77f589a490335c8749a24151e1d8817R David Murray        'rfc2047_simple_nonascii_quopri': (
15865171b28e77f589a490335c8749a24151e1d8817R David Murray            '=?utf-8?q?=C3=89ric?=',
15965171b28e77f589a490335c8749a24151e1d8817R David Murray            'Éric'),
16065171b28e77f589a490335c8749a24151e1d8817R David Murray
161923512f327af6944bbdbc905d2372658a3977489R David Murray        'rfc2047_quopri_with_regular_text': (
162923512f327af6944bbdbc905d2372658a3977489R David Murray            'The =?utf-8?q?=C3=89ric=2C?= Himself',
163923512f327af6944bbdbc905d2372658a3977489R David Murray            'The Éric, Himself'),
164923512f327af6944bbdbc905d2372658a3977489R David Murray
16565171b28e77f589a490335c8749a24151e1d8817R David Murray    }
1660b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
1670b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
16865171b28e77f589a490335c8749a24151e1d8817R David Murray@parameterize
1690b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murrayclass TestDateHeader(TestHeaderBase):
1700b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
1710b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    datestring = 'Sun, 23 Sep 2001 20:10:55 -0700'
1720b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    utcoffset = datetime.timedelta(hours=-7)
1730b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    tz = datetime.timezone(utcoffset)
1740b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    dt = datetime.datetime(2001, 9, 23, 20, 10, 55, tzinfo=tz)
1750b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
1760b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_parse_date(self):
1770b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('date', self.datestring)
1780b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h, self.datestring)
1790b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.datetime, self.dt)
1800b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.datetime.utcoffset(), self.utcoffset)
1810b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.defects, ())
1820b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
1830b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_set_from_datetime(self):
1840b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('date', self.dt)
1850b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h, self.datestring)
1860b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.datetime, self.dt)
1870b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.defects, ())
1880b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
1890b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_date_header_properties(self):
1900b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('date', self.datestring)
191ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        self.assertIsInstance(h, headerregistry.UniqueDateHeader)
1920b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.max_count, 1)
1930b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.defects, ())
1940b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
1950b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_resent_date_header_properties(self):
1960b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('resent-date', self.datestring)
197ea9766897bf1d2ccf610ff9ce805acca7c4cce6fR David Murray        self.assertIsInstance(h, headerregistry.DateHeader)
1980b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.max_count, None)
1990b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.defects, ())
2000b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
2010b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_no_value_is_defect(self):
2020b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('date', '')
2030b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(len(h.defects), 1)
2040b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertIsInstance(h.defects[0], errors.HeaderMissingRequiredValue)
2050b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
2060b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_datetime_read_only(self):
2070b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('date', self.datestring)
2080b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        with self.assertRaises(AttributeError):
2090b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            h.datetime = 'foo'
2100b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
211dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray    def test_set_date_header_from_datetime(self):
212dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray        m = Message(policy=policy.default)
213dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray        m['Date'] = self.dt
214dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray        self.assertEqual(m['Date'], self.datestring)
215dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray        self.assertEqual(m['Date'].datetime, self.dt)
216dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray
2170b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
2181be413e366be7bed676074b7f395b2a20a10ac47R David Murray@parameterize
21997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murrayclass TestContentTypeHeader(TestHeaderBase):
22097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
22197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray    def content_type_as_value(self,
22297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                              source,
22397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                              content_type,
22497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                              maintype,
22597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                              subtype,
22697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                              *args):
22797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        l = len(args)
22897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        parmdict = args[0] if l>0 else {}
22997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        defects =  args[1] if l>1 else []
23097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        decoded =  args[2] if l>2 and args[2] is not DITTO else source
23197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        header = 'Content-Type:' + ' ' if source else ''
23297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        folded = args[3] if l>3 else header + source + '\n'
23397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        h = self.make_header('Content-Type', source)
23497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h.content_type, content_type)
23597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h.maintype, maintype)
23697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h.subtype, subtype)
23797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h.params, parmdict)
238685b3495e1fd9853b1ca5960db3e3cb705920d4fR David Murray        with self.assertRaises(TypeError):
239685b3495e1fd9853b1ca5960db3e3cb705920d4fR David Murray            h.params['abc'] = 'xyz'   # params is read-only.
24097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertDefectsEqual(h.defects, defects)
24197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h, decoded)
24297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h.fold(policy=policy.default), folded)
24397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
24497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray    content_type_params = {
24597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
24697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # Examples from RFC 2045.
24797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
24897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'RFC_2045_1': (
24997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; charset=us-ascii (Plain text)',
25097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
25197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
25297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
25397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'charset': 'us-ascii'},
25497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [],
25597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; charset="us-ascii"'),
25697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
25797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'RFC_2045_2': (
25897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; charset=us-ascii',
25997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
26097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
26197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
26297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'charset': 'us-ascii'},
26397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [],
26497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; charset="us-ascii"'),
26597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
26697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'RFC_2045_3': (
26797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; charset="us-ascii"',
26897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
26997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
27097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
27197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'charset': 'us-ascii'}),
27297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
27397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # RFC 2045 5.2 says syntactically invalid values are to be treated as
27497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # text/plain.
27597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
27697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'no_subtype_in_content_type': (
27797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/',
27897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
27997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
28097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
28197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {},
28297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]),
28397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
28497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'no_slash_in_content_type': (
28597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'foo',
28697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
28797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
28897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
28997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {},
29097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]),
29197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
29297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'junk_text_in_content_type': (
29397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '<crazy "stuff">',
29497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
29597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
29697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
29797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {},
29897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]),
29997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
30097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'too_many_slashes_in_content_type': (
30197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image/jpeg/foo',
30297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
30397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
30497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
30597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {},
30697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]),
30797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
30897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # But unknown names are OK.  We could make non-IANA names a defect, but
30997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # by not doing so we make ourselves future proof.  The fact that they
31097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # are unknown will be detectable by the fact that they don't appear in
31197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # the mime_registry...and the application is free to extend that list
31297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # to handle them even if the core library doesn't.
31397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
31497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'unknown_content_type': (
31597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'bad/names',
31697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'bad/names',
31797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'bad',
31897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'names'),
31997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
32097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # The content type is case insensitive, and CFWS is ignored.
32197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
32297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'mixed_case_content_type': (
32397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'ImAge/JPeg',
32497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image/jpeg',
32597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image',
32697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'jpeg'),
32797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
32897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'spaces_in_content_type': (
32997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '  text  /  plain  ',
33097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
33197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
33297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain'),
33397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
33497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'cfws_in_content_type': (
33597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '(foo) text (bar)/(baz)plain(stuff)',
33697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
33797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
33897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain'),
33997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
34097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # test some parameters (more tests could be added for parameters
34197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # associated with other content types, but since parameter parsing is
34297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # generic they would be redundant for the current implementation).
34397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
34497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'charset_param': (
34597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; charset="utf-8"',
34697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
34797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
34897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
34997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'charset': 'utf-8'}),
35097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
35197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'capitalized_charset': (
35297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; charset="US-ASCII"',
35397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
35497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
35597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
35697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'charset': 'US-ASCII'}),
35797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
35897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'unknown_charset': (
35997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; charset="fOo"',
36097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
36197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
36297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
36397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'charset': 'fOo'}),
36497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
36597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'capitalized_charset_param_name_and_comment': (
36697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; (interjection) Charset="utf-8"',
36797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
36897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
36997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
37097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'charset': 'utf-8'},
37197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [],
37297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            # Should the parameter name be lowercased here?
37397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; Charset="utf-8"'),
37497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
37597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # Since this is pretty much the ur-mimeheader, we'll put all the tests
37697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # that exercise the parameter parsing and formatting here.
37797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #
37897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # XXX: question: is minimal quoting preferred?
37997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
38097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'unquoted_param_value': (
38197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; title=foo',
38297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
38397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
38497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
38597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'title': 'foo'},
38697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [],
38797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; title="foo"'),
38897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
38997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'param_value_with_tspecials': (
39097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; title="(bar)foo blue"',
39197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
39297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
39397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
39497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'title': '(bar)foo blue'}),
39597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
39697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'param_with_extra_quoted_whitespace': (
39797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; title="  a     loong  way \t home   "',
39897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
39997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
40097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
40197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'title': '  a     loong  way \t home   '}),
40297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
40397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'bad_params': (
40497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'blarg; baz; boo',
40597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
40697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
40797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
40897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'baz': '', 'boo': ''},
40997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]*3),
41097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
41197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'spaces_around_param_equals': (
41297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'Multipart/mixed; boundary = "CPIMSSMTPC06p5f3tG"',
41397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'multipart/mixed',
41497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'multipart',
41597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'mixed',
41697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'boundary': 'CPIMSSMTPC06p5f3tG'},
41797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [],
41897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'Multipart/mixed; boundary="CPIMSSMTPC06p5f3tG"'),
41997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
42097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'spaces_around_semis': (
42197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('image/jpeg; name="wibble.JPG" ; x-mac-type="4A504547" ; '
42297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                'x-mac-creator="474B4F4E"'),
42397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image/jpeg',
42497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image',
42597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'jpeg',
42697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': 'wibble.JPG',
42797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             'x-mac-type': '4A504547',
42897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             'x-mac-creator': '474B4F4E'},
42997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [],
43097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('image/jpeg; name="wibble.JPG"; x-mac-type="4A504547"; '
43197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                'x-mac-creator="474B4F4E"'),
43297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            # XXX: it could be that we will eventually prefer to fold starting
43397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            # from the decoded value, in which case these spaces and similar
43497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            # spaces in other tests will be wrong.
43597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('Content-Type: image/jpeg; name="wibble.JPG" ; '
43697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                'x-mac-type="4A504547" ;\n'
43797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             ' x-mac-creator="474B4F4E"\n'),
43897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ),
43997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
44097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'semis_inside_quotes': (
44197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image/jpeg; name="Jim&amp;&amp;Jill"',
44297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image/jpeg',
44397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image',
44497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'jpeg',
44597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': 'Jim&amp;&amp;Jill'}),
44697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
44797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'single_quotes_inside_quotes': (
44897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image/jpeg; name="Jim \'Bob\' Jill"',
44997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image/jpeg',
45097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image',
45197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'jpeg',
45297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': "Jim 'Bob' Jill"}),
45397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
45497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'double_quotes_inside_quotes': (
45597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            r'image/jpeg; name="Jim \"Bob\" Jill"',
45697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image/jpeg',
45797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image',
45897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'jpeg',
45997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': 'Jim "Bob" Jill'},
46097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [],
46197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            r'image/jpeg; name="Jim \"Bob\" Jill"'),
46297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
46397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # XXX: This test works except for the refolding of the header.  I'll
46497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # deal with that bug when I deal with the other folding bugs.
46597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #'non_ascii_in_params': (
46697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #    ('foo\xa7/bar; b\xa7r=two; '
46797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #        'baz=thr\xa7e'.encode('latin-1').decode('us-ascii',
46897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #                                                'surrogateescape')),
46997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #    'foo\uFFFD/bar',
47097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #    'foo\uFFFD',
47197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #    'bar',
47297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #    {'b\uFFFDr': 'two', 'baz': 'thr\uFFFDe'},
47397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #    [errors.UndecodableBytesDefect]*3,
47497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #    'foo�/bar; b�r="two"; baz="thr�e"',
47597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #    ),
47697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
47797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # RFC 2231 parameter tests.
47897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
47997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'rfc2231_segmented_normal_values': (
48097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image/jpeg; name*0="abc"; name*1=".html"',
48197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image/jpeg',
48297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image',
48397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'jpeg',
48497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': "abc.html"},
48597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [],
48697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image/jpeg; name="abc.html"'),
48797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
48897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'quotes_inside_rfc2231_value': (
48997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            r'image/jpeg; bar*0="baz\"foobar"; bar*1="\"baz"',
49097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image/jpeg',
49197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'image',
49297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'jpeg',
49397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'bar': 'baz"foobar"baz'},
49497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [],
49597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            r'image/jpeg; bar="baz\"foobar\"baz"'),
49697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
49797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # XXX: This test works except for the refolding of the header.  I'll
49897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # deal with that bug when I deal with the other folding bugs.
49997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #'non_ascii_rfc2231_value': (
50097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #    ('text/plain; charset=us-ascii; '
50197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #     "title*=us-ascii'en'This%20is%20"
50297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #     'not%20f\xa7n').encode('latin-1').decode('us-ascii',
50397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #                                             'surrogateescape'),
50497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #    'text/plain',
50597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #    'text',
50697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #    'plain',
50797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #    {'charset': 'us-ascii', 'title': 'This is not f\uFFFDn'},
50897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #     [errors.UndecodableBytesDefect],
50997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        #     'text/plain; charset="us-ascii"; title="This is not f�n"'),
51097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
51197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'rfc2231_encoded_charset': (
51297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; charset*=ansi-x3.4-1968\'\'us-ascii',
51397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
51497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
51597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
51697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'charset': 'us-ascii'},
51797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [],
51897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; charset="us-ascii"'),
51997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
52097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # This follows the RFC: no double quotes around encoded values.
52197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'rfc2231_encoded_no_double_quotes': (
52297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ("text/plain;"
52397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                "\tname*0*=''This%20is%20;"
52497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                "\tname*1*=%2A%2A%2Afun%2A%2A%2A%20;"
52597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*2="is it not.pdf"'),
52697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
52797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
52897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
52997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': 'This is ***fun*** is it not.pdf'},
53097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [],
53197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; name="This is ***fun*** is it not.pdf"',
53297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('Content-Type: text/plain;\tname*0*=\'\'This%20is%20;\n'
53397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             '\tname*1*=%2A%2A%2Afun%2A%2A%2A%20;\tname*2="is it not.pdf"\n'),
53497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ),
53597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
536b5bc353b8893461b0ecdf0e4bc2b299ef2b19bc0Ezio Melotti        # Make sure we also handle it if there are spurious double quotes.
53797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'rfc2231_encoded_with_double_quotes': (
53897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ("text/plain;"
53997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*0*="us-ascii\'\'This%20is%20even%20more%20";'
54097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*1*="%2A%2A%2Afun%2A%2A%2A%20";'
54197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*2="is it not.pdf"'),
54297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
54397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
54497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
54597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': 'This is even more ***fun*** is it not.pdf'},
54697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]*2,
54797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; name="This is even more ***fun*** is it not.pdf"',
54897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('Content-Type: text/plain;\t'
54997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                'name*0*="us-ascii\'\'This%20is%20even%20more%20";\n'
55097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             '\tname*1*="%2A%2A%2Afun%2A%2A%2A%20";\tname*2="is it not.pdf"\n'),
55197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ),
55297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
55397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'rfc2231_single_quote_inside_double_quotes': (
55497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('text/plain; charset=us-ascii;'
55597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray               '\ttitle*0*="us-ascii\'en\'This%20is%20really%20";'
55697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray               '\ttitle*1*="%2A%2A%2Afun%2A%2A%2A%20";'
55797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray               '\ttitle*2="isn\'t it!"'),
55897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
55997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
56097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
56197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'charset': 'us-ascii', 'title': "This is really ***fun*** isn't it!"},
56297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]*2,
56397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('text/plain; charset="us-ascii"; '
56497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray               'title="This is really ***fun*** isn\'t it!"'),
56597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('Content-Type: text/plain; charset=us-ascii;\n'
56697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             '\ttitle*0*="us-ascii\'en\'This%20is%20really%20";\n'
56797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             '\ttitle*1*="%2A%2A%2Afun%2A%2A%2A%20";\ttitle*2="isn\'t it!"\n'),
56897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ),
56997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
57097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'rfc2231_single_quote_in_value_with_charset_and_lang': (
57197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('application/x-foo;'
57297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                "\tname*0*=\"us-ascii'en-us'Frank's\"; name*1*=\" Document\""),
57397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'application/x-foo',
57497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'application',
57597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'x-foo',
57697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': "Frank's Document"},
57797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]*2,
57897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'application/x-foo; name="Frank\'s Document"',
57997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('Content-Type: application/x-foo;\t'
58097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                'name*0*="us-ascii\'en-us\'Frank\'s";\n'
58197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             ' name*1*=" Document"\n'),
58297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ),
58397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
58497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'rfc2231_single_quote_in_non_encoded_value': (
58597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('application/x-foo;'
58697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                "\tname*0=\"us-ascii'en-us'Frank's\"; name*1=\" Document\""),
58797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'application/x-foo',
58897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'application',
58997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'x-foo',
59097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': "us-ascii'en-us'Frank's Document"},
59197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [],
59297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'application/x-foo; name="us-ascii\'en-us\'Frank\'s Document"',
59397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('Content-Type: application/x-foo;\t'
59497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                'name*0="us-ascii\'en-us\'Frank\'s";\n'
59597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             ' name*1=" Document"\n'),
59697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             ),
59797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
59897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'rfc2231_no_language_or_charset': (
59997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; NAME*0*=english_is_the_default.html',
60097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
60197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
60297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
60397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': 'english_is_the_default.html'},
60497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect],
60597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; NAME="english_is_the_default.html"'),
60697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
60797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'rfc2231_encoded_no_charset': (
60897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ("text/plain;"
60997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*0*="\'\'This%20is%20even%20more%20";'
61097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*1*="%2A%2A%2Afun%2A%2A%2A%20";'
61197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*2="is it.pdf"'),
61297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
61397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
61497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
61597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': 'This is even more ***fun*** is it.pdf'},
61697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]*2,
61797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; name="This is even more ***fun*** is it.pdf"',
61897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('Content-Type: text/plain;\t'
61997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                'name*0*="\'\'This%20is%20even%20more%20";\n'
62097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             '\tname*1*="%2A%2A%2Afun%2A%2A%2A%20";\tname*2="is it.pdf"\n'),
62197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ),
62297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
62397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # XXX: see below...the first name line here should be *0 not *0*.
62497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'rfc2231_partly_encoded': (
62597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ("text/plain;"
62697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*0*="\'\'This%20is%20even%20more%20";'
62797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*1*="%2A%2A%2Afun%2A%2A%2A%20";'
62897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*2="is it.pdf"'),
62997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
63097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
63197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
63297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': 'This is even more ***fun*** is it.pdf'},
63397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]*2,
63497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; name="This is even more ***fun*** is it.pdf"',
63597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('Content-Type: text/plain;\t'
63697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                'name*0*="\'\'This%20is%20even%20more%20";\n'
63797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             '\tname*1*="%2A%2A%2Afun%2A%2A%2A%20";\tname*2="is it.pdf"\n'),
63897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ),
63997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
64097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'rfc2231_partly_encoded_2': (
64197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ("text/plain;"
64297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*0*="\'\'This%20is%20even%20more%20";'
64397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*1="%2A%2A%2Afun%2A%2A%2A%20";'
64497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*2="is it.pdf"'),
64597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
64697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
64797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
64897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': 'This is even more %2A%2A%2Afun%2A%2A%2A%20is it.pdf'},
64997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect],
65097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; name="This is even more %2A%2A%2Afun%2A%2A%2A%20is it.pdf"',
65197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('Content-Type: text/plain;\t'
65297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                'name*0*="\'\'This%20is%20even%20more%20";\n'
65397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             '\tname*1="%2A%2A%2Afun%2A%2A%2A%20";\tname*2="is it.pdf"\n'),
65497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ),
65597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
65697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'rfc2231_unknown_charset_treated_as_ascii': (
65797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            "text/plain; name*0*=bogus'xx'ascii_is_the_default",
65897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
65997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
66097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
66197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': 'ascii_is_the_default'},
66297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [],
66397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; name="ascii_is_the_default"'),
66497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
66597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'rfc2231_bad_character_in_charset_parameter_value': (
6663da240fd01e02a31e516847ba865a9f56d7cfcbcR David Murray            "text/plain; charset*=ascii''utf-8%F1%F2%F3",
66797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain',
66897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text',
66997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'plain',
67097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'charset': 'utf-8\uFFFD\uFFFD\uFFFD'},
67197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.UndecodableBytesDefect],
67297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'text/plain; charset="utf-8\uFFFD\uFFFD\uFFFD"'),
67397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
6743da240fd01e02a31e516847ba865a9f56d7cfcbcR David Murray        'rfc2231_utf_8_in_supposedly_ascii_charset_parameter_value': (
6753da240fd01e02a31e516847ba865a9f56d7cfcbcR David Murray            "text/plain; charset*=ascii''utf-8%E2%80%9D",
6763da240fd01e02a31e516847ba865a9f56d7cfcbcR David Murray            'text/plain',
6773da240fd01e02a31e516847ba865a9f56d7cfcbcR David Murray            'text',
6783da240fd01e02a31e516847ba865a9f56d7cfcbcR David Murray            'plain',
6793da240fd01e02a31e516847ba865a9f56d7cfcbcR David Murray            {'charset': 'utf-8”'},
6803da240fd01e02a31e516847ba865a9f56d7cfcbcR David Murray            [errors.UndecodableBytesDefect],
6813da240fd01e02a31e516847ba865a9f56d7cfcbcR David Murray            'text/plain; charset="utf-8”"',
6823da240fd01e02a31e516847ba865a9f56d7cfcbcR David Murray            ),
6833da240fd01e02a31e516847ba865a9f56d7cfcbcR David Murray            # XXX: if the above were *re*folded, it would get tagged as utf-8
6843da240fd01e02a31e516847ba865a9f56d7cfcbcR David Murray            # instead of ascii in the param, since it now contains non-ASCII.
6853da240fd01e02a31e516847ba865a9f56d7cfcbcR David Murray
68697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'rfc2231_encoded_then_unencoded_segments': (
68797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('application/x-foo;'
68897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*0*="us-ascii\'en-us\'My";'
68997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*1=" Document";'
69097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*2=" For You"'),
69197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'application/x-foo',
69297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'application',
69397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'x-foo',
69497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': 'My Document For You'},
69597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect],
69697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'application/x-foo; name="My Document For You"',
69797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('Content-Type: application/x-foo;\t'
69897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                'name*0*="us-ascii\'en-us\'My";\n'
69997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             '\tname*1=" Document";\tname*2=" For You"\n'),
70097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ),
70197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
70297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # My reading of the RFC is that this is an invalid header.  The RFC
70397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # says that if charset and language information is given, the first
70497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # segment *must* be encoded.
70597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'rfc2231_unencoded_then_encoded_segments': (
70697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('application/x-foo;'
70797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*0=us-ascii\'en-us\'My;'
70897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*1*=" Document";'
70997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*2*=" For You"'),
71097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'application/x-foo',
71197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'application',
71297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'x-foo',
71397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': 'My Document For You'},
71497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]*3,
71597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'application/x-foo; name="My Document For You"',
71697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ("Content-Type: application/x-foo;\tname*0=us-ascii'en-us'My;\t"
71797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                # XXX: the newline is in the wrong place, come back and fix
71897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                # this when the rest of tests pass.
71997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                'name*1*=" Document"\n;'
72097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             '\tname*2*=" For You"\n'),
72197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ),
72297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
72397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # XXX: I would say this one should default to ascii/en for the
7243f5db3940ff71428d1eecb3d4eebe68d9c3d216dEzio Melotti        # "encoded" segment, since the first segment is not encoded and is
72597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # in double quotes, making the value a valid non-encoded string.  The
72697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # old parser decodes this just like the previous case, which may be the
72797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # better Postel rule, but could equally result in borking headers that
728b5bc353b8893461b0ecdf0e4bc2b299ef2b19bc0Ezio Melotti        # intentionally have quoted quotes in them.  We could get this 98%
729b5bc353b8893461b0ecdf0e4bc2b299ef2b19bc0Ezio Melotti        # right if we treat it as a quoted string *unless* it matches the
73097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # charset'lang'value pattern exactly *and* there is at least one
73197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # encoded segment.  Implementing that algorithm will require some
73297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # refactoring, so I haven't done it (yet).
73397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
73497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'rfc2231_qouted_unencoded_then_encoded_segments': (
73597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('application/x-foo;'
73697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*0="us-ascii\'en-us\'My";'
73797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*1*=" Document";'
73897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                '\tname*2*=" For You"'),
73997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'application/x-foo',
74097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'application',
74197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'x-foo',
74297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'name': "us-ascii'en-us'My Document For You"},
74397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]*2,
74497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'application/x-foo; name="us-ascii\'en-us\'My Document For You"',
74597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('Content-Type: application/x-foo;\t'
74697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                'name*0="us-ascii\'en-us\'My";\n'
74797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             '\tname*1*=" Document";\tname*2*=" For You"\n'),
74897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ),
74997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
75097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray    }
75197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
75297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
75397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray@parameterize
75497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murrayclass TestContentTransferEncoding(TestHeaderBase):
75597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
75697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray    def cte_as_value(self,
75797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                     source,
75897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                     cte,
75997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                     *args):
76097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        l = len(args)
76197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        defects =  args[0] if l>0 else []
76297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        decoded =  args[1] if l>1 and args[1] is not DITTO else source
76397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        header = 'Content-Transfer-Encoding:' + ' ' if source else ''
76497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        folded = args[2] if l>2 else header + source + '\n'
76597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        h = self.make_header('Content-Transfer-Encoding', source)
76697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h.cte, cte)
76797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertDefectsEqual(h.defects, defects)
76897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h, decoded)
76997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h.fold(policy=policy.default), folded)
77097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
77197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray    cte_params = {
77297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
77397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'RFC_2183_1': (
77497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'base64',
77597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'base64',),
77697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
77797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'no_value': (
77897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '',
77997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '7bit',
78097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.HeaderMissingRequiredValue],
78197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '',
78297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'Content-Transfer-Encoding:\n',
78397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ),
78497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
78597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'junk_after_cte': (
78697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '7bit and a bunch more',
78797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '7bit',
78897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]),
78997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
79097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray    }
79197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
79297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
79397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray@parameterize
79497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murrayclass TestContentDisposition(TestHeaderBase):
79597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
79697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray    def content_disp_as_value(self,
79797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                              source,
79897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                              content_disposition,
79997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                              *args):
80097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        l = len(args)
80197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        parmdict = args[0] if l>0 else {}
80297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        defects =  args[1] if l>1 else []
80397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        decoded =  args[2] if l>2 and args[2] is not DITTO else source
80497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        header = 'Content-Disposition:' + ' ' if source else ''
80597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        folded = args[3] if l>3 else header + source + '\n'
80697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        h = self.make_header('Content-Disposition', source)
80797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h.content_disposition, content_disposition)
80897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h.params, parmdict)
80997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertDefectsEqual(h.defects, defects)
81097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h, decoded)
81197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h.fold(policy=policy.default), folded)
81297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
81397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray    content_disp_params = {
81497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
81597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # Examples from RFC 2183.
81697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
81797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'RFC_2183_1': (
81897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'inline',
81997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'inline',),
82097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
82197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'RFC_2183_2': (
82297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('attachment; filename=genome.jpeg;'
82397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             '  modification-date="Wed, 12 Feb 1997 16:29:51 -0500";'),
82497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'attachment',
82597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'filename': 'genome.jpeg',
82697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             'modification-date': 'Wed, 12 Feb 1997 16:29:51 -0500'},
82797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [],
82897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('attachment; filename="genome.jpeg"; '
82997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                 'modification-date="Wed, 12 Feb 1997 16:29:51 -0500"'),
83097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ('Content-Disposition: attachment; filename=genome.jpeg;\n'
83197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray             '  modification-date="Wed, 12 Feb 1997 16:29:51 -0500";\n'),
83297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            ),
83397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
83497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'no_value': (
83597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '',
83697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
83797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {},
83897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.HeaderMissingRequiredValue],
83997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '',
84097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'Content-Disposition:\n'),
84197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
84297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'invalid_value': (
84397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'ab./k',
84497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'ab.',
84597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {},
84697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]),
84797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
84897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'invalid_value_with_params': (
84997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'ab./k; filename="foo"',
85097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'ab.',
85197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            {'filename': 'foo'},
85297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]),
85397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
85497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray    }
85597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
85697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
85797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray@parameterize
85897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murrayclass TestMIMEVersionHeader(TestHeaderBase):
85997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
86097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray    def version_string_as_MIME_Version(self,
86197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                                       source,
86297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                                       decoded,
86397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                                       version,
86497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                                       major,
86597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                                       minor,
86697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                                       defects):
86797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        h = self.make_header('MIME-Version', source)
86897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h, decoded)
86997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h.version, version)
87097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h.major, major)
87197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h.minor, minor)
87297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertDefectsEqual(h.defects, defects)
87397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        if source:
87497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            source = ' ' + source
87597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        self.assertEqual(h.fold(policy=policy.default),
87697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray                        'MIME-Version:' + source + '\n')
87797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
87897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray    version_string_params = {
87997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
88097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # Examples from the RFC.
88197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
88297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'RFC_2045_1': (
88397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.0',
88497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.0',
88597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.0',
88697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            1,
88797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            0,
88897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            []),
88997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
89097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'RFC_2045_2': (
89197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.0 (produced by MetaSend Vx.x)',
89297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.0 (produced by MetaSend Vx.x)',
89397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.0',
89497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            1,
89597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            0,
89697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            []),
89797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
89897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'RFC_2045_3': (
89997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '(produced by MetaSend Vx.x) 1.0',
90097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '(produced by MetaSend Vx.x) 1.0',
90197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.0',
90297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            1,
90397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            0,
90497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            []),
90597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
90697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'RFC_2045_4': (
90797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.(produced by MetaSend Vx.x)0',
90897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.(produced by MetaSend Vx.x)0',
90997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.0',
91097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            1,
91197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            0,
91297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            []),
91397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
91497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # Other valid values.
91597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
91697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        '1_1': (
91797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.1',
91897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.1',
91997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.1',
92097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            1,
92197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            1,
92297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            []),
92397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
92497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        '2_1': (
92597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '2.1',
92697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '2.1',
92797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '2.1',
92897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            2,
92997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            1,
93097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            []),
93197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
93297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'whitespace': (
93397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1 .0',
93497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1 .0',
93597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.0',
93697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            1,
93797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            0,
93897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            []),
93997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
94097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'leading_trailing_whitespace_ignored': (
94197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '  1.0  ',
94297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '  1.0  ',
94397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.0',
94497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            1,
94597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            0,
94697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            []),
94797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
94897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # Recoverable invalid values.  We can recover here only because we
94997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # already have a valid value by the time we encounter the garbage.
95097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # Anywhere else, and we don't know where the garbage ends.
95197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
95297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'non_comment_garbage_after': (
95397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.0 <abc>',
95497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.0 <abc>',
95597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.0',
95697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            1,
95797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            0,
95897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]),
95997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
96097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # Unrecoverable invalid values.  We *could* apply more heuristics to
961b5bc353b8893461b0ecdf0e4bc2b299ef2b19bc0Ezio Melotti        # get something out of the first two, but doing so is not worth the
96297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        # effort.
96397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
96497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'non_comment_garbage_before': (
96597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '<abc> 1.0',
96697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '<abc> 1.0',
96797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
96897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
96997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
97097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]),
97197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
97297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'non_comment_garbage_inside': (
97397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.<abc>0',
97497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1.<abc>0',
97597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
97697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
97797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
97897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]),
97997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
98097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'two_periods': (
98197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1..0',
98297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '1..0',
98397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
98497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
98597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
98697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]),
98797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
98897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        '2_x': (
98997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '2.x',
99097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '2.x',
99197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,  # This could be 2, but it seems safer to make it None.
99297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
99397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
99497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]),
99597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
99697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'foo': (
99797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'foo',
99897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            'foo',
99997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
100097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
100197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
100297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.InvalidHeaderDefect]),
100397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
100497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        'missing': (
100597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '',
100697f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            '',
100797f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
100897f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
100997f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            None,
101097f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray            [errors.HeaderMissingRequiredValue]),
101197f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
101297f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray        }
101397f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
101497f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray
101597f43c019f3bb8376a3a5f7bc52e97b4c2ed8e16R David Murray@parameterize
10161be413e366be7bed676074b7f395b2a20a10ac47R David Murrayclass TestAddressHeader(TestHeaderBase):
10170b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
101856517e5cb91c896024934a520d365d6e275eb1adR David Murray    example_params = {
10190b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
10200b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        'empty':
10210b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            ('<>',
10220b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             [errors.InvalidHeaderDefect],
10230b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '<>',
10240b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '',
10250b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '<>',
10260b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '',
10270b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '',
10280b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             None),
10290b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
10300b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        'address_only':
10310b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            ('zippy@pinhead.com',
10320b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             [],
10330b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'zippy@pinhead.com',
10340b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '',
10350b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'zippy@pinhead.com',
10360b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'zippy',
10370b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'pinhead.com',
10380b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             None),
10390b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
10400b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        'name_and_address':
10410b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            ('Zaphrod Beblebrux <zippy@pinhead.com>',
10420b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             [],
10430b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'Zaphrod Beblebrux <zippy@pinhead.com>',
10440b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'Zaphrod Beblebrux',
10450b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'zippy@pinhead.com',
10460b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'zippy',
10470b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'pinhead.com',
10480b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             None),
10490b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
10500b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        'quoted_local_part':
10510b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            ('Zaphrod Beblebrux <"foo bar"@pinhead.com>',
10520b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             [],
10530b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'Zaphrod Beblebrux <"foo bar"@pinhead.com>',
10540b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'Zaphrod Beblebrux',
10550b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '"foo bar"@pinhead.com',
10560b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'foo bar',
10570b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'pinhead.com',
10580b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             None),
10590b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
10600b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        'quoted_parens_in_name':
10610b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            (r'"A \(Special\) Person" <person@dom.ain>',
10620b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             [],
10630b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '"A (Special) Person" <person@dom.ain>',
10640b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'A (Special) Person',
10650b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'person@dom.ain',
10660b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'person',
10670b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'dom.ain',
10680b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             None),
10690b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
10700b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        'quoted_backslashes_in_name':
10710b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            (r'"Arthur \\Backslash\\ Foobar" <person@dom.ain>',
10720b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             [],
10730b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             r'"Arthur \\Backslash\\ Foobar" <person@dom.ain>',
10740b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             r'Arthur \Backslash\ Foobar',
10750b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'person@dom.ain',
10760b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'person',
10770b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'dom.ain',
10780b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             None),
10790b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
10800b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        'name_with_dot':
10810b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            ('John X. Doe <jxd@example.com>',
10820b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             [errors.ObsoleteHeaderDefect],
10830b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '"John X. Doe" <jxd@example.com>',
10840b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'John X. Doe',
10850b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'jxd@example.com',
10860b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'jxd',
10870b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'example.com',
10880b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             None),
10890b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
10900b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        'quoted_strings_in_local_part':
10910b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            ('""example" example"@example.com',
10920b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             [errors.InvalidHeaderDefect]*3,
10930b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '"example example"@example.com',
10940b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '',
10950b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '"example example"@example.com',
10960b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'example example',
10970b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'example.com',
10980b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             None),
10990b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
11000b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        'escaped_quoted_strings_in_local_part':
11010b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            (r'"\"example\" example"@example.com',
11020b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             [],
11030b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             r'"\"example\" example"@example.com',
11040b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '',
11050b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             r'"\"example\" example"@example.com',
11060b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             r'"example" example',
11070b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'example.com',
11080b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            None),
11090b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
11100b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        'escaped_escapes_in_local_part':
11110b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            (r'"\\"example\\" example"@example.com',
11120b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             [errors.InvalidHeaderDefect]*5,
11130b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             r'"\\example\\\\ example"@example.com',
11140b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '',
11150b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             r'"\\example\\\\ example"@example.com',
11160b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             r'\example\\ example',
11170b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'example.com',
11180b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            None),
11190b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
11200b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        'spaces_in_unquoted_local_part_collapsed':
11210b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            ('merwok  wok  @example.com',
11220b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             [errors.InvalidHeaderDefect]*2,
11230b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '"merwok wok"@example.com',
11240b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '',
11250b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '"merwok wok"@example.com',
11260b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'merwok wok',
11270b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'example.com',
11280b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             None),
11290b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
11300b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        'spaces_around_dots_in_local_part_removed':
11310b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            ('merwok. wok .  wok@example.com',
11320b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             [errors.ObsoleteHeaderDefect],
11330b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'merwok.wok.wok@example.com',
11340b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             '',
11350b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'merwok.wok.wok@example.com',
11360b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'merwok.wok.wok',
11370b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             'example.com',
11380b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             None),
11390b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
1140923512f327af6944bbdbc905d2372658a3977489R David Murray        'rfc2047_atom_is_decoded':
1141923512f327af6944bbdbc905d2372658a3977489R David Murray            ('=?utf-8?q?=C3=89ric?= <foo@example.com>',
1142923512f327af6944bbdbc905d2372658a3977489R David Murray            [],
1143923512f327af6944bbdbc905d2372658a3977489R David Murray            'Éric <foo@example.com>',
1144923512f327af6944bbdbc905d2372658a3977489R David Murray            'Éric',
1145923512f327af6944bbdbc905d2372658a3977489R David Murray            'foo@example.com',
1146923512f327af6944bbdbc905d2372658a3977489R David Murray            'foo',
1147923512f327af6944bbdbc905d2372658a3977489R David Murray            'example.com',
1148923512f327af6944bbdbc905d2372658a3977489R David Murray            None),
1149923512f327af6944bbdbc905d2372658a3977489R David Murray
1150923512f327af6944bbdbc905d2372658a3977489R David Murray        'rfc2047_atom_in_phrase_is_decoded':
1151923512f327af6944bbdbc905d2372658a3977489R David Murray            ('The =?utf-8?q?=C3=89ric=2C?= Himself <foo@example.com>',
1152923512f327af6944bbdbc905d2372658a3977489R David Murray            [],
1153923512f327af6944bbdbc905d2372658a3977489R David Murray            '"The Éric, Himself" <foo@example.com>',
1154923512f327af6944bbdbc905d2372658a3977489R David Murray            'The Éric, Himself',
1155923512f327af6944bbdbc905d2372658a3977489R David Murray            'foo@example.com',
1156923512f327af6944bbdbc905d2372658a3977489R David Murray            'foo',
1157923512f327af6944bbdbc905d2372658a3977489R David Murray            'example.com',
1158923512f327af6944bbdbc905d2372658a3977489R David Murray            None),
1159923512f327af6944bbdbc905d2372658a3977489R David Murray
11600400d33928e6b463db164836da670700f03edc5dR David Murray        'rfc2047_atom_in_quoted_string_is_decoded':
11610400d33928e6b463db164836da670700f03edc5dR David Murray            ('"=?utf-8?q?=C3=89ric?=" <foo@example.com>',
11620400d33928e6b463db164836da670700f03edc5dR David Murray            [errors.InvalidHeaderDefect],
11630400d33928e6b463db164836da670700f03edc5dR David Murray            'Éric <foo@example.com>',
11640400d33928e6b463db164836da670700f03edc5dR David Murray            'Éric',
11650400d33928e6b463db164836da670700f03edc5dR David Murray            'foo@example.com',
11660400d33928e6b463db164836da670700f03edc5dR David Murray            'foo',
11670400d33928e6b463db164836da670700f03edc5dR David Murray            'example.com',
11680400d33928e6b463db164836da670700f03edc5dR David Murray            None),
11690400d33928e6b463db164836da670700f03edc5dR David Murray
11700b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        }
11710b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
11720b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        # XXX: Need many more examples, and in particular some with names in
11730b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        # trailing comments, which aren't currently handled.  comments in
11740b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        # general are not handled yet.
11750b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
117656517e5cb91c896024934a520d365d6e275eb1adR David Murray    def example_as_address(self, source, defects, decoded, display_name,
117756517e5cb91c896024934a520d365d6e275eb1adR David Murray                           addr_spec, username, domain, comment):
11780b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('sender', source)
11790b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h, decoded)
11800b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertDefectsEqual(h.defects, defects)
11810b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        a = h.address
11820b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(a), decoded)
11830b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(len(h.groups), 1)
11840b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual([a], list(h.groups[0].addresses))
11850b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual([a], list(h.addresses))
11860b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.display_name, display_name)
11870b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.addr_spec, addr_spec)
11880b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.username, username)
11890b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.domain, domain)
11900b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        # XXX: we have no comment support yet.
11910b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        #self.assertEqual(a.comment, comment)
11920b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
119356517e5cb91c896024934a520d365d6e275eb1adR David Murray    def example_as_group(self, source, defects, decoded, display_name,
119456517e5cb91c896024934a520d365d6e275eb1adR David Murray                         addr_spec, username, domain, comment):
11950b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        source = 'foo: {};'.format(source)
11960b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        gdecoded = 'foo: {};'.format(decoded) if decoded else 'foo:;'
11970b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('to', source)
11980b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h, gdecoded)
11990b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertDefectsEqual(h.defects, defects)
12000b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.groups[0].addresses, h.addresses)
12010b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(len(h.groups), 1)
12020b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(len(h.addresses), 1)
12030b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        a = h.addresses[0]
12040b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(a), decoded)
12050b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.display_name, display_name)
12060b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.addr_spec, addr_spec)
12070b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.username, username)
12080b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.domain, domain)
12090b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
12100b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_simple_address_list(self):
12110b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        value = ('Fred <dinsdale@python.org>, foo@example.com, '
12120b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                    '"Harry W. Hastings" <hasty@example.com>')
12130b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('to', value)
12140b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h, value)
12150b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(len(h.groups), 3)
12160b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(len(h.addresses), 3)
12170b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        for i in range(3):
12180b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            self.assertEqual(h.groups[i].addresses[0], h.addresses[i])
12190b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(h.addresses[0]), 'Fred <dinsdale@python.org>')
12200b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(h.addresses[1]), 'foo@example.com')
12210b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(h.addresses[2]),
12220b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            '"Harry W. Hastings" <hasty@example.com>')
12230b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.addresses[2].display_name,
12240b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            'Harry W. Hastings')
12250b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
12260b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_complex_address_list(self):
122756517e5cb91c896024934a520d365d6e275eb1adR David Murray        examples = list(self.example_params.values())
12280b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        source = ('dummy list:;, another: (empty);,' +
12290b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                 ', '.join([x[0] for x in examples[:4]]) + ', ' +
12300b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                 r'"A \"list\"": ' +
12310b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                    ', '.join([x[0] for x in examples[4:6]]) + ';,' +
12320b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                 ', '.join([x[0] for x in examples[6:]])
12330b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            )
12340b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        # XXX: the fact that (empty) disappears here is a potential API design
12350b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        # bug.  We don't currently have a way to preserve comments.
12360b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        expected = ('dummy list:;, another:;, ' +
12370b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                 ', '.join([x[2] for x in examples[:4]]) + ', ' +
12380b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                 r'"A \"list\"": ' +
12390b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                    ', '.join([x[2] for x in examples[4:6]]) + ';, ' +
12400b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                 ', '.join([x[2] for x in examples[6:]])
12410b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            )
12420b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
12430b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('to', source)
12440b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.split(','), expected.split(','))
12450b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h, expected)
12460b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(len(h.groups), 7 + len(examples) - 6)
12470b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.groups[0].display_name, 'dummy list')
12480b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.groups[1].display_name, 'another')
12490b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.groups[6].display_name, 'A "list"')
12500b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(len(h.addresses), len(examples))
12510b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        for i in range(4):
12520b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            self.assertIsNone(h.groups[i+2].display_name)
12530b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            self.assertEqual(str(h.groups[i+2].addresses[0]), examples[i][2])
12540b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        for i in range(7, 7 + len(examples) - 6):
12550b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            self.assertIsNone(h.groups[i].display_name)
12560b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            self.assertEqual(str(h.groups[i].addresses[0]), examples[i-1][2])
12570b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        for i in range(len(examples)):
12580b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            self.assertEqual(str(h.addresses[i]), examples[i][2])
12590b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            self.assertEqual(h.addresses[i].addr_spec, examples[i][4])
12600b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
12610b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_address_read_only(self):
12620b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('sender', 'abc@xyz.com')
12630b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        with self.assertRaises(AttributeError):
12640b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            h.address = 'foo'
12650b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
12660b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_addresses_read_only(self):
12670b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('sender', 'abc@xyz.com')
12680b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        with self.assertRaises(AttributeError):
12690b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            h.addresses = 'foo'
12700b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
12710b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_groups_read_only(self):
12720b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('sender', 'abc@xyz.com')
12730b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        with self.assertRaises(AttributeError):
12740b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            h.groups = 'foo'
12750b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
12760b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_addresses_types(self):
12770b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        source = 'me <who@example.com>'
12780b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('to', source)
12790b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertIsInstance(h.addresses, tuple)
12800b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertIsInstance(h.addresses[0], Address)
12810b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
12820b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_groups_types(self):
12830b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        source = 'me <who@example.com>'
12840b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('to', source)
12850b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertIsInstance(h.groups, tuple)
12860b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertIsInstance(h.groups[0], Group)
12870b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
12880b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_set_from_Address(self):
12890b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('to', Address('me', 'foo', 'example.com'))
12900b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h, 'me <foo@example.com>')
12910b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
12920b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_set_from_Address_list(self):
12930b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('to', [Address('me', 'foo', 'example.com'),
12940b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                                    Address('you', 'bar', 'example.com')])
12950b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h, 'me <foo@example.com>, you <bar@example.com>')
12960b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
12970b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_set_from_Address_and_Group_list(self):
12980b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('to', [Address('me', 'foo', 'example.com'),
12990b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                                    Group('bing', [Address('fiz', 'z', 'b.com'),
13000b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                                                   Address('zif', 'f', 'c.com')]),
13010b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                                    Address('you', 'bar', 'example.com')])
13020b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h, 'me <foo@example.com>, bing: fiz <z@b.com>, '
13030b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                            'zif <f@c.com>;, you <bar@example.com>')
13040b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h.fold(policy=policy.default.clone(max_line_length=40)),
13050b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                        'to: me <foo@example.com>,\n'
13060b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                        ' bing: fiz <z@b.com>, zif <f@c.com>;,\n'
13070b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                        ' you <bar@example.com>\n')
13080b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13090b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_set_from_Group_list(self):
13100b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('to', [Group('bing', [Address('fiz', 'z', 'b.com'),
13110b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                                                   Address('zif', 'f', 'c.com')])])
13120b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(h, 'bing: fiz <z@b.com>, zif <f@c.com>;')
13130b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13140b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13150b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murrayclass TestAddressAndGroup(TestEmailBase):
13160b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13170b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def _test_attr_ro(self, obj, attr):
13180b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        with self.assertRaises(AttributeError):
13190b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            setattr(obj, attr, 'foo')
13200b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13210b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_address_display_name_ro(self):
13220b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self._test_attr_ro(Address('foo', 'bar', 'baz'), 'display_name')
13230b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13240b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_address_username_ro(self):
13250b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self._test_attr_ro(Address('foo', 'bar', 'baz'), 'username')
13260b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13270b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_address_domain_ro(self):
13280b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self._test_attr_ro(Address('foo', 'bar', 'baz'), 'domain')
13290b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13300b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_group_display_name_ro(self):
13310b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self._test_attr_ro(Group('foo'), 'display_name')
13320b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13330b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_group_addresses_ro(self):
13340b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self._test_attr_ro(Group('foo'), 'addresses')
13350b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13360b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_address_from_username_domain(self):
13370b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        a = Address('foo', 'bar', 'baz')
13380b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.display_name, 'foo')
13390b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.username, 'bar')
13400b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.domain, 'baz')
13410b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.addr_spec, 'bar@baz')
13420b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(a), 'foo <bar@baz>')
13430b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13440b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_address_from_addr_spec(self):
13450b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        a = Address('foo', addr_spec='bar@baz')
13460b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.display_name, 'foo')
13470b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.username, 'bar')
13480b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.domain, 'baz')
13490b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.addr_spec, 'bar@baz')
13500b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(a), 'foo <bar@baz>')
13510b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13520b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_address_with_no_display_name(self):
13530b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        a = Address(addr_spec='bar@baz')
13540b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.display_name, '')
13550b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.username, 'bar')
13560b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.domain, 'baz')
13570b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.addr_spec, 'bar@baz')
13580b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(a), 'bar@baz')
13590b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13600b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_null_address(self):
13610b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        a = Address()
13620b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.display_name, '')
13630b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.username, '')
13640b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.domain, '')
13650b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.addr_spec, '<>')
13660b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(a), '<>')
13670b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13680b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_domain_only(self):
13690b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        # This isn't really a valid address.
13700b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        a = Address(domain='buzz')
13710b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.display_name, '')
13720b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.username, '')
13730b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.domain, 'buzz')
13740b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.addr_spec, '@buzz')
13750b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(a), '@buzz')
13760b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13770b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_username_only(self):
13780b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        # This isn't really a valid address.
13790b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        a = Address(username='buzz')
13800b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.display_name, '')
13810b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.username, 'buzz')
13820b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.domain, '')
13830b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.addr_spec, 'buzz')
13840b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(a), 'buzz')
13850b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13860b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_display_name_only(self):
13870b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        a = Address('buzz')
13880b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.display_name, 'buzz')
13890b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.username, '')
13900b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.domain, '')
13910b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.addr_spec, '<>')
13920b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(a), 'buzz <>')
13930b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
13940b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_quoting(self):
13950b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        # Ideally we'd check every special individually, but I'm not up for
13960b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        # writing that many tests.
13970b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        a = Address('Sara J.', 'bad name', 'example.com')
13980b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.display_name, 'Sara J.')
13990b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.username, 'bad name')
14000b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.domain, 'example.com')
14010b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.addr_spec, '"bad name"@example.com')
14020b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(a), '"Sara J." <"bad name"@example.com>')
14030b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
14040b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_il8n(self):
14050b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        a = Address('Éric', 'wok', 'exàmple.com')
14060b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.display_name, 'Éric')
14070b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.username, 'wok')
14080b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.domain, 'exàmple.com')
14090b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(a.addr_spec, 'wok@exàmple.com')
14100b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(a), 'Éric <wok@exàmple.com>')
14110b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
14120b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    # XXX: there is an API design issue that needs to be solved here.
14130b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    #def test_non_ascii_username_raises(self):
14140b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    #    with self.assertRaises(ValueError):
14150b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    #        Address('foo', 'wők', 'example.com')
14160b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
14170b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_non_ascii_username_in_addr_spec_raises(self):
14180b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        with self.assertRaises(ValueError):
14190b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            Address('foo', addr_spec='wők@example.com')
14200b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
14210b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_address_addr_spec_and_username_raises(self):
14220b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        with self.assertRaises(TypeError):
14230b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            Address('foo', username='bing', addr_spec='bar@baz')
14240b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
14250b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_address_addr_spec_and_domain_raises(self):
14260b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        with self.assertRaises(TypeError):
14270b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            Address('foo', domain='bing', addr_spec='bar@baz')
14280b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
14290b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_address_addr_spec_and_username_and_domain_raises(self):
14300b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        with self.assertRaises(TypeError):
14310b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            Address('foo', username='bong', domain='bing', addr_spec='bar@baz')
14320b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
14330b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_space_in_addr_spec_username_raises(self):
14340b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        with self.assertRaises(ValueError):
14350b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            Address('foo', addr_spec="bad name@example.com")
14360b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
14370b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_bad_addr_sepc_raises(self):
14380b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        with self.assertRaises(ValueError):
14390b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            Address('foo', addr_spec="name@ex[]ample.com")
14400b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
14410b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_empty_group(self):
14420b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        g = Group('foo')
14430b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(g.display_name, 'foo')
14440b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(g.addresses, tuple())
14450b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(g), 'foo:;')
14460b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
14470b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_empty_group_list(self):
14480b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        g = Group('foo', addresses=[])
14490b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(g.display_name, 'foo')
14500b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(g.addresses, tuple())
14510b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(g), 'foo:;')
14520b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
14530b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_null_group(self):
14540b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        g = Group()
14550b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertIsNone(g.display_name)
14560b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(g.addresses, tuple())
14570b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(g), 'None:;')
14580b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
14590b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_group_with_addresses(self):
14600b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        addrs = [Address('b', 'b', 'c'), Address('a', 'b','c')]
14610b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        g = Group('foo', addrs)
14620b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(g.display_name, 'foo')
14630b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(g.addresses, tuple(addrs))
14640b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(g), 'foo: b <b@c>, a <b@c>;')
14650b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
14660b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_group_with_addresses_no_display_name(self):
14670b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        addrs = [Address('b', 'b', 'c'), Address('a', 'b','c')]
14680b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        g = Group(addresses=addrs)
14690b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertIsNone(g.display_name)
14700b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(g.addresses, tuple(addrs))
14710b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(g), 'None: b <b@c>, a <b@c>;')
14720b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
14730b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_group_with_one_address_no_display_name(self):
14740b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        addrs = [Address('b', 'b', 'c')]
14750b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        g = Group(addresses=addrs)
14760b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertIsNone(g.display_name)
14770b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(g.addresses, tuple(addrs))
14780b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(g), 'b <b@c>')
14790b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
14800b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_display_name_quoting(self):
14810b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        g = Group('foo.bar')
14820b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(g.display_name, 'foo.bar')
14830b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(g.addresses, tuple())
14840b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(g), '"foo.bar":;')
14850b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
14860b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_display_name_blanks_not_quoted(self):
14870b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        g = Group('foo bar')
14880b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(g.display_name, 'foo bar')
14890b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(g.addresses, tuple())
14900b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(str(g), 'foo bar:;')
14910b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
1492dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray    def test_set_message_header_from_address(self):
1493dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray        a = Address('foo', 'bar', 'example.com')
1494dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray        m = Message(policy=policy.default)
1495dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray        m['To'] = a
1496dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray        self.assertEqual(m['to'], 'foo <bar@example.com>')
1497dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray        self.assertEqual(m['to'].addresses, (a,))
1498dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray
1499dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray    def test_set_message_header_from_group(self):
1500dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray        g = Group('foo bar')
1501dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray        m = Message(policy=policy.default)
1502dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray        m['To'] = g
1503dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray        self.assertEqual(m['to'], 'foo bar:;')
1504dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray        self.assertEqual(m['to'].addresses, g.addresses)
1505dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray
15060b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
15070b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murrayclass TestFolding(TestHeaderBase):
15080b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
15090b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_short_unstructured(self):
15100b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('subject', 'this is a test')
1511a7c9ddb59cf11b9e5832636327ed04fb3bf052b2R David Murray        self.assertEqual(h.fold(policy=policy.default),
15120b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                         'subject: this is a test\n')
15130b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
15140b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_long_unstructured(self):
15150b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('Subject', 'This is a long header '
15160b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            'line that will need to be folded into two lines '
15170b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            'and will demonstrate basic folding')
1518a7c9ddb59cf11b9e5832636327ed04fb3bf052b2R David Murray        self.assertEqual(h.fold(policy=policy.default),
15190b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                        'Subject: This is a long header line that will '
15200b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                            'need to be folded into two lines\n'
15210b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                        ' and will demonstrate basic folding\n')
15220b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
15230b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_unstructured_short_max_line_length(self):
15240b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('Subject', 'this is a short header '
15250b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            'that will be folded anyway')
15260b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(
15270b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            h.fold(policy=policy.default.clone(max_line_length=20)),
15280b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            textwrap.dedent("""\
15290b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                Subject: this is a
15300b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                 short header that
15310b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                 will be folded
15320b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                 anyway
15330b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                """))
15340b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
15350b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_fold_unstructured_single_word(self):
15360b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('Subject', 'test')
1537a7c9ddb59cf11b9e5832636327ed04fb3bf052b2R David Murray        self.assertEqual(h.fold(policy=policy.default), 'Subject: test\n')
15380b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
15390b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_fold_unstructured_short(self):
15400b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('Subject', 'test test test')
1541a7c9ddb59cf11b9e5832636327ed04fb3bf052b2R David Murray        self.assertEqual(h.fold(policy=policy.default),
15420b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                        'Subject: test test test\n')
15430b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
15440b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_fold_unstructured_with_overlong_word(self):
15450b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('Subject', 'thisisaverylonglineconsistingofa'
15460b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            'singlewordthatwontfit')
15470b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(
15480b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            h.fold(policy=policy.default.clone(max_line_length=20)),
15490b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            'Subject: thisisaverylonglineconsistingofasinglewordthatwontfit\n')
15500b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
15510b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_fold_unstructured_with_two_overlong_words(self):
15520b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('Subject', 'thisisaverylonglineconsistingofa'
15530b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            'singlewordthatwontfit plusanotherverylongwordthatwontfit')
15540b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(
15550b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            h.fold(policy=policy.default.clone(max_line_length=20)),
15560b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            'Subject: thisisaverylonglineconsistingofasinglewordthatwontfit\n'
15570b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                ' plusanotherverylongwordthatwontfit\n')
15580b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
15590b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_fold_unstructured_with_slightly_long_word(self):
15600b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('Subject', 'thislongwordislessthanmaxlinelen')
15610b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(
15620b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            h.fold(policy=policy.default.clone(max_line_length=35)),
15630b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            'Subject:\n thislongwordislessthanmaxlinelen\n')
15640b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
15650b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_fold_unstructured_with_commas(self):
15660b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        # The old wrapper would fold this at the commas.
15670b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('Subject', "This header is intended to "
1568b5bc353b8893461b0ecdf0e4bc2b299ef2b19bc0Ezio Melotti            "demonstrate, in a fairly succinct way, that we now do "
15690b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            "not give a , special treatment in unstructured headers.")
15700b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        self.assertEqual(
15710b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            h.fold(policy=policy.default.clone(max_line_length=60)),
15720b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            textwrap.dedent("""\
15730b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                Subject: This header is intended to demonstrate, in a fairly
1574b5bc353b8893461b0ecdf0e4bc2b299ef2b19bc0Ezio Melotti                 succinct way, that we now do not give a , special treatment
15750b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                 in unstructured headers.
15760b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                 """))
15770b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
15780b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_fold_address_list(self):
15790b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('To', '"Theodore H. Perfect" <yes@man.com>, '
15800b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            '"My address is very long because my name is long" <foo@bar.com>, '
15810b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            '"Only A. Friend" <no@yes.com>')
1582a7c9ddb59cf11b9e5832636327ed04fb3bf052b2R David Murray        self.assertEqual(h.fold(policy=policy.default), textwrap.dedent("""\
15830b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray            To: "Theodore H. Perfect" <yes@man.com>,
15840b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             "My address is very long because my name is long" <foo@bar.com>,
15850b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             "Only A. Friend" <no@yes.com>
15860b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray             """))
15870b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
15880b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    def test_fold_date_header(self):
15890b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray        h = self.make_header('Date', 'Sat, 2 Feb 2002 17:00:06 -0800')
1590a7c9ddb59cf11b9e5832636327ed04fb3bf052b2R David Murray        self.assertEqual(h.fold(policy=policy.default),
15910b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray                        'Date: Sat, 02 Feb 2002 17:00:06 -0800\n')
15920b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
15930b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray
1594dcaf2ece6cbd432f8ad71ca2bebc4f79e3b97fbcR David Murray
15950b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murrayif __name__ == '__main__':
15960b6f6c82b51b7071d88f48abb3192bf3dc2a2d24R David Murray    unittest.main()
1597