1*cda5da8dSAndroid Build Coastguard Worker"""This will be the home for the policy that hooks in the new 2*cda5da8dSAndroid Build Coastguard Workercode that adds all the email6 features. 3*cda5da8dSAndroid Build Coastguard Worker""" 4*cda5da8dSAndroid Build Coastguard Worker 5*cda5da8dSAndroid Build Coastguard Workerimport re 6*cda5da8dSAndroid Build Coastguard Workerimport sys 7*cda5da8dSAndroid Build Coastguard Workerfrom email._policybase import Policy, Compat32, compat32, _extend_docstrings 8*cda5da8dSAndroid Build Coastguard Workerfrom email.utils import _has_surrogates 9*cda5da8dSAndroid Build Coastguard Workerfrom email.headerregistry import HeaderRegistry as HeaderRegistry 10*cda5da8dSAndroid Build Coastguard Workerfrom email.contentmanager import raw_data_manager 11*cda5da8dSAndroid Build Coastguard Workerfrom email.message import EmailMessage 12*cda5da8dSAndroid Build Coastguard Worker 13*cda5da8dSAndroid Build Coastguard Worker__all__ = [ 14*cda5da8dSAndroid Build Coastguard Worker 'Compat32', 15*cda5da8dSAndroid Build Coastguard Worker 'compat32', 16*cda5da8dSAndroid Build Coastguard Worker 'Policy', 17*cda5da8dSAndroid Build Coastguard Worker 'EmailPolicy', 18*cda5da8dSAndroid Build Coastguard Worker 'default', 19*cda5da8dSAndroid Build Coastguard Worker 'strict', 20*cda5da8dSAndroid Build Coastguard Worker 'SMTP', 21*cda5da8dSAndroid Build Coastguard Worker 'HTTP', 22*cda5da8dSAndroid Build Coastguard Worker ] 23*cda5da8dSAndroid Build Coastguard Worker 24*cda5da8dSAndroid Build Coastguard Workerlinesep_splitter = re.compile(r'\n|\r') 25*cda5da8dSAndroid Build Coastguard Worker 26*cda5da8dSAndroid Build Coastguard Worker@_extend_docstrings 27*cda5da8dSAndroid Build Coastguard Workerclass EmailPolicy(Policy): 28*cda5da8dSAndroid Build Coastguard Worker 29*cda5da8dSAndroid Build Coastguard Worker """+ 30*cda5da8dSAndroid Build Coastguard Worker PROVISIONAL 31*cda5da8dSAndroid Build Coastguard Worker 32*cda5da8dSAndroid Build Coastguard Worker The API extensions enabled by this policy are currently provisional. 33*cda5da8dSAndroid Build Coastguard Worker Refer to the documentation for details. 34*cda5da8dSAndroid Build Coastguard Worker 35*cda5da8dSAndroid Build Coastguard Worker This policy adds new header parsing and folding algorithms. Instead of 36*cda5da8dSAndroid Build Coastguard Worker simple strings, headers are custom objects with custom attributes 37*cda5da8dSAndroid Build Coastguard Worker depending on the type of the field. The folding algorithm fully 38*cda5da8dSAndroid Build Coastguard Worker implements RFCs 2047 and 5322. 39*cda5da8dSAndroid Build Coastguard Worker 40*cda5da8dSAndroid Build Coastguard Worker In addition to the settable attributes listed above that apply to 41*cda5da8dSAndroid Build Coastguard Worker all Policies, this policy adds the following additional attributes: 42*cda5da8dSAndroid Build Coastguard Worker 43*cda5da8dSAndroid Build Coastguard Worker utf8 -- if False (the default) message headers will be 44*cda5da8dSAndroid Build Coastguard Worker serialized as ASCII, using encoded words to encode 45*cda5da8dSAndroid Build Coastguard Worker any non-ASCII characters in the source strings. If 46*cda5da8dSAndroid Build Coastguard Worker True, the message headers will be serialized using 47*cda5da8dSAndroid Build Coastguard Worker utf8 and will not contain encoded words (see RFC 48*cda5da8dSAndroid Build Coastguard Worker 6532 for more on this serialization format). 49*cda5da8dSAndroid Build Coastguard Worker 50*cda5da8dSAndroid Build Coastguard Worker refold_source -- if the value for a header in the Message object 51*cda5da8dSAndroid Build Coastguard Worker came from the parsing of some source, this attribute 52*cda5da8dSAndroid Build Coastguard Worker indicates whether or not a generator should refold 53*cda5da8dSAndroid Build Coastguard Worker that value when transforming the message back into 54*cda5da8dSAndroid Build Coastguard Worker stream form. The possible values are: 55*cda5da8dSAndroid Build Coastguard Worker 56*cda5da8dSAndroid Build Coastguard Worker none -- all source values use original folding 57*cda5da8dSAndroid Build Coastguard Worker long -- source values that have any line that is 58*cda5da8dSAndroid Build Coastguard Worker longer than max_line_length will be 59*cda5da8dSAndroid Build Coastguard Worker refolded 60*cda5da8dSAndroid Build Coastguard Worker all -- all values are refolded. 61*cda5da8dSAndroid Build Coastguard Worker 62*cda5da8dSAndroid Build Coastguard Worker The default is 'long'. 63*cda5da8dSAndroid Build Coastguard Worker 64*cda5da8dSAndroid Build Coastguard Worker header_factory -- a callable that takes two arguments, 'name' and 65*cda5da8dSAndroid Build Coastguard Worker 'value', where 'name' is a header field name and 66*cda5da8dSAndroid Build Coastguard Worker 'value' is an unfolded header field value, and 67*cda5da8dSAndroid Build Coastguard Worker returns a string-like object that represents that 68*cda5da8dSAndroid Build Coastguard Worker header. A default header_factory is provided that 69*cda5da8dSAndroid Build Coastguard Worker understands some of the RFC5322 header field types. 70*cda5da8dSAndroid Build Coastguard Worker (Currently address fields and date fields have 71*cda5da8dSAndroid Build Coastguard Worker special treatment, while all other fields are 72*cda5da8dSAndroid Build Coastguard Worker treated as unstructured. This list will be 73*cda5da8dSAndroid Build Coastguard Worker completed before the extension is marked stable.) 74*cda5da8dSAndroid Build Coastguard Worker 75*cda5da8dSAndroid Build Coastguard Worker content_manager -- an object with at least two methods: get_content 76*cda5da8dSAndroid Build Coastguard Worker and set_content. When the get_content or 77*cda5da8dSAndroid Build Coastguard Worker set_content method of a Message object is called, 78*cda5da8dSAndroid Build Coastguard Worker it calls the corresponding method of this object, 79*cda5da8dSAndroid Build Coastguard Worker passing it the message object as its first argument, 80*cda5da8dSAndroid Build Coastguard Worker and any arguments or keywords that were passed to 81*cda5da8dSAndroid Build Coastguard Worker it as additional arguments. The default 82*cda5da8dSAndroid Build Coastguard Worker content_manager is 83*cda5da8dSAndroid Build Coastguard Worker :data:`~email.contentmanager.raw_data_manager`. 84*cda5da8dSAndroid Build Coastguard Worker 85*cda5da8dSAndroid Build Coastguard Worker """ 86*cda5da8dSAndroid Build Coastguard Worker 87*cda5da8dSAndroid Build Coastguard Worker message_factory = EmailMessage 88*cda5da8dSAndroid Build Coastguard Worker utf8 = False 89*cda5da8dSAndroid Build Coastguard Worker refold_source = 'long' 90*cda5da8dSAndroid Build Coastguard Worker header_factory = HeaderRegistry() 91*cda5da8dSAndroid Build Coastguard Worker content_manager = raw_data_manager 92*cda5da8dSAndroid Build Coastguard Worker 93*cda5da8dSAndroid Build Coastguard Worker def __init__(self, **kw): 94*cda5da8dSAndroid Build Coastguard Worker # Ensure that each new instance gets a unique header factory 95*cda5da8dSAndroid Build Coastguard Worker # (as opposed to clones, which share the factory). 96*cda5da8dSAndroid Build Coastguard Worker if 'header_factory' not in kw: 97*cda5da8dSAndroid Build Coastguard Worker object.__setattr__(self, 'header_factory', HeaderRegistry()) 98*cda5da8dSAndroid Build Coastguard Worker super().__init__(**kw) 99*cda5da8dSAndroid Build Coastguard Worker 100*cda5da8dSAndroid Build Coastguard Worker def header_max_count(self, name): 101*cda5da8dSAndroid Build Coastguard Worker """+ 102*cda5da8dSAndroid Build Coastguard Worker The implementation for this class returns the max_count attribute from 103*cda5da8dSAndroid Build Coastguard Worker the specialized header class that would be used to construct a header 104*cda5da8dSAndroid Build Coastguard Worker of type 'name'. 105*cda5da8dSAndroid Build Coastguard Worker """ 106*cda5da8dSAndroid Build Coastguard Worker return self.header_factory[name].max_count 107*cda5da8dSAndroid Build Coastguard Worker 108*cda5da8dSAndroid Build Coastguard Worker # The logic of the next three methods is chosen such that it is possible to 109*cda5da8dSAndroid Build Coastguard Worker # switch a Message object between a Compat32 policy and a policy derived 110*cda5da8dSAndroid Build Coastguard Worker # from this class and have the results stay consistent. This allows a 111*cda5da8dSAndroid Build Coastguard Worker # Message object constructed with this policy to be passed to a library 112*cda5da8dSAndroid Build Coastguard Worker # that only handles Compat32 objects, or to receive such an object and 113*cda5da8dSAndroid Build Coastguard Worker # convert it to use the newer style by just changing its policy. It is 114*cda5da8dSAndroid Build Coastguard Worker # also chosen because it postpones the relatively expensive full rfc5322 115*cda5da8dSAndroid Build Coastguard Worker # parse until as late as possible when parsing from source, since in many 116*cda5da8dSAndroid Build Coastguard Worker # applications only a few headers will actually be inspected. 117*cda5da8dSAndroid Build Coastguard Worker 118*cda5da8dSAndroid Build Coastguard Worker def header_source_parse(self, sourcelines): 119*cda5da8dSAndroid Build Coastguard Worker """+ 120*cda5da8dSAndroid Build Coastguard Worker The name is parsed as everything up to the ':' and returned unmodified. 121*cda5da8dSAndroid Build Coastguard Worker The value is determined by stripping leading whitespace off the 122*cda5da8dSAndroid Build Coastguard Worker remainder of the first line, joining all subsequent lines together, and 123*cda5da8dSAndroid Build Coastguard Worker stripping any trailing carriage return or linefeed characters. (This 124*cda5da8dSAndroid Build Coastguard Worker is the same as Compat32). 125*cda5da8dSAndroid Build Coastguard Worker 126*cda5da8dSAndroid Build Coastguard Worker """ 127*cda5da8dSAndroid Build Coastguard Worker name, value = sourcelines[0].split(':', 1) 128*cda5da8dSAndroid Build Coastguard Worker value = value.lstrip(' \t') + ''.join(sourcelines[1:]) 129*cda5da8dSAndroid Build Coastguard Worker return (name, value.rstrip('\r\n')) 130*cda5da8dSAndroid Build Coastguard Worker 131*cda5da8dSAndroid Build Coastguard Worker def header_store_parse(self, name, value): 132*cda5da8dSAndroid Build Coastguard Worker """+ 133*cda5da8dSAndroid Build Coastguard Worker The name is returned unchanged. If the input value has a 'name' 134*cda5da8dSAndroid Build Coastguard Worker attribute and it matches the name ignoring case, the value is returned 135*cda5da8dSAndroid Build Coastguard Worker unchanged. Otherwise the name and value are passed to header_factory 136*cda5da8dSAndroid Build Coastguard Worker method, and the resulting custom header object is returned as the 137*cda5da8dSAndroid Build Coastguard Worker value. In this case a ValueError is raised if the input value contains 138*cda5da8dSAndroid Build Coastguard Worker CR or LF characters. 139*cda5da8dSAndroid Build Coastguard Worker 140*cda5da8dSAndroid Build Coastguard Worker """ 141*cda5da8dSAndroid Build Coastguard Worker if hasattr(value, 'name') and value.name.lower() == name.lower(): 142*cda5da8dSAndroid Build Coastguard Worker return (name, value) 143*cda5da8dSAndroid Build Coastguard Worker if isinstance(value, str) and len(value.splitlines())>1: 144*cda5da8dSAndroid Build Coastguard Worker # XXX this error message isn't quite right when we use splitlines 145*cda5da8dSAndroid Build Coastguard Worker # (see issue 22233), but I'm not sure what should happen here. 146*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Header values may not contain linefeed " 147*cda5da8dSAndroid Build Coastguard Worker "or carriage return characters") 148*cda5da8dSAndroid Build Coastguard Worker return (name, self.header_factory(name, value)) 149*cda5da8dSAndroid Build Coastguard Worker 150*cda5da8dSAndroid Build Coastguard Worker def header_fetch_parse(self, name, value): 151*cda5da8dSAndroid Build Coastguard Worker """+ 152*cda5da8dSAndroid Build Coastguard Worker If the value has a 'name' attribute, it is returned to unmodified. 153*cda5da8dSAndroid Build Coastguard Worker Otherwise the name and the value with any linesep characters removed 154*cda5da8dSAndroid Build Coastguard Worker are passed to the header_factory method, and the resulting custom 155*cda5da8dSAndroid Build Coastguard Worker header object is returned. Any surrogateescaped bytes get turned 156*cda5da8dSAndroid Build Coastguard Worker into the unicode unknown-character glyph. 157*cda5da8dSAndroid Build Coastguard Worker 158*cda5da8dSAndroid Build Coastguard Worker """ 159*cda5da8dSAndroid Build Coastguard Worker if hasattr(value, 'name'): 160*cda5da8dSAndroid Build Coastguard Worker return value 161*cda5da8dSAndroid Build Coastguard Worker # We can't use splitlines here because it splits on more than \r and \n. 162*cda5da8dSAndroid Build Coastguard Worker value = ''.join(linesep_splitter.split(value)) 163*cda5da8dSAndroid Build Coastguard Worker return self.header_factory(name, value) 164*cda5da8dSAndroid Build Coastguard Worker 165*cda5da8dSAndroid Build Coastguard Worker def fold(self, name, value): 166*cda5da8dSAndroid Build Coastguard Worker """+ 167*cda5da8dSAndroid Build Coastguard Worker Header folding is controlled by the refold_source policy setting. A 168*cda5da8dSAndroid Build Coastguard Worker value is considered to be a 'source value' if and only if it does not 169*cda5da8dSAndroid Build Coastguard Worker have a 'name' attribute (having a 'name' attribute means it is a header 170*cda5da8dSAndroid Build Coastguard Worker object of some sort). If a source value needs to be refolded according 171*cda5da8dSAndroid Build Coastguard Worker to the policy, it is converted into a custom header object by passing 172*cda5da8dSAndroid Build Coastguard Worker the name and the value with any linesep characters removed to the 173*cda5da8dSAndroid Build Coastguard Worker header_factory method. Folding of a custom header object is done by 174*cda5da8dSAndroid Build Coastguard Worker calling its fold method with the current policy. 175*cda5da8dSAndroid Build Coastguard Worker 176*cda5da8dSAndroid Build Coastguard Worker Source values are split into lines using splitlines. If the value is 177*cda5da8dSAndroid Build Coastguard Worker not to be refolded, the lines are rejoined using the linesep from the 178*cda5da8dSAndroid Build Coastguard Worker policy and returned. The exception is lines containing non-ascii 179*cda5da8dSAndroid Build Coastguard Worker binary data. In that case the value is refolded regardless of the 180*cda5da8dSAndroid Build Coastguard Worker refold_source setting, which causes the binary data to be CTE encoded 181*cda5da8dSAndroid Build Coastguard Worker using the unknown-8bit charset. 182*cda5da8dSAndroid Build Coastguard Worker 183*cda5da8dSAndroid Build Coastguard Worker """ 184*cda5da8dSAndroid Build Coastguard Worker return self._fold(name, value, refold_binary=True) 185*cda5da8dSAndroid Build Coastguard Worker 186*cda5da8dSAndroid Build Coastguard Worker def fold_binary(self, name, value): 187*cda5da8dSAndroid Build Coastguard Worker """+ 188*cda5da8dSAndroid Build Coastguard Worker The same as fold if cte_type is 7bit, except that the returned value is 189*cda5da8dSAndroid Build Coastguard Worker bytes. 190*cda5da8dSAndroid Build Coastguard Worker 191*cda5da8dSAndroid Build Coastguard Worker If cte_type is 8bit, non-ASCII binary data is converted back into 192*cda5da8dSAndroid Build Coastguard Worker bytes. Headers with binary data are not refolded, regardless of the 193*cda5da8dSAndroid Build Coastguard Worker refold_header setting, since there is no way to know whether the binary 194*cda5da8dSAndroid Build Coastguard Worker data consists of single byte characters or multibyte characters. 195*cda5da8dSAndroid Build Coastguard Worker 196*cda5da8dSAndroid Build Coastguard Worker If utf8 is true, headers are encoded to utf8, otherwise to ascii with 197*cda5da8dSAndroid Build Coastguard Worker non-ASCII unicode rendered as encoded words. 198*cda5da8dSAndroid Build Coastguard Worker 199*cda5da8dSAndroid Build Coastguard Worker """ 200*cda5da8dSAndroid Build Coastguard Worker folded = self._fold(name, value, refold_binary=self.cte_type=='7bit') 201*cda5da8dSAndroid Build Coastguard Worker charset = 'utf8' if self.utf8 else 'ascii' 202*cda5da8dSAndroid Build Coastguard Worker return folded.encode(charset, 'surrogateescape') 203*cda5da8dSAndroid Build Coastguard Worker 204*cda5da8dSAndroid Build Coastguard Worker def _fold(self, name, value, refold_binary=False): 205*cda5da8dSAndroid Build Coastguard Worker if hasattr(value, 'name'): 206*cda5da8dSAndroid Build Coastguard Worker return value.fold(policy=self) 207*cda5da8dSAndroid Build Coastguard Worker maxlen = self.max_line_length if self.max_line_length else sys.maxsize 208*cda5da8dSAndroid Build Coastguard Worker lines = value.splitlines() 209*cda5da8dSAndroid Build Coastguard Worker refold = (self.refold_source == 'all' or 210*cda5da8dSAndroid Build Coastguard Worker self.refold_source == 'long' and 211*cda5da8dSAndroid Build Coastguard Worker (lines and len(lines[0])+len(name)+2 > maxlen or 212*cda5da8dSAndroid Build Coastguard Worker any(len(x) > maxlen for x in lines[1:]))) 213*cda5da8dSAndroid Build Coastguard Worker if refold or refold_binary and _has_surrogates(value): 214*cda5da8dSAndroid Build Coastguard Worker return self.header_factory(name, ''.join(lines)).fold(policy=self) 215*cda5da8dSAndroid Build Coastguard Worker return name + ': ' + self.linesep.join(lines) + self.linesep 216*cda5da8dSAndroid Build Coastguard Worker 217*cda5da8dSAndroid Build Coastguard Worker 218*cda5da8dSAndroid Build Coastguard Workerdefault = EmailPolicy() 219*cda5da8dSAndroid Build Coastguard Worker# Make the default policy use the class default header_factory 220*cda5da8dSAndroid Build Coastguard Workerdel default.header_factory 221*cda5da8dSAndroid Build Coastguard Workerstrict = default.clone(raise_on_defect=True) 222*cda5da8dSAndroid Build Coastguard WorkerSMTP = default.clone(linesep='\r\n') 223*cda5da8dSAndroid Build Coastguard WorkerHTTP = default.clone(linesep='\r\n', max_line_length=None) 224*cda5da8dSAndroid Build Coastguard WorkerSMTPUTF8 = SMTP.clone(utf8=True) 225