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