jpayne@68
|
1 """Policy framework for the email package.
|
jpayne@68
|
2
|
jpayne@68
|
3 Allows fine grained feature control of how the package parses and emits data.
|
jpayne@68
|
4 """
|
jpayne@68
|
5
|
jpayne@68
|
6 import abc
|
jpayne@68
|
7 from email import header
|
jpayne@68
|
8 from email import charset as _charset
|
jpayne@68
|
9 from email.utils import _has_surrogates
|
jpayne@68
|
10
|
jpayne@68
|
11 __all__ = [
|
jpayne@68
|
12 'Policy',
|
jpayne@68
|
13 'Compat32',
|
jpayne@68
|
14 'compat32',
|
jpayne@68
|
15 ]
|
jpayne@68
|
16
|
jpayne@68
|
17
|
jpayne@68
|
18 class _PolicyBase:
|
jpayne@68
|
19
|
jpayne@68
|
20 """Policy Object basic framework.
|
jpayne@68
|
21
|
jpayne@68
|
22 This class is useless unless subclassed. A subclass should define
|
jpayne@68
|
23 class attributes with defaults for any values that are to be
|
jpayne@68
|
24 managed by the Policy object. The constructor will then allow
|
jpayne@68
|
25 non-default values to be set for these attributes at instance
|
jpayne@68
|
26 creation time. The instance will be callable, taking these same
|
jpayne@68
|
27 attributes keyword arguments, and returning a new instance
|
jpayne@68
|
28 identical to the called instance except for those values changed
|
jpayne@68
|
29 by the keyword arguments. Instances may be added, yielding new
|
jpayne@68
|
30 instances with any non-default values from the right hand
|
jpayne@68
|
31 operand overriding those in the left hand operand. That is,
|
jpayne@68
|
32
|
jpayne@68
|
33 A + B == A(<non-default values of B>)
|
jpayne@68
|
34
|
jpayne@68
|
35 The repr of an instance can be used to reconstruct the object
|
jpayne@68
|
36 if and only if the repr of the values can be used to reconstruct
|
jpayne@68
|
37 those values.
|
jpayne@68
|
38
|
jpayne@68
|
39 """
|
jpayne@68
|
40
|
jpayne@68
|
41 def __init__(self, **kw):
|
jpayne@68
|
42 """Create new Policy, possibly overriding some defaults.
|
jpayne@68
|
43
|
jpayne@68
|
44 See class docstring for a list of overridable attributes.
|
jpayne@68
|
45
|
jpayne@68
|
46 """
|
jpayne@68
|
47 for name, value in kw.items():
|
jpayne@68
|
48 if hasattr(self, name):
|
jpayne@68
|
49 super(_PolicyBase,self).__setattr__(name, value)
|
jpayne@68
|
50 else:
|
jpayne@68
|
51 raise TypeError(
|
jpayne@68
|
52 "{!r} is an invalid keyword argument for {}".format(
|
jpayne@68
|
53 name, self.__class__.__name__))
|
jpayne@68
|
54
|
jpayne@68
|
55 def __repr__(self):
|
jpayne@68
|
56 args = [ "{}={!r}".format(name, value)
|
jpayne@68
|
57 for name, value in self.__dict__.items() ]
|
jpayne@68
|
58 return "{}({})".format(self.__class__.__name__, ', '.join(args))
|
jpayne@68
|
59
|
jpayne@68
|
60 def clone(self, **kw):
|
jpayne@68
|
61 """Return a new instance with specified attributes changed.
|
jpayne@68
|
62
|
jpayne@68
|
63 The new instance has the same attribute values as the current object,
|
jpayne@68
|
64 except for the changes passed in as keyword arguments.
|
jpayne@68
|
65
|
jpayne@68
|
66 """
|
jpayne@68
|
67 newpolicy = self.__class__.__new__(self.__class__)
|
jpayne@68
|
68 for attr, value in self.__dict__.items():
|
jpayne@68
|
69 object.__setattr__(newpolicy, attr, value)
|
jpayne@68
|
70 for attr, value in kw.items():
|
jpayne@68
|
71 if not hasattr(self, attr):
|
jpayne@68
|
72 raise TypeError(
|
jpayne@68
|
73 "{!r} is an invalid keyword argument for {}".format(
|
jpayne@68
|
74 attr, self.__class__.__name__))
|
jpayne@68
|
75 object.__setattr__(newpolicy, attr, value)
|
jpayne@68
|
76 return newpolicy
|
jpayne@68
|
77
|
jpayne@68
|
78 def __setattr__(self, name, value):
|
jpayne@68
|
79 if hasattr(self, name):
|
jpayne@68
|
80 msg = "{!r} object attribute {!r} is read-only"
|
jpayne@68
|
81 else:
|
jpayne@68
|
82 msg = "{!r} object has no attribute {!r}"
|
jpayne@68
|
83 raise AttributeError(msg.format(self.__class__.__name__, name))
|
jpayne@68
|
84
|
jpayne@68
|
85 def __add__(self, other):
|
jpayne@68
|
86 """Non-default values from right operand override those from left.
|
jpayne@68
|
87
|
jpayne@68
|
88 The object returned is a new instance of the subclass.
|
jpayne@68
|
89
|
jpayne@68
|
90 """
|
jpayne@68
|
91 return self.clone(**other.__dict__)
|
jpayne@68
|
92
|
jpayne@68
|
93
|
jpayne@68
|
94 def _append_doc(doc, added_doc):
|
jpayne@68
|
95 doc = doc.rsplit('\n', 1)[0]
|
jpayne@68
|
96 added_doc = added_doc.split('\n', 1)[1]
|
jpayne@68
|
97 return doc + '\n' + added_doc
|
jpayne@68
|
98
|
jpayne@68
|
99 def _extend_docstrings(cls):
|
jpayne@68
|
100 if cls.__doc__ and cls.__doc__.startswith('+'):
|
jpayne@68
|
101 cls.__doc__ = _append_doc(cls.__bases__[0].__doc__, cls.__doc__)
|
jpayne@68
|
102 for name, attr in cls.__dict__.items():
|
jpayne@68
|
103 if attr.__doc__ and attr.__doc__.startswith('+'):
|
jpayne@68
|
104 for c in (c for base in cls.__bases__ for c in base.mro()):
|
jpayne@68
|
105 doc = getattr(getattr(c, name), '__doc__')
|
jpayne@68
|
106 if doc:
|
jpayne@68
|
107 attr.__doc__ = _append_doc(doc, attr.__doc__)
|
jpayne@68
|
108 break
|
jpayne@68
|
109 return cls
|
jpayne@68
|
110
|
jpayne@68
|
111
|
jpayne@68
|
112 class Policy(_PolicyBase, metaclass=abc.ABCMeta):
|
jpayne@68
|
113
|
jpayne@68
|
114 r"""Controls for how messages are interpreted and formatted.
|
jpayne@68
|
115
|
jpayne@68
|
116 Most of the classes and many of the methods in the email package accept
|
jpayne@68
|
117 Policy objects as parameters. A Policy object contains a set of values and
|
jpayne@68
|
118 functions that control how input is interpreted and how output is rendered.
|
jpayne@68
|
119 For example, the parameter 'raise_on_defect' controls whether or not an RFC
|
jpayne@68
|
120 violation results in an error being raised or not, while 'max_line_length'
|
jpayne@68
|
121 controls the maximum length of output lines when a Message is serialized.
|
jpayne@68
|
122
|
jpayne@68
|
123 Any valid attribute may be overridden when a Policy is created by passing
|
jpayne@68
|
124 it as a keyword argument to the constructor. Policy objects are immutable,
|
jpayne@68
|
125 but a new Policy object can be created with only certain values changed by
|
jpayne@68
|
126 calling the Policy instance with keyword arguments. Policy objects can
|
jpayne@68
|
127 also be added, producing a new Policy object in which the non-default
|
jpayne@68
|
128 attributes set in the right hand operand overwrite those specified in the
|
jpayne@68
|
129 left operand.
|
jpayne@68
|
130
|
jpayne@68
|
131 Settable attributes:
|
jpayne@68
|
132
|
jpayne@68
|
133 raise_on_defect -- If true, then defects should be raised as errors.
|
jpayne@68
|
134 Default: False.
|
jpayne@68
|
135
|
jpayne@68
|
136 linesep -- string containing the value to use as separation
|
jpayne@68
|
137 between output lines. Default '\n'.
|
jpayne@68
|
138
|
jpayne@68
|
139 cte_type -- Type of allowed content transfer encodings
|
jpayne@68
|
140
|
jpayne@68
|
141 7bit -- ASCII only
|
jpayne@68
|
142 8bit -- Content-Transfer-Encoding: 8bit is allowed
|
jpayne@68
|
143
|
jpayne@68
|
144 Default: 8bit. Also controls the disposition of
|
jpayne@68
|
145 (RFC invalid) binary data in headers; see the
|
jpayne@68
|
146 documentation of the binary_fold method.
|
jpayne@68
|
147
|
jpayne@68
|
148 max_line_length -- maximum length of lines, excluding 'linesep',
|
jpayne@68
|
149 during serialization. None or 0 means no line
|
jpayne@68
|
150 wrapping is done. Default is 78.
|
jpayne@68
|
151
|
jpayne@68
|
152 mangle_from_ -- a flag that, when True escapes From_ lines in the
|
jpayne@68
|
153 body of the message by putting a `>' in front of
|
jpayne@68
|
154 them. This is used when the message is being
|
jpayne@68
|
155 serialized by a generator. Default: True.
|
jpayne@68
|
156
|
jpayne@68
|
157 message_factory -- the class to use to create new message objects.
|
jpayne@68
|
158 If the value is None, the default is Message.
|
jpayne@68
|
159
|
jpayne@68
|
160 """
|
jpayne@68
|
161
|
jpayne@68
|
162 raise_on_defect = False
|
jpayne@68
|
163 linesep = '\n'
|
jpayne@68
|
164 cte_type = '8bit'
|
jpayne@68
|
165 max_line_length = 78
|
jpayne@68
|
166 mangle_from_ = False
|
jpayne@68
|
167 message_factory = None
|
jpayne@68
|
168
|
jpayne@68
|
169 def handle_defect(self, obj, defect):
|
jpayne@68
|
170 """Based on policy, either raise defect or call register_defect.
|
jpayne@68
|
171
|
jpayne@68
|
172 handle_defect(obj, defect)
|
jpayne@68
|
173
|
jpayne@68
|
174 defect should be a Defect subclass, but in any case must be an
|
jpayne@68
|
175 Exception subclass. obj is the object on which the defect should be
|
jpayne@68
|
176 registered if it is not raised. If the raise_on_defect is True, the
|
jpayne@68
|
177 defect is raised as an error, otherwise the object and the defect are
|
jpayne@68
|
178 passed to register_defect.
|
jpayne@68
|
179
|
jpayne@68
|
180 This method is intended to be called by parsers that discover defects.
|
jpayne@68
|
181 The email package parsers always call it with Defect instances.
|
jpayne@68
|
182
|
jpayne@68
|
183 """
|
jpayne@68
|
184 if self.raise_on_defect:
|
jpayne@68
|
185 raise defect
|
jpayne@68
|
186 self.register_defect(obj, defect)
|
jpayne@68
|
187
|
jpayne@68
|
188 def register_defect(self, obj, defect):
|
jpayne@68
|
189 """Record 'defect' on 'obj'.
|
jpayne@68
|
190
|
jpayne@68
|
191 Called by handle_defect if raise_on_defect is False. This method is
|
jpayne@68
|
192 part of the Policy API so that Policy subclasses can implement custom
|
jpayne@68
|
193 defect handling. The default implementation calls the append method of
|
jpayne@68
|
194 the defects attribute of obj. The objects used by the email package by
|
jpayne@68
|
195 default that get passed to this method will always have a defects
|
jpayne@68
|
196 attribute with an append method.
|
jpayne@68
|
197
|
jpayne@68
|
198 """
|
jpayne@68
|
199 obj.defects.append(defect)
|
jpayne@68
|
200
|
jpayne@68
|
201 def header_max_count(self, name):
|
jpayne@68
|
202 """Return the maximum allowed number of headers named 'name'.
|
jpayne@68
|
203
|
jpayne@68
|
204 Called when a header is added to a Message object. If the returned
|
jpayne@68
|
205 value is not 0 or None, and there are already a number of headers with
|
jpayne@68
|
206 the name 'name' equal to the value returned, a ValueError is raised.
|
jpayne@68
|
207
|
jpayne@68
|
208 Because the default behavior of Message's __setitem__ is to append the
|
jpayne@68
|
209 value to the list of headers, it is easy to create duplicate headers
|
jpayne@68
|
210 without realizing it. This method allows certain headers to be limited
|
jpayne@68
|
211 in the number of instances of that header that may be added to a
|
jpayne@68
|
212 Message programmatically. (The limit is not observed by the parser,
|
jpayne@68
|
213 which will faithfully produce as many headers as exist in the message
|
jpayne@68
|
214 being parsed.)
|
jpayne@68
|
215
|
jpayne@68
|
216 The default implementation returns None for all header names.
|
jpayne@68
|
217 """
|
jpayne@68
|
218 return None
|
jpayne@68
|
219
|
jpayne@68
|
220 @abc.abstractmethod
|
jpayne@68
|
221 def header_source_parse(self, sourcelines):
|
jpayne@68
|
222 """Given a list of linesep terminated strings constituting the lines of
|
jpayne@68
|
223 a single header, return the (name, value) tuple that should be stored
|
jpayne@68
|
224 in the model. The input lines should retain their terminating linesep
|
jpayne@68
|
225 characters. The lines passed in by the email package may contain
|
jpayne@68
|
226 surrogateescaped binary data.
|
jpayne@68
|
227 """
|
jpayne@68
|
228 raise NotImplementedError
|
jpayne@68
|
229
|
jpayne@68
|
230 @abc.abstractmethod
|
jpayne@68
|
231 def header_store_parse(self, name, value):
|
jpayne@68
|
232 """Given the header name and the value provided by the application
|
jpayne@68
|
233 program, return the (name, value) that should be stored in the model.
|
jpayne@68
|
234 """
|
jpayne@68
|
235 raise NotImplementedError
|
jpayne@68
|
236
|
jpayne@68
|
237 @abc.abstractmethod
|
jpayne@68
|
238 def header_fetch_parse(self, name, value):
|
jpayne@68
|
239 """Given the header name and the value from the model, return the value
|
jpayne@68
|
240 to be returned to the application program that is requesting that
|
jpayne@68
|
241 header. The value passed in by the email package may contain
|
jpayne@68
|
242 surrogateescaped binary data if the lines were parsed by a BytesParser.
|
jpayne@68
|
243 The returned value should not contain any surrogateescaped data.
|
jpayne@68
|
244
|
jpayne@68
|
245 """
|
jpayne@68
|
246 raise NotImplementedError
|
jpayne@68
|
247
|
jpayne@68
|
248 @abc.abstractmethod
|
jpayne@68
|
249 def fold(self, name, value):
|
jpayne@68
|
250 """Given the header name and the value from the model, return a string
|
jpayne@68
|
251 containing linesep characters that implement the folding of the header
|
jpayne@68
|
252 according to the policy controls. The value passed in by the email
|
jpayne@68
|
253 package may contain surrogateescaped binary data if the lines were
|
jpayne@68
|
254 parsed by a BytesParser. The returned value should not contain any
|
jpayne@68
|
255 surrogateescaped data.
|
jpayne@68
|
256
|
jpayne@68
|
257 """
|
jpayne@68
|
258 raise NotImplementedError
|
jpayne@68
|
259
|
jpayne@68
|
260 @abc.abstractmethod
|
jpayne@68
|
261 def fold_binary(self, name, value):
|
jpayne@68
|
262 """Given the header name and the value from the model, return binary
|
jpayne@68
|
263 data containing linesep characters that implement the folding of the
|
jpayne@68
|
264 header according to the policy controls. The value passed in by the
|
jpayne@68
|
265 email package may contain surrogateescaped binary data.
|
jpayne@68
|
266
|
jpayne@68
|
267 """
|
jpayne@68
|
268 raise NotImplementedError
|
jpayne@68
|
269
|
jpayne@68
|
270
|
jpayne@68
|
271 @_extend_docstrings
|
jpayne@68
|
272 class Compat32(Policy):
|
jpayne@68
|
273
|
jpayne@68
|
274 """+
|
jpayne@68
|
275 This particular policy is the backward compatibility Policy. It
|
jpayne@68
|
276 replicates the behavior of the email package version 5.1.
|
jpayne@68
|
277 """
|
jpayne@68
|
278
|
jpayne@68
|
279 mangle_from_ = True
|
jpayne@68
|
280
|
jpayne@68
|
281 def _sanitize_header(self, name, value):
|
jpayne@68
|
282 # If the header value contains surrogates, return a Header using
|
jpayne@68
|
283 # the unknown-8bit charset to encode the bytes as encoded words.
|
jpayne@68
|
284 if not isinstance(value, str):
|
jpayne@68
|
285 # Assume it is already a header object
|
jpayne@68
|
286 return value
|
jpayne@68
|
287 if _has_surrogates(value):
|
jpayne@68
|
288 return header.Header(value, charset=_charset.UNKNOWN8BIT,
|
jpayne@68
|
289 header_name=name)
|
jpayne@68
|
290 else:
|
jpayne@68
|
291 return value
|
jpayne@68
|
292
|
jpayne@68
|
293 def header_source_parse(self, sourcelines):
|
jpayne@68
|
294 """+
|
jpayne@68
|
295 The name is parsed as everything up to the ':' and returned unmodified.
|
jpayne@68
|
296 The value is determined by stripping leading whitespace off the
|
jpayne@68
|
297 remainder of the first line, joining all subsequent lines together, and
|
jpayne@68
|
298 stripping any trailing carriage return or linefeed characters.
|
jpayne@68
|
299
|
jpayne@68
|
300 """
|
jpayne@68
|
301 name, value = sourcelines[0].split(':', 1)
|
jpayne@68
|
302 value = value.lstrip(' \t') + ''.join(sourcelines[1:])
|
jpayne@68
|
303 return (name, value.rstrip('\r\n'))
|
jpayne@68
|
304
|
jpayne@68
|
305 def header_store_parse(self, name, value):
|
jpayne@68
|
306 """+
|
jpayne@68
|
307 The name and value are returned unmodified.
|
jpayne@68
|
308 """
|
jpayne@68
|
309 return (name, value)
|
jpayne@68
|
310
|
jpayne@68
|
311 def header_fetch_parse(self, name, value):
|
jpayne@68
|
312 """+
|
jpayne@68
|
313 If the value contains binary data, it is converted into a Header object
|
jpayne@68
|
314 using the unknown-8bit charset. Otherwise it is returned unmodified.
|
jpayne@68
|
315 """
|
jpayne@68
|
316 return self._sanitize_header(name, value)
|
jpayne@68
|
317
|
jpayne@68
|
318 def fold(self, name, value):
|
jpayne@68
|
319 """+
|
jpayne@68
|
320 Headers are folded using the Header folding algorithm, which preserves
|
jpayne@68
|
321 existing line breaks in the value, and wraps each resulting line to the
|
jpayne@68
|
322 max_line_length. Non-ASCII binary data are CTE encoded using the
|
jpayne@68
|
323 unknown-8bit charset.
|
jpayne@68
|
324
|
jpayne@68
|
325 """
|
jpayne@68
|
326 return self._fold(name, value, sanitize=True)
|
jpayne@68
|
327
|
jpayne@68
|
328 def fold_binary(self, name, value):
|
jpayne@68
|
329 """+
|
jpayne@68
|
330 Headers are folded using the Header folding algorithm, which preserves
|
jpayne@68
|
331 existing line breaks in the value, and wraps each resulting line to the
|
jpayne@68
|
332 max_line_length. If cte_type is 7bit, non-ascii binary data is CTE
|
jpayne@68
|
333 encoded using the unknown-8bit charset. Otherwise the original source
|
jpayne@68
|
334 header is used, with its existing line breaks and/or binary data.
|
jpayne@68
|
335
|
jpayne@68
|
336 """
|
jpayne@68
|
337 folded = self._fold(name, value, sanitize=self.cte_type=='7bit')
|
jpayne@68
|
338 return folded.encode('ascii', 'surrogateescape')
|
jpayne@68
|
339
|
jpayne@68
|
340 def _fold(self, name, value, sanitize):
|
jpayne@68
|
341 parts = []
|
jpayne@68
|
342 parts.append('%s: ' % name)
|
jpayne@68
|
343 if isinstance(value, str):
|
jpayne@68
|
344 if _has_surrogates(value):
|
jpayne@68
|
345 if sanitize:
|
jpayne@68
|
346 h = header.Header(value,
|
jpayne@68
|
347 charset=_charset.UNKNOWN8BIT,
|
jpayne@68
|
348 header_name=name)
|
jpayne@68
|
349 else:
|
jpayne@68
|
350 # If we have raw 8bit data in a byte string, we have no idea
|
jpayne@68
|
351 # what the encoding is. There is no safe way to split this
|
jpayne@68
|
352 # string. If it's ascii-subset, then we could do a normal
|
jpayne@68
|
353 # ascii split, but if it's multibyte then we could break the
|
jpayne@68
|
354 # string. There's no way to know so the least harm seems to
|
jpayne@68
|
355 # be to not split the string and risk it being too long.
|
jpayne@68
|
356 parts.append(value)
|
jpayne@68
|
357 h = None
|
jpayne@68
|
358 else:
|
jpayne@68
|
359 h = header.Header(value, header_name=name)
|
jpayne@68
|
360 else:
|
jpayne@68
|
361 # Assume it is a Header-like object.
|
jpayne@68
|
362 h = value
|
jpayne@68
|
363 if h is not None:
|
jpayne@68
|
364 # The Header class interprets a value of None for maxlinelen as the
|
jpayne@68
|
365 # default value of 78, as recommended by RFC 2822.
|
jpayne@68
|
366 maxlinelen = 0
|
jpayne@68
|
367 if self.max_line_length is not None:
|
jpayne@68
|
368 maxlinelen = self.max_line_length
|
jpayne@68
|
369 parts.append(h.encode(linesep=self.linesep, maxlinelen=maxlinelen))
|
jpayne@68
|
370 parts.append(self.linesep)
|
jpayne@68
|
371 return ''.join(parts)
|
jpayne@68
|
372
|
jpayne@68
|
373
|
jpayne@68
|
374 compat32 = Compat32()
|