3
from email import _header_value_parser as parser
4
from email import errors
5
from email import policy
6
from test.test_email import TestEmailBase, parameterize
8
class TestTokens(TestEmailBase):
10
# EWWhiteSpaceTerminal
12
def test_EWWhiteSpaceTerminal(self):
13
x = parser.EWWhiteSpaceTerminal(' \t', 'fws')
14
self.assertEqual(x, ' \t')
15
self.assertEqual(str(x), '')
16
self.assertEqual(x.value, '')
17
self.assertEqual(x.encoded, ' \t')
19
# UnstructuredTokenList
21
def test_undecodable_bytes_error_preserved(self):
22
badstr = b"le pouf c\xaflebre".decode('ascii', 'surrogateescape')
23
unst = parser.get_unstructured(badstr)
24
self.assertDefectsEqual(unst.all_defects, [errors.UndecodableBytesDefect])
25
parts = list(unst.parts)
26
self.assertDefectsEqual(parts[0].all_defects, [])
27
self.assertDefectsEqual(parts[1].all_defects, [])
28
self.assertDefectsEqual(parts[2].all_defects, [errors.UndecodableBytesDefect])
31
class TestParserMixin:
33
def _assert_results(self, tl, rest, string, value, defects, remainder,
35
self.assertEqual(str(tl), string)
36
self.assertEqual(tl.value, value)
37
self.assertDefectsEqual(tl.all_defects, defects)
38
self.assertEqual(rest, remainder)
39
if comments is not None:
40
self.assertEqual(tl.comments, comments)
42
def _test_get_x(self, method, source, string, value, defects,
43
remainder, comments=None):
44
tl, rest = method(source)
45
self._assert_results(tl, rest, string, value, defects, remainder,
49
def _test_parse_x(self, method, input, string, value, defects,
52
self._assert_results(tl, '', string, value, defects, '', comments)
56
class TestParser(TestParserMixin, TestEmailBase):
60
rfc_printable_ascii = bytes(range(33, 127)).decode('ascii')
61
rfc_atext_chars = (string.ascii_letters + string.digits +
62
"!#$%&\'*+-/=?^_`{}|~")
63
rfc_dtext_chars = rfc_printable_ascii.translate(str.maketrans('','',r'\[]'))
65
def test__wsp_splitter_one_word(self):
66
self.assertEqual(parser._wsp_splitter('foo', 1), ['foo'])
68
def test__wsp_splitter_two_words(self):
69
self.assertEqual(parser._wsp_splitter('foo def', 1),
72
def test__wsp_splitter_ws_runs(self):
73
self.assertEqual(parser._wsp_splitter('foo \t def jik', 1),
74
['foo', ' \t ', 'def jik'])
79
def test_get_fws_only(self):
80
fws = self._test_get_x(parser.get_fws, ' \t ', ' \t ', ' ', [], '')
81
self.assertEqual(fws.token_type, 'fws')
83
def test_get_fws_space(self):
84
self._test_get_x(parser.get_fws, ' foo', ' ', ' ', [], 'foo')
86
def test_get_fws_ws_run(self):
87
self._test_get_x(parser.get_fws, ' \t foo ', ' \t ', ' ', [], 'foo ')
91
def test_get_encoded_word_missing_start_raises(self):
92
with self.assertRaises(errors.HeaderParseError):
93
parser.get_encoded_word('abc')
95
def test_get_encoded_word_missing_end_raises(self):
96
with self.assertRaises(errors.HeaderParseError):
97
parser.get_encoded_word('=?abc')
99
def test_get_encoded_word_missing_middle_raises(self):
100
with self.assertRaises(errors.HeaderParseError):
101
parser.get_encoded_word('=?abc?=')
103
def test_get_encoded_word_valid_ew(self):
104
self._test_get_x(parser.get_encoded_word,
105
'=?us-ascii?q?this_is_a_test?= bird',
111
def test_get_encoded_word_internal_spaces(self):
112
self._test_get_x(parser.get_encoded_word,
113
'=?us-ascii?q?this is a test?= bird',
116
[errors.InvalidHeaderDefect],
119
def test_get_encoded_word_gets_first(self):
120
self._test_get_x(parser.get_encoded_word,
121
'=?us-ascii?q?first?= =?utf-8?q?second?=',
125
' =?utf-8?q?second?=')
127
def test_get_encoded_word_gets_first_even_if_no_space(self):
128
self._test_get_x(parser.get_encoded_word,
129
'=?us-ascii?q?first?==?utf-8?q?second?=',
133
'=?utf-8?q?second?=')
135
def test_get_encoded_word_sets_extra_attributes(self):
136
ew = self._test_get_x(parser.get_encoded_word,
137
'=?us-ascii*jive?q?first_second?=',
142
self.assertEqual(ew.encoded, '=?us-ascii*jive?q?first_second?=')
143
self.assertEqual(ew.charset, 'us-ascii')
144
self.assertEqual(ew.lang, 'jive')
146
def test_get_encoded_word_lang_default_is_blank(self):
147
ew = self._test_get_x(parser.get_encoded_word,
148
'=?us-ascii?q?first_second?=',
153
self.assertEqual(ew.encoded, '=?us-ascii?q?first_second?=')
154
self.assertEqual(ew.charset, 'us-ascii')
155
self.assertEqual(ew.lang, '')
157
def test_get_encoded_word_non_printable_defect(self):
158
self._test_get_x(parser.get_encoded_word,
159
'=?us-ascii?q?first\x02second?=',
162
[errors.NonPrintableDefect],
165
def test_get_encoded_word_leading_internal_space(self):
166
self._test_get_x(parser.get_encoded_word,
167
'=?us-ascii?q?=20foo?=',
173
def test_get_encoded_word_quopri_utf_escape_follows_cte(self):
175
self._test_get_x(parser.get_encoded_word,
176
'=?utf-8?q?=C3=89ric?=',
184
def _get_unst(self, value):
185
token = parser.get_unstructured(value)
188
def test_get_unstructured_null(self):
189
self._test_get_x(self._get_unst, '', '', '', [], '')
191
def test_get_unstructured_one_word(self):
192
self._test_get_x(self._get_unst, 'foo', 'foo', 'foo', [], '')
194
def test_get_unstructured_normal_phrase(self):
195
self._test_get_x(self._get_unst, 'foo bar bird',
201
def test_get_unstructured_normal_phrase_with_whitespace(self):
202
self._test_get_x(self._get_unst, 'foo \t bar bird',
208
def test_get_unstructured_leading_whitespace(self):
209
self._test_get_x(self._get_unst, ' foo bar',
215
def test_get_unstructured_trailing_whitespace(self):
216
self._test_get_x(self._get_unst, 'foo bar ',
222
def test_get_unstructured_leading_and_trailing_whitespace(self):
223
self._test_get_x(self._get_unst, ' foo bar ',
229
def test_get_unstructured_one_valid_ew_no_ws(self):
230
self._test_get_x(self._get_unst, '=?us-ascii?q?bar?=',
236
def test_get_unstructured_one_ew_trailing_ws(self):
237
self._test_get_x(self._get_unst, '=?us-ascii?q?bar?= ',
243
def test_get_unstructured_one_valid_ew_trailing_text(self):
244
self._test_get_x(self._get_unst, '=?us-ascii?q?bar?= bird',
250
def test_get_unstructured_phrase_with_ew_in_middle_of_text(self):
251
self._test_get_x(self._get_unst, 'foo =?us-ascii?q?bar?= bird',
257
def test_get_unstructured_phrase_with_two_ew(self):
258
self._test_get_x(self._get_unst,
259
'foo =?us-ascii?q?bar?= =?us-ascii?q?bird?=',
265
def test_get_unstructured_phrase_with_two_ew_trailing_ws(self):
266
self._test_get_x(self._get_unst,
267
'foo =?us-ascii?q?bar?= =?us-ascii?q?bird?= ',
273
def test_get_unstructured_phrase_with_ew_with_leading_ws(self):
274
self._test_get_x(self._get_unst,
275
' =?us-ascii?q?bar?=',
281
def test_get_unstructured_phrase_with_two_ew_extra_ws(self):
282
self._test_get_x(self._get_unst,
283
'foo =?us-ascii?q?bar?= \t =?us-ascii?q?bird?=',
289
def test_get_unstructured_two_ew_extra_ws_trailing_text(self):
290
self._test_get_x(self._get_unst,
291
'=?us-ascii?q?test?= =?us-ascii?q?foo?= val',
297
def test_get_unstructured_ew_with_internal_ws(self):
298
self._test_get_x(self._get_unst,
299
'=?iso-8859-1?q?hello=20world?=',
305
def test_get_unstructured_ew_with_internal_leading_ws(self):
306
self._test_get_x(self._get_unst,
307
' =?us-ascii?q?=20test?= =?us-ascii?q?=20foo?= val',
313
def test_get_unstructured_invaild_ew(self):
314
self._test_get_x(self._get_unst,
321
def test_get_unstructured_undecodable_bytes(self):
322
self._test_get_x(self._get_unst,
323
b'test \xACfoo val'.decode('ascii', 'surrogateescape'),
324
'test \uDCACfoo val',
325
'test \uDCACfoo val',
326
[errors.UndecodableBytesDefect],
329
def test_get_unstructured_undecodable_bytes_in_EW(self):
330
self._test_get_x(self._get_unst,
331
(b'=?us-ascii?q?=20test?= =?us-ascii?q?=20\xACfoo?='
332
b' val').decode('ascii', 'surrogateescape'),
333
' test \uDCACfoo val',
334
' test \uDCACfoo val',
335
[errors.UndecodableBytesDefect]*2,
338
def test_get_unstructured_missing_base64_padding(self):
339
self._test_get_x(self._get_unst,
343
[errors.InvalidBase64PaddingDefect],
346
def test_get_unstructured_invalid_base64_character(self):
347
self._test_get_x(self._get_unst,
348
'=?utf-8?b?dm\x01k===?=',
351
[errors.InvalidBase64CharactersDefect],
354
def test_get_unstructured_invalid_base64_character_and_bad_padding(self):
355
self._test_get_x(self._get_unst,
356
'=?utf-8?b?dm\x01k?=',
359
[errors.InvalidBase64CharactersDefect,
360
errors.InvalidBase64PaddingDefect],
363
def test_get_unstructured_no_whitespace_between_ews(self):
364
self._test_get_x(self._get_unst,
365
'=?utf-8?q?foo?==?utf-8?q?bar?=',
368
[errors.InvalidHeaderDefect],
373
def test_get_qp_ctext_only(self):
374
ptext = self._test_get_x(parser.get_qp_ctext,
375
'foobar', 'foobar', ' ', [], '')
376
self.assertEqual(ptext.token_type, 'ptext')
378
def test_get_qp_ctext_all_printables(self):
379
with_qp = self.rfc_printable_ascii.replace('\\', '\\\\')
380
with_qp = with_qp. replace('(', r'\(')
381
with_qp = with_qp.replace(')', r'\)')
382
ptext = self._test_get_x(parser.get_qp_ctext,
383
with_qp, self.rfc_printable_ascii, ' ', [], '')
385
def test_get_qp_ctext_two_words_gets_first(self):
386
self._test_get_x(parser.get_qp_ctext,
387
'foo de', 'foo', ' ', [], ' de')
389
def test_get_qp_ctext_following_wsp_preserved(self):
390
self._test_get_x(parser.get_qp_ctext,
391
'foo \t\tde', 'foo', ' ', [], ' \t\tde')
393
def test_get_qp_ctext_up_to_close_paren_only(self):
394
self._test_get_x(parser.get_qp_ctext,
395
'foo)', 'foo', ' ', [], ')')
397
def test_get_qp_ctext_wsp_before_close_paren_preserved(self):
398
self._test_get_x(parser.get_qp_ctext,
399
'foo )', 'foo', ' ', [], ' )')
401
def test_get_qp_ctext_close_paren_mid_word(self):
402
self._test_get_x(parser.get_qp_ctext,
403
'foo)bar', 'foo', ' ', [], ')bar')
405
def test_get_qp_ctext_up_to_open_paren_only(self):
406
self._test_get_x(parser.get_qp_ctext,
407
'foo(', 'foo', ' ', [], '(')
409
def test_get_qp_ctext_wsp_before_open_paren_preserved(self):
410
self._test_get_x(parser.get_qp_ctext,
411
'foo (', 'foo', ' ', [], ' (')
413
def test_get_qp_ctext_open_paren_mid_word(self):
414
self._test_get_x(parser.get_qp_ctext,
415
'foo(bar', 'foo', ' ', [], '(bar')
417
def test_get_qp_ctext_non_printables(self):
418
ptext = self._test_get_x(parser.get_qp_ctext,
419
'foo\x00bar)', 'foo\x00bar', ' ',
420
[errors.NonPrintableDefect], ')')
421
self.assertEqual(ptext.defects[0].non_printables[0], '\x00')
425
def test_get_qcontent_only(self):
426
ptext = self._test_get_x(parser.get_qcontent,
427
'foobar', 'foobar', 'foobar', [], '')
428
self.assertEqual(ptext.token_type, 'ptext')
430
def test_get_qcontent_all_printables(self):
431
with_qp = self.rfc_printable_ascii.replace('\\', '\\\\')
432
with_qp = with_qp. replace('"', r'\"')
433
ptext = self._test_get_x(parser.get_qcontent, with_qp,
434
self.rfc_printable_ascii,
435
self.rfc_printable_ascii, [], '')
437
def test_get_qcontent_two_words_gets_first(self):
438
self._test_get_x(parser.get_qcontent,
439
'foo de', 'foo', 'foo', [], ' de')
441
def test_get_qcontent_following_wsp_preserved(self):
442
self._test_get_x(parser.get_qcontent,
443
'foo \t\tde', 'foo', 'foo', [], ' \t\tde')
445
def test_get_qcontent_up_to_dquote_only(self):
446
self._test_get_x(parser.get_qcontent,
447
'foo"', 'foo', 'foo', [], '"')
449
def test_get_qcontent_wsp_before_close_paren_preserved(self):
450
self._test_get_x(parser.get_qcontent,
451
'foo "', 'foo', 'foo', [], ' "')
453
def test_get_qcontent_close_paren_mid_word(self):
454
self._test_get_x(parser.get_qcontent,
455
'foo"bar', 'foo', 'foo', [], '"bar')
457
def test_get_qcontent_non_printables(self):
458
ptext = self._test_get_x(parser.get_qcontent,
459
'foo\x00fg"', 'foo\x00fg', 'foo\x00fg',
460
[errors.NonPrintableDefect], '"')
461
self.assertEqual(ptext.defects[0].non_printables[0], '\x00')
465
def test_get_atext_only(self):
466
atext = self._test_get_x(parser.get_atext,
467
'foobar', 'foobar', 'foobar', [], '')
468
self.assertEqual(atext.token_type, 'atext')
470
def test_get_atext_all_atext(self):
471
atext = self._test_get_x(parser.get_atext, self.rfc_atext_chars,
472
self.rfc_atext_chars,
473
self.rfc_atext_chars, [], '')
475
def test_get_atext_two_words_gets_first(self):
476
self._test_get_x(parser.get_atext,
477
'foo bar', 'foo', 'foo', [], ' bar')
479
def test_get_atext_following_wsp_preserved(self):
480
self._test_get_x(parser.get_atext,
481
'foo \t\tbar', 'foo', 'foo', [], ' \t\tbar')
483
def test_get_atext_up_to_special(self):
484
self._test_get_x(parser.get_atext,
485
'foo@bar', 'foo', 'foo', [], '@bar')
487
def test_get_atext_non_printables(self):
488
atext = self._test_get_x(parser.get_atext,
489
'foo\x00bar(', 'foo\x00bar', 'foo\x00bar',
490
[errors.NonPrintableDefect], '(')
491
self.assertEqual(atext.defects[0].non_printables[0], '\x00')
493
# get_bare_quoted_string
495
def test_get_bare_quoted_string_only(self):
496
bqs = self._test_get_x(parser.get_bare_quoted_string,
497
'"foo"', '"foo"', 'foo', [], '')
498
self.assertEqual(bqs.token_type, 'bare-quoted-string')
500
def test_get_bare_quoted_string_must_start_with_dquote(self):
501
with self.assertRaises(errors.HeaderParseError):
502
parser.get_bare_quoted_string('foo"')
503
with self.assertRaises(errors.HeaderParseError):
504
parser.get_bare_quoted_string(' "foo"')
506
def test_get_bare_quoted_string_following_wsp_preserved(self):
507
self._test_get_x(parser.get_bare_quoted_string,
508
'"foo"\t bar', '"foo"', 'foo', [], '\t bar')
510
def test_get_bare_quoted_string_multiple_words(self):
511
self._test_get_x(parser.get_bare_quoted_string,
512
'"foo bar moo"', '"foo bar moo"', 'foo bar moo', [], '')
514
def test_get_bare_quoted_string_multiple_words_wsp_preserved(self):
515
self._test_get_x(parser.get_bare_quoted_string,
516
'" foo moo\t"', '" foo moo\t"', ' foo moo\t', [], '')
518
def test_get_bare_quoted_string_end_dquote_mid_word(self):
519
self._test_get_x(parser.get_bare_quoted_string,
520
'"foo"bar', '"foo"', 'foo', [], 'bar')
522
def test_get_bare_quoted_string_quoted_dquote(self):
523
self._test_get_x(parser.get_bare_quoted_string,
524
r'"foo\"in"a', r'"foo\"in"', 'foo"in', [], 'a')
526
def test_get_bare_quoted_string_non_printables(self):
527
self._test_get_x(parser.get_bare_quoted_string,
528
'"a\x01a"', '"a\x01a"', 'a\x01a',
529
[errors.NonPrintableDefect], '')
531
def test_get_bare_quoted_string_no_end_dquote(self):
532
self._test_get_x(parser.get_bare_quoted_string,
533
'"foo', '"foo"', 'foo',
534
[errors.InvalidHeaderDefect], '')
535
self._test_get_x(parser.get_bare_quoted_string,
536
'"foo ', '"foo "', 'foo ',
537
[errors.InvalidHeaderDefect], '')
539
def test_get_bare_quoted_string_empty_quotes(self):
540
self._test_get_x(parser.get_bare_quoted_string,
541
'""', '""', '', [], '')
545
def test_get_comment_only(self):
546
comment = self._test_get_x(parser.get_comment,
547
'(comment)', '(comment)', ' ', [], '', ['comment'])
548
self.assertEqual(comment.token_type, 'comment')
550
def test_get_comment_must_start_with_paren(self):
551
with self.assertRaises(errors.HeaderParseError):
552
parser.get_comment('foo"')
553
with self.assertRaises(errors.HeaderParseError):
554
parser.get_comment(' (foo"')
556
def test_get_comment_following_wsp_preserved(self):
557
self._test_get_x(parser.get_comment,
558
'(comment) \t', '(comment)', ' ', [], ' \t', ['comment'])
560
def test_get_comment_multiple_words(self):
561
self._test_get_x(parser.get_comment,
562
'(foo bar) \t', '(foo bar)', ' ', [], ' \t', ['foo bar'])
564
def test_get_comment_multiple_words_wsp_preserved(self):
565
self._test_get_x(parser.get_comment,
566
'( foo bar\t ) \t', '( foo bar\t )', ' ', [], ' \t',
569
def test_get_comment_end_paren_mid_word(self):
570
self._test_get_x(parser.get_comment,
571
'(foo)bar', '(foo)', ' ', [], 'bar', ['foo'])
573
def test_get_comment_quoted_parens(self):
574
self._test_get_x(parser.get_comment,
575
'(foo\) \(\)bar)', '(foo\) \(\)bar)', ' ', [], '', ['foo) ()bar'])
577
def test_get_comment_non_printable(self):
578
self._test_get_x(parser.get_comment,
579
'(foo\x7Fbar)', '(foo\x7Fbar)', ' ',
580
[errors.NonPrintableDefect], '', ['foo\x7Fbar'])
582
def test_get_comment_no_end_paren(self):
583
self._test_get_x(parser.get_comment,
584
'(foo bar', '(foo bar)', ' ',
585
[errors.InvalidHeaderDefect], '', ['foo bar'])
586
self._test_get_x(parser.get_comment,
587
'(foo bar ', '(foo bar )', ' ',
588
[errors.InvalidHeaderDefect], '', ['foo bar '])
590
def test_get_comment_nested_comment(self):
591
comment = self._test_get_x(parser.get_comment,
592
'(foo(bar))', '(foo(bar))', ' ', [], '', ['foo(bar)'])
593
self.assertEqual(comment[1].content, 'bar')
595
def test_get_comment_nested_comment_wsp(self):
596
comment = self._test_get_x(parser.get_comment,
597
'(foo ( bar ) )', '(foo ( bar ) )', ' ', [], '', ['foo ( bar ) '])
598
self.assertEqual(comment[2].content, ' bar ')
600
def test_get_comment_empty_comment(self):
601
self._test_get_x(parser.get_comment,
602
'()', '()', ' ', [], '', [''])
604
def test_get_comment_multiple_nesting(self):
605
comment = self._test_get_x(parser.get_comment,
606
'(((((foo)))))', '(((((foo)))))', ' ', [], '', ['((((foo))))'])
607
for i in range(4, 0, -1):
608
self.assertEqual(comment[0].content, '('*(i-1)+'foo'+')'*(i-1))
610
self.assertEqual(comment.content, 'foo')
612
def test_get_comment_missing_end_of_nesting(self):
613
self._test_get_x(parser.get_comment,
614
'(((((foo)))', '(((((foo)))))', ' ',
615
[errors.InvalidHeaderDefect]*2, '', ['((((foo))))'])
617
def test_get_comment_qs_in_nested_comment(self):
618
comment = self._test_get_x(parser.get_comment,
619
'(foo (b\)))', '(foo (b\)))', ' ', [], '', ['foo (b\))'])
620
self.assertEqual(comment[2].content, 'b)')
624
def test_get_cfws_only_ws(self):
625
cfws = self._test_get_x(parser.get_cfws,
626
' \t \t', ' \t \t', ' ', [], '', [])
627
self.assertEqual(cfws.token_type, 'cfws')
629
def test_get_cfws_only_comment(self):
630
cfws = self._test_get_x(parser.get_cfws,
631
'(foo)', '(foo)', ' ', [], '', ['foo'])
632
self.assertEqual(cfws[0].content, 'foo')
634
def test_get_cfws_only_mixed(self):
635
cfws = self._test_get_x(parser.get_cfws,
636
' (foo ) ( bar) ', ' (foo ) ( bar) ', ' ', [], '',
638
self.assertEqual(cfws[1].content, 'foo ')
639
self.assertEqual(cfws[3].content, ' bar')
641
def test_get_cfws_ends_at_non_leader(self):
642
cfws = self._test_get_x(parser.get_cfws,
643
'(foo) bar', '(foo) ', ' ', [], 'bar', ['foo'])
644
self.assertEqual(cfws[0].content, 'foo')
646
def test_get_cfws_ends_at_non_printable(self):
647
cfws = self._test_get_x(parser.get_cfws,
648
'(foo) \x07', '(foo) ', ' ', [], '\x07', ['foo'])
649
self.assertEqual(cfws[0].content, 'foo')
651
def test_get_cfws_non_printable_in_comment(self):
652
cfws = self._test_get_x(parser.get_cfws,
653
'(foo \x07) "test"', '(foo \x07) ', ' ',
654
[errors.NonPrintableDefect], '"test"', ['foo \x07'])
655
self.assertEqual(cfws[0].content, 'foo \x07')
657
def test_get_cfws_header_ends_in_comment(self):
658
cfws = self._test_get_x(parser.get_cfws,
659
' (foo ', ' (foo )', ' ',
660
[errors.InvalidHeaderDefect], '', ['foo '])
661
self.assertEqual(cfws[1].content, 'foo ')
663
def test_get_cfws_multiple_nested_comments(self):
664
cfws = self._test_get_x(parser.get_cfws,
665
'(foo (bar)) ((a)(a))', '(foo (bar)) ((a)(a))', ' ', [],
666
'', ['foo (bar)', '(a)(a)'])
667
self.assertEqual(cfws[0].comments, ['foo (bar)'])
668
self.assertEqual(cfws[2].comments, ['(a)(a)'])
672
def test_get_quoted_string_only(self):
673
qs = self._test_get_x(parser.get_quoted_string,
674
'"bob"', '"bob"', 'bob', [], '')
675
self.assertEqual(qs.token_type, 'quoted-string')
676
self.assertEqual(qs.quoted_value, '"bob"')
677
self.assertEqual(qs.content, 'bob')
679
def test_get_quoted_string_with_wsp(self):
680
qs = self._test_get_x(parser.get_quoted_string,
681
'\t "bob" ', '\t "bob" ', ' bob ', [], '')
682
self.assertEqual(qs.quoted_value, ' "bob" ')
683
self.assertEqual(qs.content, 'bob')
685
def test_get_quoted_string_with_comments_and_wsp(self):
686
qs = self._test_get_x(parser.get_quoted_string,
687
' (foo) "bob"(bar)', ' (foo) "bob"(bar)', ' bob ', [], '')
688
self.assertEqual(qs[0][1].content, 'foo')
689
self.assertEqual(qs[2][0].content, 'bar')
690
self.assertEqual(qs.content, 'bob')
691
self.assertEqual(qs.quoted_value, ' "bob" ')
693
def test_get_quoted_string_with_multiple_comments(self):
694
qs = self._test_get_x(parser.get_quoted_string,
695
' (foo) (bar) "bob"(bird)', ' (foo) (bar) "bob"(bird)', ' bob ',
697
self.assertEqual(qs[0].comments, ['foo', 'bar'])
698
self.assertEqual(qs[2].comments, ['bird'])
699
self.assertEqual(qs.content, 'bob')
700
self.assertEqual(qs.quoted_value, ' "bob" ')
702
def test_get_quoted_string_non_printable_in_comment(self):
703
qs = self._test_get_x(parser.get_quoted_string,
704
' (\x0A) "bob"', ' (\x0A) "bob"', ' bob',
705
[errors.NonPrintableDefect], '')
706
self.assertEqual(qs[0].comments, ['\x0A'])
707
self.assertEqual(qs.content, 'bob')
708
self.assertEqual(qs.quoted_value, ' "bob"')
710
def test_get_quoted_string_non_printable_in_qcontent(self):
711
qs = self._test_get_x(parser.get_quoted_string,
712
' (a) "a\x0B"', ' (a) "a\x0B"', ' a\x0B',
713
[errors.NonPrintableDefect], '')
714
self.assertEqual(qs[0].comments, ['a'])
715
self.assertEqual(qs.content, 'a\x0B')
716
self.assertEqual(qs.quoted_value, ' "a\x0B"')
718
def test_get_quoted_string_internal_ws(self):
719
qs = self._test_get_x(parser.get_quoted_string,
720
' (a) "foo bar "', ' (a) "foo bar "', ' foo bar ',
722
self.assertEqual(qs[0].comments, ['a'])
723
self.assertEqual(qs.content, 'foo bar ')
724
self.assertEqual(qs.quoted_value, ' "foo bar "')
726
def test_get_quoted_string_header_ends_in_comment(self):
727
qs = self._test_get_x(parser.get_quoted_string,
728
' (a) "bob" (a', ' (a) "bob" (a)', ' bob ',
729
[errors.InvalidHeaderDefect], '')
730
self.assertEqual(qs[0].comments, ['a'])
731
self.assertEqual(qs[2].comments, ['a'])
732
self.assertEqual(qs.content, 'bob')
733
self.assertEqual(qs.quoted_value, ' "bob" ')
735
def test_get_quoted_string_header_ends_in_qcontent(self):
736
qs = self._test_get_x(parser.get_quoted_string,
737
' (a) "bob', ' (a) "bob"', ' bob',
738
[errors.InvalidHeaderDefect], '')
739
self.assertEqual(qs[0].comments, ['a'])
740
self.assertEqual(qs.content, 'bob')
741
self.assertEqual(qs.quoted_value, ' "bob"')
743
def test_get_quoted_string_no_quoted_string(self):
744
with self.assertRaises(errors.HeaderParseError):
745
parser.get_quoted_string(' (ab) xyz')
747
def test_get_quoted_string_qs_ends_at_noncfws(self):
748
qs = self._test_get_x(parser.get_quoted_string,
749
'\t "bob" fee', '\t "bob" ', ' bob ', [], 'fee')
750
self.assertEqual(qs.content, 'bob')
751
self.assertEqual(qs.quoted_value, ' "bob" ')
755
def test_get_atom_only(self):
756
atom = self._test_get_x(parser.get_atom,
757
'bob', 'bob', 'bob', [], '')
758
self.assertEqual(atom.token_type, 'atom')
760
def test_get_atom_with_wsp(self):
761
self._test_get_x(parser.get_atom,
762
'\t bob ', '\t bob ', ' bob ', [], '')
764
def test_get_atom_with_comments_and_wsp(self):
765
atom = self._test_get_x(parser.get_atom,
766
' (foo) bob(bar)', ' (foo) bob(bar)', ' bob ', [], '')
767
self.assertEqual(atom[0][1].content, 'foo')
768
self.assertEqual(atom[2][0].content, 'bar')
770
def test_get_atom_with_multiple_comments(self):
771
atom = self._test_get_x(parser.get_atom,
772
' (foo) (bar) bob(bird)', ' (foo) (bar) bob(bird)', ' bob ',
774
self.assertEqual(atom[0].comments, ['foo', 'bar'])
775
self.assertEqual(atom[2].comments, ['bird'])
777
def test_get_atom_non_printable_in_comment(self):
778
atom = self._test_get_x(parser.get_atom,
779
' (\x0A) bob', ' (\x0A) bob', ' bob',
780
[errors.NonPrintableDefect], '')
781
self.assertEqual(atom[0].comments, ['\x0A'])
783
def test_get_atom_non_printable_in_atext(self):
784
atom = self._test_get_x(parser.get_atom,
785
' (a) a\x0B', ' (a) a\x0B', ' a\x0B',
786
[errors.NonPrintableDefect], '')
787
self.assertEqual(atom[0].comments, ['a'])
789
def test_get_atom_header_ends_in_comment(self):
790
atom = self._test_get_x(parser.get_atom,
791
' (a) bob (a', ' (a) bob (a)', ' bob ',
792
[errors.InvalidHeaderDefect], '')
793
self.assertEqual(atom[0].comments, ['a'])
794
self.assertEqual(atom[2].comments, ['a'])
796
def test_get_atom_no_atom(self):
797
with self.assertRaises(errors.HeaderParseError):
798
parser.get_atom(' (ab) ')
800
def test_get_atom_no_atom_before_special(self):
801
with self.assertRaises(errors.HeaderParseError):
802
parser.get_atom(' (ab) @')
804
def test_get_atom_atom_ends_at_special(self):
805
atom = self._test_get_x(parser.get_atom,
806
' (foo) bob(bar) @bang', ' (foo) bob(bar) ', ' bob ', [], '@bang')
807
self.assertEqual(atom[0].comments, ['foo'])
808
self.assertEqual(atom[2].comments, ['bar'])
810
def test_get_atom_atom_ends_at_noncfws(self):
811
self._test_get_x(parser.get_atom,
812
'bob fred', 'bob ', 'bob ', [], 'fred')
814
def test_get_atom_rfc2047_atom(self):
815
self._test_get_x(parser.get_atom,
816
'=?utf-8?q?=20bob?=', ' bob', ' bob', [], '')
820
def test_get_dot_atom_text(self):
821
dot_atom_text = self._test_get_x(parser.get_dot_atom_text,
822
'foo.bar.bang', 'foo.bar.bang', 'foo.bar.bang', [], '')
823
self.assertEqual(dot_atom_text.token_type, 'dot-atom-text')
824
self.assertEqual(len(dot_atom_text), 5)
826
def test_get_dot_atom_text_lone_atom_is_valid(self):
827
dot_atom_text = self._test_get_x(parser.get_dot_atom_text,
828
'foo', 'foo', 'foo', [], '')
830
def test_get_dot_atom_text_raises_on_leading_dot(self):
831
with self.assertRaises(errors.HeaderParseError):
832
parser.get_dot_atom_text('.foo.bar')
834
def test_get_dot_atom_text_raises_on_trailing_dot(self):
835
with self.assertRaises(errors.HeaderParseError):
836
parser.get_dot_atom_text('foo.bar.')
838
def test_get_dot_atom_text_raises_on_leading_non_atext(self):
839
with self.assertRaises(errors.HeaderParseError):
840
parser.get_dot_atom_text(' foo.bar')
841
with self.assertRaises(errors.HeaderParseError):
842
parser.get_dot_atom_text('@foo.bar')
843
with self.assertRaises(errors.HeaderParseError):
844
parser.get_dot_atom_text('"foo.bar"')
846
def test_get_dot_atom_text_trailing_text_preserved(self):
847
dot_atom_text = self._test_get_x(parser.get_dot_atom_text,
848
'foo@bar', 'foo', 'foo', [], '@bar')
850
def test_get_dot_atom_text_trailing_ws_preserved(self):
851
dot_atom_text = self._test_get_x(parser.get_dot_atom_text,
852
'foo .bar', 'foo', 'foo', [], ' .bar')
856
def test_get_dot_atom_only(self):
857
dot_atom = self._test_get_x(parser.get_dot_atom,
858
'foo.bar.bing', 'foo.bar.bing', 'foo.bar.bing', [], '')
859
self.assertEqual(dot_atom.token_type, 'dot-atom')
860
self.assertEqual(len(dot_atom), 1)
862
def test_get_dot_atom_with_wsp(self):
863
self._test_get_x(parser.get_dot_atom,
864
'\t foo.bar.bing ', '\t foo.bar.bing ', ' foo.bar.bing ', [], '')
866
def test_get_dot_atom_with_comments_and_wsp(self):
867
self._test_get_x(parser.get_dot_atom,
868
' (sing) foo.bar.bing (here) ', ' (sing) foo.bar.bing (here) ',
869
' foo.bar.bing ', [], '')
871
def test_get_dot_atom_space_ends_dot_atom(self):
872
self._test_get_x(parser.get_dot_atom,
873
' (sing) foo.bar .bing (here) ', ' (sing) foo.bar ',
874
' foo.bar ', [], '.bing (here) ')
876
def test_get_dot_atom_no_atom_raises(self):
877
with self.assertRaises(errors.HeaderParseError):
878
parser.get_dot_atom(' (foo) ')
880
def test_get_dot_atom_leading_dot_raises(self):
881
with self.assertRaises(errors.HeaderParseError):
882
parser.get_dot_atom(' (foo) .bar')
884
def test_get_dot_atom_two_dots_raises(self):
885
with self.assertRaises(errors.HeaderParseError):
886
parser.get_dot_atom('bar..bang')
888
def test_get_dot_atom_trailing_dot_raises(self):
889
with self.assertRaises(errors.HeaderParseError):
890
parser.get_dot_atom(' (foo) bar.bang. foo')
892
def test_get_dot_atom_rfc2047_atom(self):
893
self._test_get_x(parser.get_dot_atom,
894
'=?utf-8?q?=20bob?=', ' bob', ' bob', [], '')
896
# get_word (if this were black box we'd repeat all the qs/atom tests)
898
def test_get_word_atom_yields_atom(self):
899
word = self._test_get_x(parser.get_word,
900
' (foo) bar (bang) :ah', ' (foo) bar (bang) ', ' bar ', [], ':ah')
901
self.assertEqual(word.token_type, 'atom')
902
self.assertEqual(word[0].token_type, 'cfws')
904
def test_get_word_qs_yields_qs(self):
905
word = self._test_get_x(parser.get_word,
906
'"bar " (bang) ah', '"bar " (bang) ', 'bar ', [], 'ah')
907
self.assertEqual(word.token_type, 'quoted-string')
908
self.assertEqual(word[0].token_type, 'bare-quoted-string')
909
self.assertEqual(word[0].value, 'bar ')
910
self.assertEqual(word.content, 'bar ')
912
def test_get_word_ends_at_dot(self):
913
self._test_get_x(parser.get_word,
914
'foo.', 'foo', 'foo', [], '.')
918
def test_get_phrase_simple(self):
919
phrase = self._test_get_x(parser.get_phrase,
920
'"Fred A. Johnson" is his name, oh.',
921
'"Fred A. Johnson" is his name',
922
'Fred A. Johnson is his name',
925
self.assertEqual(phrase.token_type, 'phrase')
927
def test_get_phrase_complex(self):
928
phrase = self._test_get_x(parser.get_phrase,
929
' (A) bird (in (my|your)) "hand " is messy\t<>\t',
930
' (A) bird (in (my|your)) "hand " is messy\t',
931
' bird hand is messy ',
934
self.assertEqual(phrase[0][0].comments, ['A'])
935
self.assertEqual(phrase[0][2].comments, ['in (my|your)'])
937
def test_get_phrase_obsolete(self):
938
phrase = self._test_get_x(parser.get_phrase,
939
'Fred A.(weird).O Johnson',
940
'Fred A.(weird).O Johnson',
941
'Fred A. .O Johnson',
942
[errors.ObsoleteHeaderDefect]*3,
944
self.assertEqual(len(phrase), 7)
945
self.assertEqual(phrase[3].comments, ['weird'])
947
def test_get_phrase_pharse_must_start_with_word(self):
948
phrase = self._test_get_x(parser.get_phrase,
949
'(even weirder).name',
950
'(even weirder).name',
952
[errors.InvalidHeaderDefect] + [errors.ObsoleteHeaderDefect]*2,
954
self.assertEqual(len(phrase), 3)
955
self.assertEqual(phrase[0].comments, ['even weirder'])
957
def test_get_phrase_ending_with_obsolete(self):
958
phrase = self._test_get_x(parser.get_phrase,
959
'simple phrase.(with trailing comment):boo',
960
'simple phrase.(with trailing comment)',
962
[errors.ObsoleteHeaderDefect]*2,
964
self.assertEqual(len(phrase), 4)
965
self.assertEqual(phrase[3].comments, ['with trailing comment'])
967
def get_phrase_cfws_only_raises(self):
968
with self.assertRaises(errors.HeaderParseError):
969
parser.get_phrase(' (foo) ')
973
def test_get_local_part_simple(self):
974
local_part = self._test_get_x(parser.get_local_part,
975
'dinsdale@python.org', 'dinsdale', 'dinsdale', [], '@python.org')
976
self.assertEqual(local_part.token_type, 'local-part')
977
self.assertEqual(local_part.local_part, 'dinsdale')
979
def test_get_local_part_with_dot(self):
980
local_part = self._test_get_x(parser.get_local_part,
981
'Fred.A.Johnson@python.org',
986
self.assertEqual(local_part.local_part, 'Fred.A.Johnson')
988
def test_get_local_part_with_whitespace(self):
989
local_part = self._test_get_x(parser.get_local_part,
990
' Fred.A.Johnson @python.org',
995
self.assertEqual(local_part.local_part, 'Fred.A.Johnson')
997
def test_get_local_part_with_cfws(self):
998
local_part = self._test_get_x(parser.get_local_part,
999
' (foo) Fred.A.Johnson (bar (bird)) @python.org',
1000
' (foo) Fred.A.Johnson (bar (bird)) ',
1004
self.assertEqual(local_part.local_part, 'Fred.A.Johnson')
1005
self.assertEqual(local_part[0][0].comments, ['foo'])
1006
self.assertEqual(local_part[0][2].comments, ['bar (bird)'])
1008
def test_get_local_part_simple_quoted(self):
1009
local_part = self._test_get_x(parser.get_local_part,
1010
'"dinsdale"@python.org', '"dinsdale"', '"dinsdale"', [], '@python.org')
1011
self.assertEqual(local_part.token_type, 'local-part')
1012
self.assertEqual(local_part.local_part, 'dinsdale')
1014
def test_get_local_part_with_quoted_dot(self):
1015
local_part = self._test_get_x(parser.get_local_part,
1016
'"Fred.A.Johnson"@python.org',
1021
self.assertEqual(local_part.local_part, 'Fred.A.Johnson')
1023
def test_get_local_part_quoted_with_whitespace(self):
1024
local_part = self._test_get_x(parser.get_local_part,
1025
' "Fred A. Johnson" @python.org',
1026
' "Fred A. Johnson" ',
1027
' "Fred A. Johnson" ',
1030
self.assertEqual(local_part.local_part, 'Fred A. Johnson')
1032
def test_get_local_part_quoted_with_cfws(self):
1033
local_part = self._test_get_x(parser.get_local_part,
1034
' (foo) " Fred A. Johnson " (bar (bird)) @python.org',
1035
' (foo) " Fred A. Johnson " (bar (bird)) ',
1036
' " Fred A. Johnson " ',
1039
self.assertEqual(local_part.local_part, ' Fred A. Johnson ')
1040
self.assertEqual(local_part[0][0].comments, ['foo'])
1041
self.assertEqual(local_part[0][2].comments, ['bar (bird)'])
1044
def test_get_local_part_simple_obsolete(self):
1045
local_part = self._test_get_x(parser.get_local_part,
1046
'Fred. A.Johnson@python.org',
1049
[errors.ObsoleteHeaderDefect],
1051
self.assertEqual(local_part.local_part, 'Fred.A.Johnson')
1053
def test_get_local_part_complex_obsolete_1(self):
1054
local_part = self._test_get_x(parser.get_local_part,
1055
' (foo )Fred (bar).(bird) A.(sheep)Johnson."and dogs "@python.org',
1056
' (foo )Fred (bar).(bird) A.(sheep)Johnson."and dogs "',
1057
' Fred . A. Johnson.and dogs ',
1058
[errors.ObsoleteHeaderDefect],
1060
self.assertEqual(local_part.local_part, 'Fred.A.Johnson.and dogs ')
1062
def test_get_local_part_complex_obsolete_invalid(self):
1063
local_part = self._test_get_x(parser.get_local_part,
1064
' (foo )Fred (bar).(bird) A.(sheep)Johnson "and dogs"@python.org',
1065
' (foo )Fred (bar).(bird) A.(sheep)Johnson "and dogs"',
1066
' Fred . A. Johnson and dogs',
1067
[errors.InvalidHeaderDefect]*2,
1069
self.assertEqual(local_part.local_part, 'Fred.A.Johnson and dogs')
1071
def test_get_local_part_no_part_raises(self):
1072
with self.assertRaises(errors.HeaderParseError):
1073
parser.get_local_part(' (foo) ')
1075
def test_get_local_part_special_instead_raises(self):
1076
with self.assertRaises(errors.HeaderParseError):
1077
parser.get_local_part(' (foo) @python.org')
1079
def test_get_local_part_trailing_dot(self):
1080
local_part = self._test_get_x(parser.get_local_part,
1081
' borris.@python.org',
1084
[errors.InvalidHeaderDefect]*2,
1086
self.assertEqual(local_part.local_part, 'borris.')
1088
def test_get_local_part_trailing_dot_with_ws(self):
1089
local_part = self._test_get_x(parser.get_local_part,
1090
' borris. @python.org',
1093
[errors.InvalidHeaderDefect]*2,
1095
self.assertEqual(local_part.local_part, 'borris.')
1097
def test_get_local_part_leading_dot(self):
1098
local_part = self._test_get_x(parser.get_local_part,
1099
'.borris@python.org',
1102
[errors.InvalidHeaderDefect]*2,
1104
self.assertEqual(local_part.local_part, '.borris')
1106
def test_get_local_part_leading_dot_after_ws(self):
1107
local_part = self._test_get_x(parser.get_local_part,
1108
' .borris@python.org',
1111
[errors.InvalidHeaderDefect]*2,
1113
self.assertEqual(local_part.local_part, '.borris')
1115
def test_get_local_part_double_dot_raises(self):
1116
local_part = self._test_get_x(parser.get_local_part,
1117
' borris.(foo).natasha@python.org',
1118
' borris.(foo).natasha',
1119
' borris. .natasha',
1120
[errors.InvalidHeaderDefect]*2,
1122
self.assertEqual(local_part.local_part, 'borris..natasha')
1124
def test_get_local_part_quoted_strings_in_atom_list(self):
1125
local_part = self._test_get_x(parser.get_local_part,
1126
'""example" example"@example.com',
1127
'""example" example"',
1129
[errors.InvalidHeaderDefect]*3,
1131
self.assertEqual(local_part.local_part, 'example example')
1133
def test_get_local_part_valid_and_invalid_qp_in_atom_list(self):
1134
local_part = self._test_get_x(parser.get_local_part,
1135
r'"\\"example\\" example"@example.com',
1136
r'"\\"example\\" example"',
1137
r'\example\\ example',
1138
[errors.InvalidHeaderDefect]*5,
1140
self.assertEqual(local_part.local_part, r'\example\\ example')
1142
def test_get_local_part_unicode_defect(self):
1143
# Currently this only happens when parsing unicode, not when parsing
1144
# stuff that was originally binary.
1145
local_part = self._test_get_x(parser.get_local_part,
1146
'exámple@example.com',
1149
[errors.NonASCIILocalPartDefect],
1151
self.assertEqual(local_part.local_part, 'exámple')
1155
def test_get_dtext_only(self):
1156
dtext = self._test_get_x(parser.get_dtext,
1157
'foobar', 'foobar', 'foobar', [], '')
1158
self.assertEqual(dtext.token_type, 'ptext')
1160
def test_get_dtext_all_dtext(self):
1161
dtext = self._test_get_x(parser.get_dtext, self.rfc_dtext_chars,
1162
self.rfc_dtext_chars,
1163
self.rfc_dtext_chars, [], '')
1165
def test_get_dtext_two_words_gets_first(self):
1166
self._test_get_x(parser.get_dtext,
1167
'foo bar', 'foo', 'foo', [], ' bar')
1169
def test_get_dtext_following_wsp_preserved(self):
1170
self._test_get_x(parser.get_dtext,
1171
'foo \t\tbar', 'foo', 'foo', [], ' \t\tbar')
1173
def test_get_dtext_non_printables(self):
1174
dtext = self._test_get_x(parser.get_dtext,
1175
'foo\x00bar]', 'foo\x00bar', 'foo\x00bar',
1176
[errors.NonPrintableDefect], ']')
1177
self.assertEqual(dtext.defects[0].non_printables[0], '\x00')
1179
def test_get_dtext_with_qp(self):
1180
ptext = self._test_get_x(parser.get_dtext,
1181
r'foo\]\[\\bar\b\e\l\l',
1184
[errors.ObsoleteHeaderDefect],
1187
def test_get_dtext_up_to_close_bracket_only(self):
1188
self._test_get_x(parser.get_dtext,
1189
'foo]', 'foo', 'foo', [], ']')
1191
def test_get_dtext_wsp_before_close_bracket_preserved(self):
1192
self._test_get_x(parser.get_dtext,
1193
'foo ]', 'foo', 'foo', [], ' ]')
1195
def test_get_dtext_close_bracket_mid_word(self):
1196
self._test_get_x(parser.get_dtext,
1197
'foo]bar', 'foo', 'foo', [], ']bar')
1199
def test_get_dtext_up_to_open_bracket_only(self):
1200
self._test_get_x(parser.get_dtext,
1201
'foo[', 'foo', 'foo', [], '[')
1203
def test_get_dtext_wsp_before_open_bracket_preserved(self):
1204
self._test_get_x(parser.get_dtext,
1205
'foo [', 'foo', 'foo', [], ' [')
1207
def test_get_dtext_open_bracket_mid_word(self):
1208
self._test_get_x(parser.get_dtext,
1209
'foo[bar', 'foo', 'foo', [], '[bar')
1211
# get_domain_literal
1213
def test_get_domain_literal_only(self):
1214
domain_literal = domain_literal = self._test_get_x(parser.get_domain_literal,
1220
self.assertEqual(domain_literal.token_type, 'domain-literal')
1221
self.assertEqual(domain_literal.domain, '[127.0.0.1]')
1222
self.assertEqual(domain_literal.ip, '127.0.0.1')
1224
def test_get_domain_literal_with_internal_ws(self):
1225
domain_literal = self._test_get_x(parser.get_domain_literal,
1231
self.assertEqual(domain_literal.domain, '[127.0.0.1]')
1232
self.assertEqual(domain_literal.ip, '127.0.0.1')
1234
def test_get_domain_literal_with_surrounding_cfws(self):
1235
domain_literal = self._test_get_x(parser.get_domain_literal,
1236
'(foo)[ 127.0.0.1] (bar)',
1237
'(foo)[ 127.0.0.1] (bar)',
1241
self.assertEqual(domain_literal.domain, '[127.0.0.1]')
1242
self.assertEqual(domain_literal.ip, '127.0.0.1')
1244
def test_get_domain_literal_no_start_char_raises(self):
1245
with self.assertRaises(errors.HeaderParseError):
1246
parser.get_domain_literal('(foo) ')
1248
def test_get_domain_literal_no_start_char_before_special_raises(self):
1249
with self.assertRaises(errors.HeaderParseError):
1250
parser.get_domain_literal('(foo) @')
1252
def test_get_domain_literal_bad_dtext_char_before_special_raises(self):
1253
with self.assertRaises(errors.HeaderParseError):
1254
parser.get_domain_literal('(foo) [abc[@')
1258
def test_get_domain_regular_domain_only(self):
1259
domain = self._test_get_x(parser.get_domain,
1265
self.assertEqual(domain.token_type, 'domain')
1266
self.assertEqual(domain.domain, 'example.com')
1268
def test_get_domain_domain_literal_only(self):
1269
domain = self._test_get_x(parser.get_domain,
1275
self.assertEqual(domain.token_type, 'domain')
1276
self.assertEqual(domain.domain, '[127.0.0.1]')
1278
def test_get_domain_with_cfws(self):
1279
domain = self._test_get_x(parser.get_domain,
1280
'(foo) example.com(bar)\t',
1281
'(foo) example.com(bar)\t',
1285
self.assertEqual(domain.domain, 'example.com')
1287
def test_get_domain_domain_literal_with_cfws(self):
1288
domain = self._test_get_x(parser.get_domain,
1289
'(foo)[127.0.0.1]\t(bar)',
1290
'(foo)[127.0.0.1]\t(bar)',
1294
self.assertEqual(domain.domain, '[127.0.0.1]')
1296
def test_get_domain_domain_with_cfws_ends_at_special(self):
1297
domain = self._test_get_x(parser.get_domain,
1298
'(foo)example.com\t(bar), next',
1299
'(foo)example.com\t(bar)',
1303
self.assertEqual(domain.domain, 'example.com')
1305
def test_get_domain_domain_literal_with_cfws_ends_at_special(self):
1306
domain = self._test_get_x(parser.get_domain,
1307
'(foo)[127.0.0.1]\t(bar), next',
1308
'(foo)[127.0.0.1]\t(bar)',
1312
self.assertEqual(domain.domain, '[127.0.0.1]')
1314
def test_get_domain_obsolete(self):
1315
domain = self._test_get_x(parser.get_domain,
1316
'(foo) example . (bird)com(bar)\t',
1317
'(foo) example . (bird)com(bar)\t',
1319
[errors.ObsoleteHeaderDefect],
1321
self.assertEqual(domain.domain, 'example.com')
1323
def test_get_domain_no_non_cfws_raises(self):
1324
with self.assertRaises(errors.HeaderParseError):
1325
parser.get_domain(" (foo)\t")
1327
def test_get_domain_no_atom_raises(self):
1328
with self.assertRaises(errors.HeaderParseError):
1329
parser.get_domain(" (foo)\t, broken")
1334
def test_get_addr_spec_normal(self):
1335
addr_spec = self._test_get_x(parser.get_addr_spec,
1336
'dinsdale@example.com',
1337
'dinsdale@example.com',
1338
'dinsdale@example.com',
1341
self.assertEqual(addr_spec.token_type, 'addr-spec')
1342
self.assertEqual(addr_spec.local_part, 'dinsdale')
1343
self.assertEqual(addr_spec.domain, 'example.com')
1344
self.assertEqual(addr_spec.addr_spec, 'dinsdale@example.com')
1346
def test_get_addr_spec_with_doamin_literal(self):
1347
addr_spec = self._test_get_x(parser.get_addr_spec,
1348
'dinsdale@[127.0.0.1]',
1349
'dinsdale@[127.0.0.1]',
1350
'dinsdale@[127.0.0.1]',
1353
self.assertEqual(addr_spec.local_part, 'dinsdale')
1354
self.assertEqual(addr_spec.domain, '[127.0.0.1]')
1355
self.assertEqual(addr_spec.addr_spec, 'dinsdale@[127.0.0.1]')
1357
def test_get_addr_spec_with_cfws(self):
1358
addr_spec = self._test_get_x(parser.get_addr_spec,
1359
'(foo) dinsdale(bar)@ (bird) example.com (bog)',
1360
'(foo) dinsdale(bar)@ (bird) example.com (bog)',
1361
' dinsdale@example.com ',
1364
self.assertEqual(addr_spec.local_part, 'dinsdale')
1365
self.assertEqual(addr_spec.domain, 'example.com')
1366
self.assertEqual(addr_spec.addr_spec, 'dinsdale@example.com')
1368
def test_get_addr_spec_with_qouoted_string_and_cfws(self):
1369
addr_spec = self._test_get_x(parser.get_addr_spec,
1370
'(foo) "roy a bug"(bar)@ (bird) example.com (bog)',
1371
'(foo) "roy a bug"(bar)@ (bird) example.com (bog)',
1372
' "roy a bug"@example.com ',
1375
self.assertEqual(addr_spec.local_part, 'roy a bug')
1376
self.assertEqual(addr_spec.domain, 'example.com')
1377
self.assertEqual(addr_spec.addr_spec, '"roy a bug"@example.com')
1379
def test_get_addr_spec_ends_at_special(self):
1380
addr_spec = self._test_get_x(parser.get_addr_spec,
1381
'(foo) "roy a bug"(bar)@ (bird) example.com (bog) , next',
1382
'(foo) "roy a bug"(bar)@ (bird) example.com (bog) ',
1383
' "roy a bug"@example.com ',
1386
self.assertEqual(addr_spec.local_part, 'roy a bug')
1387
self.assertEqual(addr_spec.domain, 'example.com')
1388
self.assertEqual(addr_spec.addr_spec, '"roy a bug"@example.com')
1390
def test_get_addr_spec_quoted_strings_in_atom_list(self):
1391
addr_spec = self._test_get_x(parser.get_addr_spec,
1392
'""example" example"@example.com',
1393
'""example" example"@example.com',
1394
'example example@example.com',
1395
[errors.InvalidHeaderDefect]*3,
1397
self.assertEqual(addr_spec.local_part, 'example example')
1398
self.assertEqual(addr_spec.domain, 'example.com')
1399
self.assertEqual(addr_spec.addr_spec, '"example example"@example.com')
1401
def test_get_addr_spec_dot_atom(self):
1402
addr_spec = self._test_get_x(parser.get_addr_spec,
1403
'star.a.star@example.com',
1404
'star.a.star@example.com',
1405
'star.a.star@example.com',
1408
self.assertEqual(addr_spec.local_part, 'star.a.star')
1409
self.assertEqual(addr_spec.domain, 'example.com')
1410
self.assertEqual(addr_spec.addr_spec, 'star.a.star@example.com')
1414
def test_get_obs_route_simple(self):
1415
obs_route = self._test_get_x(parser.get_obs_route,
1416
'@example.com, @two.example.com:',
1417
'@example.com, @two.example.com:',
1418
'@example.com, @two.example.com:',
1421
self.assertEqual(obs_route.token_type, 'obs-route')
1422
self.assertEqual(obs_route.domains, ['example.com', 'two.example.com'])
1424
def test_get_obs_route_complex(self):
1425
obs_route = self._test_get_x(parser.get_obs_route,
1426
'(foo),, (blue)@example.com (bar),@two.(foo) example.com (bird):',
1427
'(foo),, (blue)@example.com (bar),@two.(foo) example.com (bird):',
1428
' ,, @example.com ,@two. example.com :',
1429
[errors.ObsoleteHeaderDefect], # This is the obs-domain
1431
self.assertEqual(obs_route.token_type, 'obs-route')
1432
self.assertEqual(obs_route.domains, ['example.com', 'two.example.com'])
1434
def test_get_obs_route_no_route_before_end_raises(self):
1435
with self.assertRaises(errors.HeaderParseError):
1436
parser.get_obs_route('(foo) @example.com,')
1438
def test_get_obs_route_no_route_before_special_raises(self):
1439
with self.assertRaises(errors.HeaderParseError):
1440
parser.get_obs_route('(foo) [abc],')
1442
def test_get_obs_route_no_route_before_special_raises2(self):
1443
with self.assertRaises(errors.HeaderParseError):
1444
parser.get_obs_route('(foo) @example.com [abc],')
1448
def test_get_angle_addr_simple(self):
1449
angle_addr = self._test_get_x(parser.get_angle_addr,
1450
'<dinsdale@example.com>',
1451
'<dinsdale@example.com>',
1452
'<dinsdale@example.com>',
1455
self.assertEqual(angle_addr.token_type, 'angle-addr')
1456
self.assertEqual(angle_addr.local_part, 'dinsdale')
1457
self.assertEqual(angle_addr.domain, 'example.com')
1458
self.assertIsNone(angle_addr.route)
1459
self.assertEqual(angle_addr.addr_spec, 'dinsdale@example.com')
1461
def test_get_angle_addr_empty(self):
1462
angle_addr = self._test_get_x(parser.get_angle_addr,
1466
[errors.InvalidHeaderDefect],
1468
self.assertEqual(angle_addr.token_type, 'angle-addr')
1469
self.assertIsNone(angle_addr.local_part)
1470
self.assertIsNone(angle_addr.domain)
1471
self.assertIsNone(angle_addr.route)
1472
self.assertEqual(angle_addr.addr_spec, '<>')
1474
def test_get_angle_addr_with_cfws(self):
1475
angle_addr = self._test_get_x(parser.get_angle_addr,
1476
' (foo) <dinsdale@example.com>(bar)',
1477
' (foo) <dinsdale@example.com>(bar)',
1478
' <dinsdale@example.com> ',
1481
self.assertEqual(angle_addr.token_type, 'angle-addr')
1482
self.assertEqual(angle_addr.local_part, 'dinsdale')
1483
self.assertEqual(angle_addr.domain, 'example.com')
1484
self.assertIsNone(angle_addr.route)
1485
self.assertEqual(angle_addr.addr_spec, 'dinsdale@example.com')
1487
def test_get_angle_addr_qs_and_domain_literal(self):
1488
angle_addr = self._test_get_x(parser.get_angle_addr,
1489
'<"Fred Perfect"@[127.0.0.1]>',
1490
'<"Fred Perfect"@[127.0.0.1]>',
1491
'<"Fred Perfect"@[127.0.0.1]>',
1494
self.assertEqual(angle_addr.local_part, 'Fred Perfect')
1495
self.assertEqual(angle_addr.domain, '[127.0.0.1]')
1496
self.assertIsNone(angle_addr.route)
1497
self.assertEqual(angle_addr.addr_spec, '"Fred Perfect"@[127.0.0.1]')
1499
def test_get_angle_addr_internal_cfws(self):
1500
angle_addr = self._test_get_x(parser.get_angle_addr,
1501
'<(foo) dinsdale@example.com(bar)>',
1502
'<(foo) dinsdale@example.com(bar)>',
1503
'< dinsdale@example.com >',
1506
self.assertEqual(angle_addr.local_part, 'dinsdale')
1507
self.assertEqual(angle_addr.domain, 'example.com')
1508
self.assertIsNone(angle_addr.route)
1509
self.assertEqual(angle_addr.addr_spec, 'dinsdale@example.com')
1511
def test_get_angle_addr_obs_route(self):
1512
angle_addr = self._test_get_x(parser.get_angle_addr,
1513
'(foo)<@example.com, (bird) @two.example.com: dinsdale@example.com> (bar) ',
1514
'(foo)<@example.com, (bird) @two.example.com: dinsdale@example.com> (bar) ',
1515
' <@example.com, @two.example.com: dinsdale@example.com> ',
1516
[errors.ObsoleteHeaderDefect],
1518
self.assertEqual(angle_addr.local_part, 'dinsdale')
1519
self.assertEqual(angle_addr.domain, 'example.com')
1520
self.assertEqual(angle_addr.route, ['example.com', 'two.example.com'])
1521
self.assertEqual(angle_addr.addr_spec, 'dinsdale@example.com')
1523
def test_get_angle_addr_missing_closing_angle(self):
1524
angle_addr = self._test_get_x(parser.get_angle_addr,
1525
'<dinsdale@example.com',
1526
'<dinsdale@example.com>',
1527
'<dinsdale@example.com>',
1528
[errors.InvalidHeaderDefect],
1530
self.assertEqual(angle_addr.local_part, 'dinsdale')
1531
self.assertEqual(angle_addr.domain, 'example.com')
1532
self.assertIsNone(angle_addr.route)
1533
self.assertEqual(angle_addr.addr_spec, 'dinsdale@example.com')
1535
def test_get_angle_addr_missing_closing_angle_with_cfws(self):
1536
angle_addr = self._test_get_x(parser.get_angle_addr,
1537
'<dinsdale@example.com (foo)',
1538
'<dinsdale@example.com (foo)>',
1539
'<dinsdale@example.com >',
1540
[errors.InvalidHeaderDefect],
1542
self.assertEqual(angle_addr.local_part, 'dinsdale')
1543
self.assertEqual(angle_addr.domain, 'example.com')
1544
self.assertIsNone(angle_addr.route)
1545
self.assertEqual(angle_addr.addr_spec, 'dinsdale@example.com')
1547
def test_get_angle_addr_ends_at_special(self):
1548
angle_addr = self._test_get_x(parser.get_angle_addr,
1549
'<dinsdale@example.com> (foo), next',
1550
'<dinsdale@example.com> (foo)',
1551
'<dinsdale@example.com> ',
1554
self.assertEqual(angle_addr.local_part, 'dinsdale')
1555
self.assertEqual(angle_addr.domain, 'example.com')
1556
self.assertIsNone(angle_addr.route)
1557
self.assertEqual(angle_addr.addr_spec, 'dinsdale@example.com')
1559
def test_get_angle_addr_no_angle_raise(self):
1560
with self.assertRaises(errors.HeaderParseError):
1561
parser.get_angle_addr('(foo) ')
1563
def test_get_angle_addr_no_angle_before_special_raises(self):
1564
with self.assertRaises(errors.HeaderParseError):
1565
parser.get_angle_addr('(foo) , next')
1567
def test_get_angle_addr_no_angle_raises(self):
1568
with self.assertRaises(errors.HeaderParseError):
1569
parser.get_angle_addr('bar')
1571
def test_get_angle_addr_special_after_angle_raises(self):
1572
with self.assertRaises(errors.HeaderParseError):
1573
parser.get_angle_addr('(foo) <, bar')
1575
# get_display_name This is phrase but with a different value.
1577
def test_get_display_name_simple(self):
1578
display_name = self._test_get_x(parser.get_display_name,
1584
self.assertEqual(display_name.token_type, 'display-name')
1585
self.assertEqual(display_name.display_name, 'Fred A Johnson')
1587
def test_get_display_name_complex1(self):
1588
display_name = self._test_get_x(parser.get_display_name,
1589
'"Fred A. Johnson" is his name, oh.',
1590
'"Fred A. Johnson" is his name',
1591
'"Fred A. Johnson is his name"',
1594
self.assertEqual(display_name.token_type, 'display-name')
1595
self.assertEqual(display_name.display_name, 'Fred A. Johnson is his name')
1597
def test_get_display_name_complex2(self):
1598
display_name = self._test_get_x(parser.get_display_name,
1599
' (A) bird (in (my|your)) "hand " is messy\t<>\t',
1600
' (A) bird (in (my|your)) "hand " is messy\t',
1601
' "bird hand is messy" ',
1604
self.assertEqual(display_name[0][0].comments, ['A'])
1605
self.assertEqual(display_name[0][2].comments, ['in (my|your)'])
1606
self.assertEqual(display_name.display_name, 'bird hand is messy')
1608
def test_get_display_name_obsolete(self):
1609
display_name = self._test_get_x(parser.get_display_name,
1610
'Fred A.(weird).O Johnson',
1611
'Fred A.(weird).O Johnson',
1612
'"Fred A. .O Johnson"',
1613
[errors.ObsoleteHeaderDefect]*3,
1615
self.assertEqual(len(display_name), 7)
1616
self.assertEqual(display_name[3].comments, ['weird'])
1617
self.assertEqual(display_name.display_name, 'Fred A. .O Johnson')
1619
def test_get_display_name_pharse_must_start_with_word(self):
1620
display_name = self._test_get_x(parser.get_display_name,
1621
'(even weirder).name',
1622
'(even weirder).name',
1624
[errors.InvalidHeaderDefect] + [errors.ObsoleteHeaderDefect]*2,
1626
self.assertEqual(len(display_name), 3)
1627
self.assertEqual(display_name[0].comments, ['even weirder'])
1628
self.assertEqual(display_name.display_name, '.name')
1630
def test_get_display_name_ending_with_obsolete(self):
1631
display_name = self._test_get_x(parser.get_display_name,
1632
'simple phrase.(with trailing comment):boo',
1633
'simple phrase.(with trailing comment)',
1634
'"simple phrase." ',
1635
[errors.ObsoleteHeaderDefect]*2,
1637
self.assertEqual(len(display_name), 4)
1638
self.assertEqual(display_name[3].comments, ['with trailing comment'])
1639
self.assertEqual(display_name.display_name, 'simple phrase.')
1643
def test_get_name_addr_angle_addr_only(self):
1644
name_addr = self._test_get_x(parser.get_name_addr,
1645
'<dinsdale@example.com>',
1646
'<dinsdale@example.com>',
1647
'<dinsdale@example.com>',
1650
self.assertEqual(name_addr.token_type, 'name-addr')
1651
self.assertIsNone(name_addr.display_name)
1652
self.assertEqual(name_addr.local_part, 'dinsdale')
1653
self.assertEqual(name_addr.domain, 'example.com')
1654
self.assertIsNone(name_addr.route)
1655
self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com')
1657
def test_get_name_addr_atom_name(self):
1658
name_addr = self._test_get_x(parser.get_name_addr,
1659
'Dinsdale <dinsdale@example.com>',
1660
'Dinsdale <dinsdale@example.com>',
1661
'Dinsdale <dinsdale@example.com>',
1664
self.assertEqual(name_addr.token_type, 'name-addr')
1665
self.assertEqual(name_addr.display_name, 'Dinsdale')
1666
self.assertEqual(name_addr.local_part, 'dinsdale')
1667
self.assertEqual(name_addr.domain, 'example.com')
1668
self.assertIsNone(name_addr.route)
1669
self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com')
1671
def test_get_name_addr_atom_name_with_cfws(self):
1672
name_addr = self._test_get_x(parser.get_name_addr,
1673
'(foo) Dinsdale (bar) <dinsdale@example.com> (bird)',
1674
'(foo) Dinsdale (bar) <dinsdale@example.com> (bird)',
1675
' Dinsdale <dinsdale@example.com> ',
1678
self.assertEqual(name_addr.display_name, 'Dinsdale')
1679
self.assertEqual(name_addr.local_part, 'dinsdale')
1680
self.assertEqual(name_addr.domain, 'example.com')
1681
self.assertIsNone(name_addr.route)
1682
self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com')
1684
def test_get_name_addr_name_with_cfws_and_dots(self):
1685
name_addr = self._test_get_x(parser.get_name_addr,
1686
'(foo) Roy.A.Bear (bar) <dinsdale@example.com> (bird)',
1687
'(foo) Roy.A.Bear (bar) <dinsdale@example.com> (bird)',
1688
' "Roy.A.Bear" <dinsdale@example.com> ',
1689
[errors.ObsoleteHeaderDefect]*2,
1691
self.assertEqual(name_addr.display_name, 'Roy.A.Bear')
1692
self.assertEqual(name_addr.local_part, 'dinsdale')
1693
self.assertEqual(name_addr.domain, 'example.com')
1694
self.assertIsNone(name_addr.route)
1695
self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com')
1697
def test_get_name_addr_qs_name(self):
1698
name_addr = self._test_get_x(parser.get_name_addr,
1699
'"Roy.A.Bear" <dinsdale@example.com>',
1700
'"Roy.A.Bear" <dinsdale@example.com>',
1701
'"Roy.A.Bear" <dinsdale@example.com>',
1704
self.assertEqual(name_addr.display_name, 'Roy.A.Bear')
1705
self.assertEqual(name_addr.local_part, 'dinsdale')
1706
self.assertEqual(name_addr.domain, 'example.com')
1707
self.assertIsNone(name_addr.route)
1708
self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com')
1710
def test_get_name_addr_with_route(self):
1711
name_addr = self._test_get_x(parser.get_name_addr,
1712
'"Roy.A.Bear" <@two.example.com: dinsdale@example.com>',
1713
'"Roy.A.Bear" <@two.example.com: dinsdale@example.com>',
1714
'"Roy.A.Bear" <@two.example.com: dinsdale@example.com>',
1715
[errors.ObsoleteHeaderDefect],
1717
self.assertEqual(name_addr.display_name, 'Roy.A.Bear')
1718
self.assertEqual(name_addr.local_part, 'dinsdale')
1719
self.assertEqual(name_addr.domain, 'example.com')
1720
self.assertEqual(name_addr.route, ['two.example.com'])
1721
self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com')
1723
def test_get_name_addr_ends_at_special(self):
1724
name_addr = self._test_get_x(parser.get_name_addr,
1725
'"Roy.A.Bear" <dinsdale@example.com>, next',
1726
'"Roy.A.Bear" <dinsdale@example.com>',
1727
'"Roy.A.Bear" <dinsdale@example.com>',
1730
self.assertEqual(name_addr.display_name, 'Roy.A.Bear')
1731
self.assertEqual(name_addr.local_part, 'dinsdale')
1732
self.assertEqual(name_addr.domain, 'example.com')
1733
self.assertIsNone(name_addr.route)
1734
self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com')
1736
def test_get_name_addr_no_content_raises(self):
1737
with self.assertRaises(errors.HeaderParseError):
1738
parser.get_name_addr(' (foo) ')
1740
def test_get_name_addr_no_content_before_special_raises(self):
1741
with self.assertRaises(errors.HeaderParseError):
1742
parser.get_name_addr(' (foo) ,')
1744
def test_get_name_addr_no_angle_after_display_name_raises(self):
1745
with self.assertRaises(errors.HeaderParseError):
1746
parser.get_name_addr('foo bar')
1750
def test_get_mailbox_addr_spec_only(self):
1751
mailbox = self._test_get_x(parser.get_mailbox,
1752
'dinsdale@example.com',
1753
'dinsdale@example.com',
1754
'dinsdale@example.com',
1757
self.assertEqual(mailbox.token_type, 'mailbox')
1758
self.assertIsNone(mailbox.display_name)
1759
self.assertEqual(mailbox.local_part, 'dinsdale')
1760
self.assertEqual(mailbox.domain, 'example.com')
1761
self.assertIsNone(mailbox.route)
1762
self.assertEqual(mailbox.addr_spec, 'dinsdale@example.com')
1764
def test_get_mailbox_angle_addr_only(self):
1765
mailbox = self._test_get_x(parser.get_mailbox,
1766
'<dinsdale@example.com>',
1767
'<dinsdale@example.com>',
1768
'<dinsdale@example.com>',
1771
self.assertEqual(mailbox.token_type, 'mailbox')
1772
self.assertIsNone(mailbox.display_name)
1773
self.assertEqual(mailbox.local_part, 'dinsdale')
1774
self.assertEqual(mailbox.domain, 'example.com')
1775
self.assertIsNone(mailbox.route)
1776
self.assertEqual(mailbox.addr_spec, 'dinsdale@example.com')
1778
def test_get_mailbox_name_addr(self):
1779
mailbox = self._test_get_x(parser.get_mailbox,
1780
'"Roy A. Bear" <dinsdale@example.com>',
1781
'"Roy A. Bear" <dinsdale@example.com>',
1782
'"Roy A. Bear" <dinsdale@example.com>',
1785
self.assertEqual(mailbox.token_type, 'mailbox')
1786
self.assertEqual(mailbox.display_name, 'Roy A. Bear')
1787
self.assertEqual(mailbox.local_part, 'dinsdale')
1788
self.assertEqual(mailbox.domain, 'example.com')
1789
self.assertIsNone(mailbox.route)
1790
self.assertEqual(mailbox.addr_spec, 'dinsdale@example.com')
1792
def test_get_mailbox_ends_at_special(self):
1793
mailbox = self._test_get_x(parser.get_mailbox,
1794
'"Roy A. Bear" <dinsdale@example.com>, rest',
1795
'"Roy A. Bear" <dinsdale@example.com>',
1796
'"Roy A. Bear" <dinsdale@example.com>',
1799
self.assertEqual(mailbox.token_type, 'mailbox')
1800
self.assertEqual(mailbox.display_name, 'Roy A. Bear')
1801
self.assertEqual(mailbox.local_part, 'dinsdale')
1802
self.assertEqual(mailbox.domain, 'example.com')
1803
self.assertIsNone(mailbox.route)
1804
self.assertEqual(mailbox.addr_spec, 'dinsdale@example.com')
1806
def test_get_mailbox_quoted_strings_in_atom_list(self):
1807
mailbox = self._test_get_x(parser.get_mailbox,
1808
'""example" example"@example.com',
1809
'""example" example"@example.com',
1810
'example example@example.com',
1811
[errors.InvalidHeaderDefect]*3,
1813
self.assertEqual(mailbox.local_part, 'example example')
1814
self.assertEqual(mailbox.domain, 'example.com')
1815
self.assertEqual(mailbox.addr_spec, '"example example"@example.com')
1819
def test_get_mailbox_list_single_addr(self):
1820
mailbox_list = self._test_get_x(parser.get_mailbox_list,
1821
'dinsdale@example.com',
1822
'dinsdale@example.com',
1823
'dinsdale@example.com',
1826
self.assertEqual(mailbox_list.token_type, 'mailbox-list')
1827
self.assertEqual(len(mailbox_list.mailboxes), 1)
1828
mailbox = mailbox_list.mailboxes[0]
1829
self.assertIsNone(mailbox.display_name)
1830
self.assertEqual(mailbox.local_part, 'dinsdale')
1831
self.assertEqual(mailbox.domain, 'example.com')
1832
self.assertIsNone(mailbox.route)
1833
self.assertEqual(mailbox.addr_spec, 'dinsdale@example.com')
1834
self.assertEqual(mailbox_list.mailboxes,
1835
mailbox_list.all_mailboxes)
1837
def test_get_mailbox_list_two_simple_addr(self):
1838
mailbox_list = self._test_get_x(parser.get_mailbox_list,
1839
'dinsdale@example.com, dinsdale@test.example.com',
1840
'dinsdale@example.com, dinsdale@test.example.com',
1841
'dinsdale@example.com, dinsdale@test.example.com',
1844
self.assertEqual(mailbox_list.token_type, 'mailbox-list')
1845
self.assertEqual(len(mailbox_list.mailboxes), 2)
1846
self.assertEqual(mailbox_list.mailboxes[0].addr_spec,
1847
'dinsdale@example.com')
1848
self.assertEqual(mailbox_list.mailboxes[1].addr_spec,
1849
'dinsdale@test.example.com')
1850
self.assertEqual(mailbox_list.mailboxes,
1851
mailbox_list.all_mailboxes)
1853
def test_get_mailbox_list_two_name_addr(self):
1854
mailbox_list = self._test_get_x(parser.get_mailbox_list,
1855
('"Roy A. Bear" <dinsdale@example.com>,'
1856
' "Fred Flintstone" <dinsdale@test.example.com>'),
1857
('"Roy A. Bear" <dinsdale@example.com>,'
1858
' "Fred Flintstone" <dinsdale@test.example.com>'),
1859
('"Roy A. Bear" <dinsdale@example.com>,'
1860
' "Fred Flintstone" <dinsdale@test.example.com>'),
1863
self.assertEqual(len(mailbox_list.mailboxes), 2)
1864
self.assertEqual(mailbox_list.mailboxes[0].addr_spec,
1865
'dinsdale@example.com')
1866
self.assertEqual(mailbox_list.mailboxes[0].display_name,
1868
self.assertEqual(mailbox_list.mailboxes[1].addr_spec,
1869
'dinsdale@test.example.com')
1870
self.assertEqual(mailbox_list.mailboxes[1].display_name,
1872
self.assertEqual(mailbox_list.mailboxes,
1873
mailbox_list.all_mailboxes)
1875
def test_get_mailbox_list_two_complex(self):
1876
mailbox_list = self._test_get_x(parser.get_mailbox_list,
1877
('(foo) "Roy A. Bear" <dinsdale@example.com>(bar),'
1878
' "Fred Flintstone" <dinsdale@test.(bird)example.com>'),
1879
('(foo) "Roy A. Bear" <dinsdale@example.com>(bar),'
1880
' "Fred Flintstone" <dinsdale@test.(bird)example.com>'),
1881
(' "Roy A. Bear" <dinsdale@example.com> ,'
1882
' "Fred Flintstone" <dinsdale@test. example.com>'),
1883
[errors.ObsoleteHeaderDefect],
1885
self.assertEqual(len(mailbox_list.mailboxes), 2)
1886
self.assertEqual(mailbox_list.mailboxes[0].addr_spec,
1887
'dinsdale@example.com')
1888
self.assertEqual(mailbox_list.mailboxes[0].display_name,
1890
self.assertEqual(mailbox_list.mailboxes[1].addr_spec,
1891
'dinsdale@test.example.com')
1892
self.assertEqual(mailbox_list.mailboxes[1].display_name,
1894
self.assertEqual(mailbox_list.mailboxes,
1895
mailbox_list.all_mailboxes)
1897
def test_get_mailbox_list_unparseable_mailbox_null(self):
1898
mailbox_list = self._test_get_x(parser.get_mailbox_list,
1899
('"Roy A. Bear"[] dinsdale@example.com,'
1900
' "Fred Flintstone" <dinsdale@test.(bird)example.com>'),
1901
('"Roy A. Bear"[] dinsdale@example.com,'
1902
' "Fred Flintstone" <dinsdale@test.(bird)example.com>'),
1903
('"Roy A. Bear"[] dinsdale@example.com,'
1904
' "Fred Flintstone" <dinsdale@test. example.com>'),
1905
[errors.InvalidHeaderDefect, # the 'extra' text after the local part
1906
errors.InvalidHeaderDefect, # the local part with no angle-addr
1907
errors.ObsoleteHeaderDefect, # period in extra text (example.com)
1908
errors.ObsoleteHeaderDefect], # (bird) in valid address.
1910
self.assertEqual(len(mailbox_list.mailboxes), 1)
1911
self.assertEqual(len(mailbox_list.all_mailboxes), 2)
1912
self.assertEqual(mailbox_list.all_mailboxes[0].token_type,
1914
self.assertIsNone(mailbox_list.all_mailboxes[0].display_name)
1915
self.assertEqual(mailbox_list.all_mailboxes[0].local_part,
1917
self.assertIsNone(mailbox_list.all_mailboxes[0].domain)
1918
self.assertEqual(mailbox_list.all_mailboxes[0].addr_spec,
1920
self.assertIs(mailbox_list.all_mailboxes[1],
1921
mailbox_list.mailboxes[0])
1922
self.assertEqual(mailbox_list.mailboxes[0].addr_spec,
1923
'dinsdale@test.example.com')
1924
self.assertEqual(mailbox_list.mailboxes[0].display_name,
1927
def test_get_mailbox_list_junk_after_valid_address(self):
1928
mailbox_list = self._test_get_x(parser.get_mailbox_list,
1929
('"Roy A. Bear" <dinsdale@example.com>@@,'
1930
' "Fred Flintstone" <dinsdale@test.example.com>'),
1931
('"Roy A. Bear" <dinsdale@example.com>@@,'
1932
' "Fred Flintstone" <dinsdale@test.example.com>'),
1933
('"Roy A. Bear" <dinsdale@example.com>@@,'
1934
' "Fred Flintstone" <dinsdale@test.example.com>'),
1935
[errors.InvalidHeaderDefect],
1937
self.assertEqual(len(mailbox_list.mailboxes), 1)
1938
self.assertEqual(len(mailbox_list.all_mailboxes), 2)
1939
self.assertEqual(mailbox_list.all_mailboxes[0].addr_spec,
1940
'dinsdale@example.com')
1941
self.assertEqual(mailbox_list.all_mailboxes[0].display_name,
1943
self.assertEqual(mailbox_list.all_mailboxes[0].token_type,
1945
self.assertIs(mailbox_list.all_mailboxes[1],
1946
mailbox_list.mailboxes[0])
1947
self.assertEqual(mailbox_list.mailboxes[0].addr_spec,
1948
'dinsdale@test.example.com')
1949
self.assertEqual(mailbox_list.mailboxes[0].display_name,
1952
def test_get_mailbox_list_empty_list_element(self):
1953
mailbox_list = self._test_get_x(parser.get_mailbox_list,
1954
('"Roy A. Bear" <dinsdale@example.com>, (bird),,'
1955
' "Fred Flintstone" <dinsdale@test.example.com>'),
1956
('"Roy A. Bear" <dinsdale@example.com>, (bird),,'
1957
' "Fred Flintstone" <dinsdale@test.example.com>'),
1958
('"Roy A. Bear" <dinsdale@example.com>, ,,'
1959
' "Fred Flintstone" <dinsdale@test.example.com>'),
1960
[errors.ObsoleteHeaderDefect]*2,
1962
self.assertEqual(len(mailbox_list.mailboxes), 2)
1963
self.assertEqual(mailbox_list.all_mailboxes,
1964
mailbox_list.mailboxes)
1965
self.assertEqual(mailbox_list.all_mailboxes[0].addr_spec,
1966
'dinsdale@example.com')
1967
self.assertEqual(mailbox_list.all_mailboxes[0].display_name,
1969
self.assertEqual(mailbox_list.mailboxes[1].addr_spec,
1970
'dinsdale@test.example.com')
1971
self.assertEqual(mailbox_list.mailboxes[1].display_name,
1974
def test_get_mailbox_list_only_empty_elements(self):
1975
mailbox_list = self._test_get_x(parser.get_mailbox_list,
1979
[errors.ObsoleteHeaderDefect]*3,
1981
self.assertEqual(len(mailbox_list.mailboxes), 0)
1982
self.assertEqual(mailbox_list.all_mailboxes,
1983
mailbox_list.mailboxes)
1987
def test_get_group_list_cfws_only(self):
1988
group_list = self._test_get_x(parser.get_group_list,
1994
self.assertEqual(group_list.token_type, 'group-list')
1995
self.assertEqual(len(group_list.mailboxes), 0)
1996
self.assertEqual(group_list.mailboxes,
1997
group_list.all_mailboxes)
1999
def test_get_group_list_mailbox_list(self):
2000
group_list = self._test_get_x(parser.get_group_list,
2001
'dinsdale@example.org, "Fred A. Bear" <dinsdale@example.org>',
2002
'dinsdale@example.org, "Fred A. Bear" <dinsdale@example.org>',
2003
'dinsdale@example.org, "Fred A. Bear" <dinsdale@example.org>',
2006
self.assertEqual(group_list.token_type, 'group-list')
2007
self.assertEqual(len(group_list.mailboxes), 2)
2008
self.assertEqual(group_list.mailboxes,
2009
group_list.all_mailboxes)
2010
self.assertEqual(group_list.mailboxes[1].display_name,
2013
def test_get_group_list_obs_group_list(self):
2014
group_list = self._test_get_x(parser.get_group_list,
2018
[errors.ObsoleteHeaderDefect],
2020
self.assertEqual(group_list.token_type, 'group-list')
2021
self.assertEqual(len(group_list.mailboxes), 0)
2022
self.assertEqual(group_list.mailboxes,
2023
group_list.all_mailboxes)
2025
def test_get_group_list_comment_only_invalid(self):
2026
group_list = self._test_get_x(parser.get_group_list,
2030
[errors.InvalidHeaderDefect],
2032
self.assertEqual(group_list.token_type, 'group-list')
2033
self.assertEqual(len(group_list.mailboxes), 0)
2034
self.assertEqual(group_list.mailboxes,
2035
group_list.all_mailboxes)
2039
def test_get_group_empty(self):
2040
group = self._test_get_x(parser.get_group,
2046
self.assertEqual(group.token_type, 'group')
2047
self.assertEqual(group.display_name, 'Monty Python')
2048
self.assertEqual(len(group.mailboxes), 0)
2049
self.assertEqual(group.mailboxes,
2050
group.all_mailboxes)
2052
def test_get_group_null_addr_spec(self):
2053
group = self._test_get_x(parser.get_group,
2057
[errors.InvalidHeaderDefect],
2059
self.assertEqual(group.display_name, 'foo')
2060
self.assertEqual(len(group.mailboxes), 0)
2061
self.assertEqual(len(group.all_mailboxes), 1)
2062
self.assertEqual(group.all_mailboxes[0].value, '<>')
2064
def test_get_group_cfws_only(self):
2065
group = self._test_get_x(parser.get_group,
2066
'Monty Python: (hidden);',
2067
'Monty Python: (hidden);',
2071
self.assertEqual(group.token_type, 'group')
2072
self.assertEqual(group.display_name, 'Monty Python')
2073
self.assertEqual(len(group.mailboxes), 0)
2074
self.assertEqual(group.mailboxes,
2075
group.all_mailboxes)
2077
def test_get_group_single_mailbox(self):
2078
group = self._test_get_x(parser.get_group,
2079
'Monty Python: "Fred A. Bear" <dinsdale@example.com>;',
2080
'Monty Python: "Fred A. Bear" <dinsdale@example.com>;',
2081
'Monty Python: "Fred A. Bear" <dinsdale@example.com>;',
2084
self.assertEqual(group.token_type, 'group')
2085
self.assertEqual(group.display_name, 'Monty Python')
2086
self.assertEqual(len(group.mailboxes), 1)
2087
self.assertEqual(group.mailboxes,
2088
group.all_mailboxes)
2089
self.assertEqual(group.mailboxes[0].addr_spec,
2090
'dinsdale@example.com')
2092
def test_get_group_mixed_list(self):
2093
group = self._test_get_x(parser.get_group,
2094
('Monty Python: "Fred A. Bear" <dinsdale@example.com>,'
2095
'(foo) Roger <ping@exampele.com>, x@test.example.com;'),
2096
('Monty Python: "Fred A. Bear" <dinsdale@example.com>,'
2097
'(foo) Roger <ping@exampele.com>, x@test.example.com;'),
2098
('Monty Python: "Fred A. Bear" <dinsdale@example.com>,'
2099
' Roger <ping@exampele.com>, x@test.example.com;'),
2102
self.assertEqual(group.token_type, 'group')
2103
self.assertEqual(group.display_name, 'Monty Python')
2104
self.assertEqual(len(group.mailboxes), 3)
2105
self.assertEqual(group.mailboxes,
2106
group.all_mailboxes)
2107
self.assertEqual(group.mailboxes[0].display_name,
2109
self.assertEqual(group.mailboxes[1].display_name,
2111
self.assertEqual(group.mailboxes[2].local_part, 'x')
2113
def test_get_group_one_invalid(self):
2114
group = self._test_get_x(parser.get_group,
2115
('Monty Python: "Fred A. Bear" <dinsdale@example.com>,'
2116
'(foo) Roger ping@exampele.com, x@test.example.com;'),
2117
('Monty Python: "Fred A. Bear" <dinsdale@example.com>,'
2118
'(foo) Roger ping@exampele.com, x@test.example.com;'),
2119
('Monty Python: "Fred A. Bear" <dinsdale@example.com>,'
2120
' Roger ping@exampele.com, x@test.example.com;'),
2121
[errors.InvalidHeaderDefect, # non-angle addr makes local part invalid
2122
errors.InvalidHeaderDefect], # and its not obs-local either: no dots.
2124
self.assertEqual(group.token_type, 'group')
2125
self.assertEqual(group.display_name, 'Monty Python')
2126
self.assertEqual(len(group.mailboxes), 2)
2127
self.assertEqual(len(group.all_mailboxes), 3)
2128
self.assertEqual(group.mailboxes[0].display_name,
2130
self.assertEqual(group.mailboxes[1].local_part, 'x')
2131
self.assertIsNone(group.all_mailboxes[1].display_name)
2135
def test_get_address_simple(self):
2136
address = self._test_get_x(parser.get_address,
2137
'dinsdale@example.com',
2138
'dinsdale@example.com',
2139
'dinsdale@example.com',
2142
self.assertEqual(address.token_type, 'address')
2143
self.assertEqual(len(address.mailboxes), 1)
2144
self.assertEqual(address.mailboxes,
2145
address.all_mailboxes)
2146
self.assertEqual(address.mailboxes[0].domain,
2148
self.assertEqual(address[0].token_type,
2151
def test_get_address_complex(self):
2152
address = self._test_get_x(parser.get_address,
2153
'(foo) "Fred A. Bear" <(bird)dinsdale@example.com>',
2154
'(foo) "Fred A. Bear" <(bird)dinsdale@example.com>',
2155
' "Fred A. Bear" < dinsdale@example.com>',
2158
self.assertEqual(address.token_type, 'address')
2159
self.assertEqual(len(address.mailboxes), 1)
2160
self.assertEqual(address.mailboxes,
2161
address.all_mailboxes)
2162
self.assertEqual(address.mailboxes[0].display_name,
2164
self.assertEqual(address[0].token_type,
2167
def test_get_address_rfc2047_display_name(self):
2168
address = self._test_get_x(parser.get_address,
2169
'=?utf-8?q?=C3=89ric?= <foo@example.com>',
2170
'Éric <foo@example.com>',
2171
'Éric <foo@example.com>',
2174
self.assertEqual(address.token_type, 'address')
2175
self.assertEqual(len(address.mailboxes), 1)
2176
self.assertEqual(address.mailboxes,
2177
address.all_mailboxes)
2178
self.assertEqual(address.mailboxes[0].display_name,
2180
self.assertEqual(address[0].token_type,
2183
def test_get_address_empty_group(self):
2184
address = self._test_get_x(parser.get_address,
2190
self.assertEqual(address.token_type, 'address')
2191
self.assertEqual(len(address.mailboxes), 0)
2192
self.assertEqual(address.mailboxes,
2193
address.all_mailboxes)
2194
self.assertEqual(address[0].token_type,
2196
self.assertEqual(address[0].display_name,
2199
def test_get_address_group(self):
2200
address = self._test_get_x(parser.get_address,
2201
'Monty Python: x@example.com, y@example.com;',
2202
'Monty Python: x@example.com, y@example.com;',
2203
'Monty Python: x@example.com, y@example.com;',
2206
self.assertEqual(address.token_type, 'address')
2207
self.assertEqual(len(address.mailboxes), 2)
2208
self.assertEqual(address.mailboxes,
2209
address.all_mailboxes)
2210
self.assertEqual(address[0].token_type,
2212
self.assertEqual(address[0].display_name,
2214
self.assertEqual(address.mailboxes[0].local_part, 'x')
2216
def test_get_address_quoted_local_part(self):
2217
address = self._test_get_x(parser.get_address,
2218
'"foo bar"@example.com',
2219
'"foo bar"@example.com',
2220
'"foo bar"@example.com',
2223
self.assertEqual(address.token_type, 'address')
2224
self.assertEqual(len(address.mailboxes), 1)
2225
self.assertEqual(address.mailboxes,
2226
address.all_mailboxes)
2227
self.assertEqual(address.mailboxes[0].domain,
2229
self.assertEqual(address.mailboxes[0].local_part,
2231
self.assertEqual(address[0].token_type, 'mailbox')
2233
def test_get_address_ends_at_special(self):
2234
address = self._test_get_x(parser.get_address,
2235
'dinsdale@example.com, next',
2236
'dinsdale@example.com',
2237
'dinsdale@example.com',
2240
self.assertEqual(address.token_type, 'address')
2241
self.assertEqual(len(address.mailboxes), 1)
2242
self.assertEqual(address.mailboxes,
2243
address.all_mailboxes)
2244
self.assertEqual(address.mailboxes[0].domain,
2246
self.assertEqual(address[0].token_type, 'mailbox')
2248
def test_get_address_invalid_mailbox_invalid(self):
2249
address = self._test_get_x(parser.get_address,
2250
'ping example.com, next',
2253
[errors.InvalidHeaderDefect, # addr-spec with no domain
2254
errors.InvalidHeaderDefect, # invalid local-part
2255
errors.InvalidHeaderDefect, # missing .s in local-part
2258
self.assertEqual(address.token_type, 'address')
2259
self.assertEqual(len(address.mailboxes), 0)
2260
self.assertEqual(len(address.all_mailboxes), 1)
2261
self.assertIsNone(address.all_mailboxes[0].domain)
2262
self.assertEqual(address.all_mailboxes[0].local_part, 'ping example.com')
2263
self.assertEqual(address[0].token_type, 'invalid-mailbox')
2265
def test_get_address_quoted_strings_in_atom_list(self):
2266
address = self._test_get_x(parser.get_address,
2267
'""example" example"@example.com',
2268
'""example" example"@example.com',
2269
'example example@example.com',
2270
[errors.InvalidHeaderDefect]*3,
2272
self.assertEqual(address.all_mailboxes[0].local_part, 'example example')
2273
self.assertEqual(address.all_mailboxes[0].domain, 'example.com')
2274
self.assertEqual(address.all_mailboxes[0].addr_spec, '"example example"@example.com')
2279
def test_get_address_list_mailboxes_simple(self):
2280
address_list = self._test_get_x(parser.get_address_list,
2281
'dinsdale@example.com',
2282
'dinsdale@example.com',
2283
'dinsdale@example.com',
2286
self.assertEqual(address_list.token_type, 'address-list')
2287
self.assertEqual(len(address_list.mailboxes), 1)
2288
self.assertEqual(address_list.mailboxes,
2289
address_list.all_mailboxes)
2290
self.assertEqual([str(x) for x in address_list.mailboxes],
2291
[str(x) for x in address_list.addresses])
2292
self.assertEqual(address_list.mailboxes[0].domain, 'example.com')
2293
self.assertEqual(address_list[0].token_type, 'address')
2294
self.assertIsNone(address_list[0].display_name)
2296
def test_get_address_list_mailboxes_two_simple(self):
2297
address_list = self._test_get_x(parser.get_address_list,
2298
'foo@example.com, "Fred A. Bar" <bar@example.com>',
2299
'foo@example.com, "Fred A. Bar" <bar@example.com>',
2300
'foo@example.com, "Fred A. Bar" <bar@example.com>',
2303
self.assertEqual(address_list.token_type, 'address-list')
2304
self.assertEqual(len(address_list.mailboxes), 2)
2305
self.assertEqual(address_list.mailboxes,
2306
address_list.all_mailboxes)
2307
self.assertEqual([str(x) for x in address_list.mailboxes],
2308
[str(x) for x in address_list.addresses])
2309
self.assertEqual(address_list.mailboxes[0].local_part, 'foo')
2310
self.assertEqual(address_list.mailboxes[1].display_name, "Fred A. Bar")
2312
def test_get_address_list_mailboxes_complex(self):
2313
address_list = self._test_get_x(parser.get_address_list,
2314
('"Roy A. Bear" <dinsdale@example.com>, '
2315
'(ping) Foo <x@example.com>,'
2316
'Nobody Is. Special <y@(bird)example.(bad)com>'),
2317
('"Roy A. Bear" <dinsdale@example.com>, '
2318
'(ping) Foo <x@example.com>,'
2319
'Nobody Is. Special <y@(bird)example.(bad)com>'),
2320
('"Roy A. Bear" <dinsdale@example.com>, '
2321
'Foo <x@example.com>,'
2322
'"Nobody Is. Special" <y@example. com>'),
2323
[errors.ObsoleteHeaderDefect, # period in Is.
2324
errors.ObsoleteHeaderDefect], # cfws in domain
2326
self.assertEqual(address_list.token_type, 'address-list')
2327
self.assertEqual(len(address_list.mailboxes), 3)
2328
self.assertEqual(address_list.mailboxes,
2329
address_list.all_mailboxes)
2330
self.assertEqual([str(x) for x in address_list.mailboxes],
2331
[str(x) for x in address_list.addresses])
2332
self.assertEqual(address_list.mailboxes[0].domain, 'example.com')
2333
self.assertEqual(address_list.mailboxes[0].token_type, 'mailbox')
2334
self.assertEqual(address_list.addresses[0].token_type, 'address')
2335
self.assertEqual(address_list.mailboxes[1].local_part, 'x')
2336
self.assertEqual(address_list.mailboxes[2].display_name,
2337
'Nobody Is. Special')
2339
def test_get_address_list_mailboxes_invalid_addresses(self):
2340
address_list = self._test_get_x(parser.get_address_list,
2341
('"Roy A. Bear" <dinsdale@example.com>, '
2342
'(ping) Foo x@example.com[],'
2343
'Nobody Is. Special <(bird)example.(bad)com>'),
2344
('"Roy A. Bear" <dinsdale@example.com>, '
2345
'(ping) Foo x@example.com[],'
2346
'Nobody Is. Special <(bird)example.(bad)com>'),
2347
('"Roy A. Bear" <dinsdale@example.com>, '
2348
'Foo x@example.com[],'
2349
'"Nobody Is. Special" < example. com>'),
2350
[errors.InvalidHeaderDefect, # invalid address in list
2351
errors.InvalidHeaderDefect, # 'Foo x' local part invalid.
2352
errors.InvalidHeaderDefect, # Missing . in 'Foo x' local part
2353
errors.ObsoleteHeaderDefect, # period in 'Is.' disp-name phrase
2354
errors.InvalidHeaderDefect, # no domain part in addr-spec
2355
errors.ObsoleteHeaderDefect], # addr-spec has comment in it
2357
self.assertEqual(address_list.token_type, 'address-list')
2358
self.assertEqual(len(address_list.mailboxes), 1)
2359
self.assertEqual(len(address_list.all_mailboxes), 3)
2360
self.assertEqual([str(x) for x in address_list.all_mailboxes],
2361
[str(x) for x in address_list.addresses])
2362
self.assertEqual(address_list.mailboxes[0].domain, 'example.com')
2363
self.assertEqual(address_list.mailboxes[0].token_type, 'mailbox')
2364
self.assertEqual(address_list.addresses[0].token_type, 'address')
2365
self.assertEqual(address_list.addresses[1].token_type, 'address')
2366
self.assertEqual(len(address_list.addresses[0].mailboxes), 1)
2367
self.assertEqual(len(address_list.addresses[1].mailboxes), 0)
2368
self.assertEqual(len(address_list.addresses[1].mailboxes), 0)
2370
address_list.addresses[1].all_mailboxes[0].local_part, 'Foo x')
2372
address_list.addresses[2].all_mailboxes[0].display_name,
2373
"Nobody Is. Special")
2375
def test_get_address_list_group_empty(self):
2376
address_list = self._test_get_x(parser.get_address_list,
2382
self.assertEqual(address_list.token_type, 'address-list')
2383
self.assertEqual(len(address_list.mailboxes), 0)
2384
self.assertEqual(address_list.mailboxes,
2385
address_list.all_mailboxes)
2386
self.assertEqual(len(address_list.addresses), 1)
2387
self.assertEqual(address_list.addresses[0].token_type, 'address')
2388
self.assertEqual(address_list.addresses[0].display_name, 'Monty Python')
2389
self.assertEqual(len(address_list.addresses[0].mailboxes), 0)
2391
def test_get_address_list_group_simple(self):
2392
address_list = self._test_get_x(parser.get_address_list,
2393
'Monty Python: dinsdale@example.com;',
2394
'Monty Python: dinsdale@example.com;',
2395
'Monty Python: dinsdale@example.com;',
2398
self.assertEqual(address_list.token_type, 'address-list')
2399
self.assertEqual(len(address_list.mailboxes), 1)
2400
self.assertEqual(address_list.mailboxes,
2401
address_list.all_mailboxes)
2402
self.assertEqual(address_list.mailboxes[0].domain, 'example.com')
2403
self.assertEqual(address_list.addresses[0].display_name,
2405
self.assertEqual(address_list.addresses[0].mailboxes[0].domain,
2408
def test_get_address_list_group_and_mailboxes(self):
2409
address_list = self._test_get_x(parser.get_address_list,
2410
('Monty Python: dinsdale@example.com, "Fred" <flint@example.com>;, '
2411
'Abe <x@example.com>, Bee <y@example.com>'),
2412
('Monty Python: dinsdale@example.com, "Fred" <flint@example.com>;, '
2413
'Abe <x@example.com>, Bee <y@example.com>'),
2414
('Monty Python: dinsdale@example.com, "Fred" <flint@example.com>;, '
2415
'Abe <x@example.com>, Bee <y@example.com>'),
2418
self.assertEqual(address_list.token_type, 'address-list')
2419
self.assertEqual(len(address_list.mailboxes), 4)
2420
self.assertEqual(address_list.mailboxes,
2421
address_list.all_mailboxes)
2422
self.assertEqual(len(address_list.addresses), 3)
2423
self.assertEqual(address_list.mailboxes[0].local_part, 'dinsdale')
2424
self.assertEqual(address_list.addresses[0].display_name,
2426
self.assertEqual(address_list.addresses[0].mailboxes[0].domain,
2428
self.assertEqual(address_list.addresses[0].mailboxes[1].local_part,
2430
self.assertEqual(address_list.addresses[1].mailboxes[0].local_part,
2432
self.assertEqual(address_list.addresses[2].mailboxes[0].local_part,
2434
self.assertEqual(str(address_list.addresses[1]),
2435
str(address_list.mailboxes[2]))
2439
class Test_parse_mime_version(TestParserMixin, TestEmailBase):
2441
def mime_version_as_value(self,
2448
mime_version = self._test_parse_x(parser.parse_mime_version,
2449
value, tl_str, tl_value, defects)
2450
self.assertEqual(mime_version.major, major)
2451
self.assertEqual(mime_version.minor, minor)
2453
mime_version_params = {
2464
'1.0 (produced by MetaSend Vx.x)',
2465
'1.0 (produced by MetaSend Vx.x)',
2472
'(produced by MetaSend Vx.x) 1.0',
2473
'(produced by MetaSend Vx.x) 1.0',
2480
'1.(produced by MetaSend Vx.x)0',
2481
'1.(produced by MetaSend Vx.x)0',
2493
[errors.HeaderMissingRequiredValue]),
2499
class TestFolding(TestEmailBase):
2501
policy = policy.default
2503
def _test(self, tl, folded, policy=policy):
2504
self.assertEqual(tl.fold(policy=policy), folded, tl.ppstr())
2506
def test_simple_unstructured_no_folds(self):
2507
self._test(parser.get_unstructured("This is a test"),
2510
def test_simple_unstructured_folded(self):
2511
self._test(parser.get_unstructured("This is also a test, but this "
2512
"time there are enough words (and even some "
2513
"symbols) to make it wrap; at least in theory."),
2514
"This is also a test, but this time there are enough "
2515
"words (and even some\n"
2516
" symbols) to make it wrap; at least in theory.\n")
2518
def test_unstructured_with_unicode_no_folds(self):
2519
self._test(parser.get_unstructured("hübsch kleiner beißt"),
2520
"=?utf-8?q?h=C3=BCbsch_kleiner_bei=C3=9Ft?=\n")
2522
def test_one_ew_on_each_of_two_wrapped_lines(self):
2523
self._test(parser.get_unstructured("Mein kleiner Kaktus ist sehr "
2524
"hübsch. Es hat viele Stacheln "
2525
"und oft beißt mich."),
2526
"Mein kleiner Kaktus ist sehr =?utf-8?q?h=C3=BCbsch=2E?= "
2527
"Es hat viele Stacheln\n"
2528
" und oft =?utf-8?q?bei=C3=9Ft?= mich.\n")
2530
def test_ews_combined_before_wrap(self):
2531
self._test(parser.get_unstructured("Mein Kaktus ist hübsch. "
2533
"And that's all I'm sayin."),
2534
"Mein Kaktus ist =?utf-8?q?h=C3=BCbsch=2E__Es_bei=C3=9Ft?= "
2535
"mich. And that's\n"
2536
" all I'm sayin.\n")
2538
# XXX Need test of an encoded word so long that it needs to be wrapped
2540
def test_simple_address(self):
2541
self._test(parser.get_address_list("abc <xyz@example.com>")[0],
2542
"abc <xyz@example.com>\n")
2544
def test_address_list_folding_at_commas(self):
2545
self._test(parser.get_address_list('abc <xyz@example.com>, '
2546
'"Fred Blunt" <sharp@example.com>, '
2547
'"J.P.Cool" <hot@example.com>, '
2548
'"K<>y" <key@example.com>, '
2549
'Firesale <cheap@example.com>, '
2550
'<end@example.com>')[0],
2551
'abc <xyz@example.com>, "Fred Blunt" <sharp@example.com>,\n'
2552
' "J.P.Cool" <hot@example.com>, "K<>y" <key@example.com>,\n'
2553
' Firesale <cheap@example.com>, <end@example.com>\n')
2555
def test_address_list_with_unicode_names(self):
2556
self._test(parser.get_address_list(
2557
'Hübsch Kaktus <beautiful@example.com>, '
2558
'beißt beißt <biter@example.com>')[0],
2559
'=?utf-8?q?H=C3=BCbsch?= Kaktus <beautiful@example.com>,\n'
2560
' =?utf-8?q?bei=C3=9Ft_bei=C3=9Ft?= <biter@example.com>\n')
2562
def test_address_list_with_unicode_names_in_quotes(self):
2563
self._test(parser.get_address_list(
2564
'"Hübsch Kaktus" <beautiful@example.com>, '
2565
'"beißt" beißt <biter@example.com>')[0],
2566
'=?utf-8?q?H=C3=BCbsch?= Kaktus <beautiful@example.com>,\n'
2567
' =?utf-8?q?bei=C3=9Ft_bei=C3=9Ft?= <biter@example.com>\n')
2569
# XXX Need tests with comments on various sides of a unicode token,
2570
# and with unicode tokens in the comments. Spaces inside the quotes
2571
# currently don't do the right thing.
2573
def test_initial_whitespace_splitting(self):
2574
body = parser.get_unstructured(' ' + 'x'*77)
2575
header = parser.Header([
2576
parser.HeaderLabel([parser.ValueTerminal('test:', 'atext')]),
2577
parser.CFWSList([parser.WhiteSpaceTerminal(' ', 'fws')]), body])
2578
self._test(header, 'test: \n ' + 'x'*77 + '\n')
2580
def test_whitespace_splitting(self):
2581
self._test(parser.get_unstructured('xxx ' + 'y'*77),
2582
'xxx \n ' + 'y'*77 + '\n')
2584
if __name__ == '__main__':