|  | 
| 4 | 4 | 
 | 
| 5 | 5 | import re | 
| 6 | 6 | import sys | 
| 7 |  | -from email._policybase import Policy, Compat32, compat32, _extend_docstrings | 
| 8 |  | -from email.utils import _has_surrogates | 
| 9 |  | -from email.headerregistry import HeaderRegistry as HeaderRegistry | 
|  | 7 | +from email._policybase import Compat32, Policy, _extend_docstrings, compat32 | 
| 10 | 8 | from email.contentmanager import raw_data_manager | 
|  | 9 | +from email.headerregistry import HeaderRegistry as HeaderRegistry | 
| 11 | 10 | from email.message import EmailMessage | 
|  | 11 | +from email.utils import _has_surrogates | 
| 12 | 12 | 
 | 
| 13 | 13 | __all__ = [ | 
| 14 | 14 |     'Compat32', | 
| @@ -125,7 +125,27 @@ def header_source_parse(self, sourcelines): | 
| 125 | 125 | 
 | 
| 126 | 126 |         """ | 
| 127 | 127 |         name, value = sourcelines[0].split(':', 1) | 
| 128 |  | -        value = value.lstrip(' \t') + ''.join(sourcelines[1:]) | 
|  | 128 | + | 
|  | 129 | +        # Fixed: https://github.com/python/cpython/issues/124452 | 
|  | 130 | +        # | 
|  | 131 | +        # Root cause: The function '_refold_parse_tree' in '_header_value_parse.py'. | 
|  | 132 | +        # If there is no WSP, it can't figure out how to wrap the text. | 
|  | 133 | +        # Therefore, it places the entire value directly after '\n', and because | 
|  | 134 | +        # there is a WSP after '<HeaderName>:', the WSP will be moved to the front | 
|  | 135 | +        # of the value according to RFC5322, section 2.2.3. | 
|  | 136 | +        # | 
|  | 137 | +        # However, the WSP is not part of the value; therefore, we must  | 
|  | 138 | +        # remove it. | 
|  | 139 | + | 
|  | 140 | +        # Remove leading WSP in the first line only if there no value in the | 
|  | 141 | +        # first line, and has values after that | 
|  | 142 | +        remove_wsp = not value.strip() and len(sourcelines) > 1 | 
|  | 143 | + | 
|  | 144 | +        value = value.lstrip(' \t') | 
|  | 145 | +        if remove_wsp and sourcelines[1][0] in ' \t': | 
|  | 146 | +            sourcelines[1] = sourcelines[1][1:] | 
|  | 147 | + | 
|  | 148 | +        value += ''.join(sourcelines[1:]) | 
| 129 | 149 |         return (name, value.rstrip('\r\n')) | 
| 130 | 150 | 
 | 
| 131 | 151 |     def header_store_parse(self, name, value): | 
|  | 
0 commit comments