--- a/Lib/email/_header_value_parser.py 2016-12-23 02:21:19.000000000 +0000 +++ b/Lib/email/_header_value_parser.py 2017-02-07 15:50:21.522642086 +0000 @@ -1742,15 +1742,21 @@ leader, value = get_cfws(value) else: leader = None - if value[0]=='"': - token, value = get_quoted_string(value) - elif value[0] in SPECIALS: - raise errors.HeaderParseError("Expected 'atom' or 'quoted-string' " - "but found '{}'".format(value)) + + if value: + if value[0]=='"': + token, value = get_quoted_string(value) + elif value[0] in SPECIALS: + raise errors.HeaderParseError("Expected 'atom' or 'quoted-string' " + "but found '{}'".format(value)) + else: + token, value = get_atom(value) + + if leader is not None: + token[:0] = [leader] else: - token, value = get_atom(value) - if leader is not None: - token[:0] = [leader] + token = leader + return token, value def get_phrase(value): --- a/Lib/test/test_email/test__header_value_parser.py 2016-12-23 02:21:20.000000000 +0000 +++ b/Lib/test/test_email/test__header_value_parser.py 2017-02-07 15:50:50.382183511 +0000 @@ -922,6 +922,20 @@ self._test_get_x(parser.get_word, 'foo.', 'foo', 'foo', [], '.') + def test_get_word_all_CFWS(self): + word = self._test_get_x(parser.get_word, + '(Recipients list suppressed)', + str(parser.CFWSList([parser.Comment([ + parser.WhiteSpaceTerminal('Recipients', 'ptext'), + parser.WhiteSpaceTerminal(' ', 'fws'), + parser.WhiteSpaceTerminal('list', 'ptext'), + parser.WhiteSpaceTerminal(' ', 'fws'), + parser.WhiteSpaceTerminal('suppressed', 'ptext') + ])])), + ' ', [], '' + ) + self.assertEqual(word.token_type, 'cfws') + # get_phrase def test_get_phrase_simple(self): @@ -2443,6 +2457,18 @@ self.assertEqual(str(address_list.addresses[1]), str(address_list.mailboxes[2])) + def test_get_address_list_CFWS(self): + address_list = self._test_get_x(parser.get_address_list, + '(Recipient list suppressed)', + '(Recipient list suppressed)', + ' ', + [errors.ObsoleteHeaderDefect], # no content in address list + '') + self.assertEqual(address_list.token_type, 'address-list') + self.assertEqual(len(address_list.mailboxes), 0) + self.assertEqual(address_list.mailboxes, + address_list.all_mailboxes) + def test_invalid_content_disposition(self): content_disp = self._test_parse_x( parser.parse_content_disposition_header,