annotate Lib/email/generator.py @ 79675:c0a2294de787 2.7

Issue #16199: Backport 2to3 typo fix from 3.2.
author Chris Jerdonek <chris.jerdonek@gmail.com>
date Thu, 11 Oct 2012 16:15:46 -0700
parents 9f500171c592
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
59834
9eabba6ded09 Merged revisions 77120,77151,77155,77209,77229,77256,77317,77331,77333,77359-77360,77382,77561,77570 via svnmerge from
Georg Brandl <georg@python.org>
parents: 58974
diff changeset
1 # Copyright (C) 2001-2010 Python Software Foundation
37078
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
2 # Contact: email-sig@python.org
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
3
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
4 """Classes to generate plain text from a message object tree."""
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
5
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
6 __all__ = ['Generator', 'DecodedGenerator']
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
7
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
8 import re
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
9 import sys
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
10 import time
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
11 import random
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
12 import warnings
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
13
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
14 from cStringIO import StringIO
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
15 from email.header import Header
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
16
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
17 UNDERSCORE = '_'
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
18 NL = '\n'
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
19
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
20 fcre = re.compile(r'^From ', re.MULTILINE)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
21
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
22 def _is8bitstring(s):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
23 if isinstance(s, str):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
24 try:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
25 unicode(s, 'us-ascii')
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
26 except UnicodeError:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
27 return True
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
28 return False
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
29
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
30
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
31
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
32 class Generator:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
33 """Generates output from a Message object tree.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
34
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
35 This basic generator writes the message to the given file object as plain
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
36 text.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
37 """
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
38 #
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
39 # Public interface
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
40 #
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
41
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
42 def __init__(self, outfp, mangle_from_=True, maxheaderlen=78):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
43 """Create the generator for message flattening.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
44
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
45 outfp is the output file-like object for writing the message to. It
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
46 must have a write() method.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
47
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
48 Optional mangle_from_ is a flag that, when True (the default), escapes
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
49 From_ lines in the body of the message by putting a `>' in front of
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
50 them.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
51
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
52 Optional maxheaderlen specifies the longest length for a non-continued
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
53 header. When a header line is longer (in characters, with tabs
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
54 expanded to 8 spaces) than maxheaderlen, the header will split as
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
55 defined in the Header class. Set maxheaderlen to zero to disable
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
56 header wrapping. The default is 78, as recommended (but not required)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
57 by RFC 2822.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
58 """
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
59 self._fp = outfp
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
60 self._mangle_from_ = mangle_from_
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
61 self._maxheaderlen = maxheaderlen
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
62
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
63 def write(self, s):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
64 # Just delegate to the file object
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
65 self._fp.write(s)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
66
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
67 def flatten(self, msg, unixfrom=False):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
68 """Print the message object tree rooted at msg to the output file
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
69 specified when the Generator instance was created.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
70
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
71 unixfrom is a flag that forces the printing of a Unix From_ delimiter
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
72 before the first object in the message tree. If the original message
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
73 has no From_ delimiter, a `standard' one is crafted. By default, this
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
74 is False to inhibit the printing of any From_ delimiter.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
75
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
76 Note that for subobjects, no From_ line is printed.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
77 """
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
78 if unixfrom:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
79 ufrom = msg.get_unixfrom()
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
80 if not ufrom:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
81 ufrom = 'From nobody ' + time.ctime(time.time())
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
82 print >> self._fp, ufrom
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
83 self._write(msg)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
84
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
85 def clone(self, fp):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
86 """Clone this generator with the exact same options."""
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
87 return self.__class__(fp, self._mangle_from_, self._maxheaderlen)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
88
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
89 #
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
90 # Protected interface - undocumented ;/
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
91 #
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
92
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
93 def _write(self, msg):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
94 # We can't write the headers yet because of the following scenario:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
95 # say a multipart message includes the boundary string somewhere in
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
96 # its body. We'd have to calculate the new boundary /before/ we write
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
97 # the headers so that we can write the correct Content-Type:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
98 # parameter.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
99 #
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
100 # The way we do this, so as to make the _handle_*() methods simpler,
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
101 # is to cache any subpart writes into a StringIO. The we write the
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
102 # headers and the StringIO contents. That way, subpart handlers can
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
103 # Do The Right Thing, and can still modify the Content-Type: header if
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
104 # necessary.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
105 oldfp = self._fp
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
106 try:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
107 self._fp = sfp = StringIO()
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
108 self._dispatch(msg)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
109 finally:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
110 self._fp = oldfp
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
111 # Write the headers. First we see if the message object wants to
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
112 # handle that itself. If not, we'll do it generically.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
113 meth = getattr(msg, '_write_headers', None)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
114 if meth is None:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
115 self._write_headers(msg)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
116 else:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
117 meth(self)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
118 self._fp.write(sfp.getvalue())
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
119
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
120 def _dispatch(self, msg):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
121 # Get the Content-Type: for the message, then try to dispatch to
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
122 # self._handle_<maintype>_<subtype>(). If there's no handler for the
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
123 # full MIME type, then dispatch to self._handle_<maintype>(). If
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
124 # that's missing too, then dispatch to self._writeBody().
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
125 main = msg.get_content_maintype()
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
126 sub = msg.get_content_subtype()
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
127 specific = UNDERSCORE.join((main, sub)).replace('-', '_')
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
128 meth = getattr(self, '_handle_' + specific, None)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
129 if meth is None:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
130 generic = main.replace('-', '_')
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
131 meth = getattr(self, '_handle_' + generic, None)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
132 if meth is None:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
133 meth = self._writeBody
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
134 meth(msg)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
135
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
136 #
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
137 # Default handlers
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
138 #
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
139
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
140 def _write_headers(self, msg):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
141 for h, v in msg.items():
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
142 print >> self._fp, '%s:' % h,
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
143 if self._maxheaderlen == 0:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
144 # Explicit no-wrapping
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
145 print >> self._fp, v
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
146 elif isinstance(v, Header):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
147 # Header instances know what to do
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
148 print >> self._fp, v.encode()
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
149 elif _is8bitstring(v):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
150 # If we have raw 8bit data in a byte string, we have no idea
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
151 # what the encoding is. There is no safe way to split this
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
152 # string. If it's ascii-subset, then we could do a normal
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
153 # ascii split, but if it's multibyte then we could break the
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
154 # string. There's no way to know so the least harm seems to
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
155 # be to not split the string and risk it being too long.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
156 print >> self._fp, v
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
157 else:
52488
5deb27042e5a A fix for issue 1974, inspired by the patch from Andi Albrecht (aalbrecht),
Barry Warsaw <barry@python.org>
parents: 48149
diff changeset
158 # Header's got lots of smarts, so use it. Note that this is
5deb27042e5a A fix for issue 1974, inspired by the patch from Andi Albrecht (aalbrecht),
Barry Warsaw <barry@python.org>
parents: 48149
diff changeset
159 # fundamentally broken though because we lose idempotency when
5deb27042e5a A fix for issue 1974, inspired by the patch from Andi Albrecht (aalbrecht),
Barry Warsaw <barry@python.org>
parents: 48149
diff changeset
160 # the header string is continued with tabs. It will now be
5deb27042e5a A fix for issue 1974, inspired by the patch from Andi Albrecht (aalbrecht),
Barry Warsaw <barry@python.org>
parents: 48149
diff changeset
161 # continued with spaces. This was reversedly broken before we
5deb27042e5a A fix for issue 1974, inspired by the patch from Andi Albrecht (aalbrecht),
Barry Warsaw <barry@python.org>
parents: 48149
diff changeset
162 # fixed bug 1974. Either way, we lose.
37078
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
163 print >> self._fp, Header(
52488
5deb27042e5a A fix for issue 1974, inspired by the patch from Andi Albrecht (aalbrecht),
Barry Warsaw <barry@python.org>
parents: 48149
diff changeset
164 v, maxlinelen=self._maxheaderlen, header_name=h).encode()
37078
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
165 # A blank line always separates headers from body
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
166 print >> self._fp
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
167
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
168 #
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
169 # Handlers for writing types and subtypes
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
170 #
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
171
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
172 def _handle_text(self, msg):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
173 payload = msg.get_payload()
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
174 if payload is None:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
175 return
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
176 if not isinstance(payload, basestring):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
177 raise TypeError('string payload expected: %s' % type(payload))
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
178 if self._mangle_from_:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
179 payload = fcre.sub('>From ', payload)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
180 self._fp.write(payload)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
181
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
182 # Default body handler
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
183 _writeBody = _handle_text
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
184
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
185 def _handle_multipart(self, msg):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
186 # The trick here is to write out each part separately, merge them all
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
187 # together, and then make sure that the boundary we've chosen isn't
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
188 # present in the payload.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
189 msgtexts = []
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
190 subparts = msg.get_payload()
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
191 if subparts is None:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
192 subparts = []
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
193 elif isinstance(subparts, basestring):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
194 # e.g. a non-strict parse of a message with no starting boundary.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
195 self._fp.write(subparts)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
196 return
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
197 elif not isinstance(subparts, list):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
198 # Scalar payload
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
199 subparts = [subparts]
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
200 for part in subparts:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
201 s = StringIO()
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
202 g = self.clone(s)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
203 g.flatten(part, unixfrom=False)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
204 msgtexts.append(s.getvalue())
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
205 # BAW: What about boundaries that are wrapped in double-quotes?
66857
a91b3168fce2 Merged revisions 87191 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 66760
diff changeset
206 boundary = msg.get_boundary()
a91b3168fce2 Merged revisions 87191 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 66760
diff changeset
207 if not boundary:
a91b3168fce2 Merged revisions 87191 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 66760
diff changeset
208 # Create a boundary that doesn't appear in any of the
a91b3168fce2 Merged revisions 87191 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 66760
diff changeset
209 # message texts.
a91b3168fce2 Merged revisions 87191 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 66760
diff changeset
210 alltext = NL.join(msgtexts)
67063
564a41666ef6 Merged revisions 87415 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 66857
diff changeset
211 boundary = _make_boundary(alltext)
37078
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
212 msg.set_boundary(boundary)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
213 # If there's a preamble, write it out, with a trailing CRLF
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
214 if msg.preamble is not None:
78247
9f500171c592 #15232: correctly mangle From lines in MIME preamble and epilogue
R David Murray <rdmurray@bitdance.com>
parents: 68256
diff changeset
215 if self._mangle_from_:
9f500171c592 #15232: correctly mangle From lines in MIME preamble and epilogue
R David Murray <rdmurray@bitdance.com>
parents: 68256
diff changeset
216 preamble = fcre.sub('>From ', msg.preamble)
9f500171c592 #15232: correctly mangle From lines in MIME preamble and epilogue
R David Murray <rdmurray@bitdance.com>
parents: 68256
diff changeset
217 else:
9f500171c592 #15232: correctly mangle From lines in MIME preamble and epilogue
R David Murray <rdmurray@bitdance.com>
parents: 68256
diff changeset
218 preamble = msg.preamble
9f500171c592 #15232: correctly mangle From lines in MIME preamble and epilogue
R David Murray <rdmurray@bitdance.com>
parents: 68256
diff changeset
219 print >> self._fp, preamble
37078
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
220 # dash-boundary transport-padding CRLF
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
221 print >> self._fp, '--' + boundary
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
222 # body-part
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
223 if msgtexts:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
224 self._fp.write(msgtexts.pop(0))
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
225 # *encapsulation
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
226 # --> delimiter transport-padding
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
227 # --> CRLF body-part
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
228 for body_part in msgtexts:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
229 # delimiter transport-padding CRLF
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
230 print >> self._fp, '\n--' + boundary
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
231 # body-part
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
232 self._fp.write(body_part)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
233 # close-delimiter transport-padding
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
234 self._fp.write('\n--' + boundary + '--')
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
235 if msg.epilogue is not None:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
236 print >> self._fp
78247
9f500171c592 #15232: correctly mangle From lines in MIME preamble and epilogue
R David Murray <rdmurray@bitdance.com>
parents: 68256
diff changeset
237 if self._mangle_from_:
9f500171c592 #15232: correctly mangle From lines in MIME preamble and epilogue
R David Murray <rdmurray@bitdance.com>
parents: 68256
diff changeset
238 epilogue = fcre.sub('>From ', msg.epilogue)
9f500171c592 #15232: correctly mangle From lines in MIME preamble and epilogue
R David Murray <rdmurray@bitdance.com>
parents: 68256
diff changeset
239 else:
9f500171c592 #15232: correctly mangle From lines in MIME preamble and epilogue
R David Murray <rdmurray@bitdance.com>
parents: 68256
diff changeset
240 epilogue = msg.epilogue
9f500171c592 #15232: correctly mangle From lines in MIME preamble and epilogue
R David Murray <rdmurray@bitdance.com>
parents: 68256
diff changeset
241 self._fp.write(epilogue)
37078
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
242
58352
0895040adeff Merged revisions 77517,77525 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 48149
diff changeset
243 def _handle_multipart_signed(self, msg):
0895040adeff Merged revisions 77517,77525 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 48149
diff changeset
244 # The contents of signed parts has to stay unmodified in order to keep
0895040adeff Merged revisions 77517,77525 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 48149
diff changeset
245 # the signature intact per RFC1847 2.1, so we disable header wrapping.
0895040adeff Merged revisions 77517,77525 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 48149
diff changeset
246 # RDM: This isn't enough to completely preserve the part, but it helps.
0895040adeff Merged revisions 77517,77525 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 48149
diff changeset
247 old_maxheaderlen = self._maxheaderlen
0895040adeff Merged revisions 77517,77525 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 48149
diff changeset
248 try:
0895040adeff Merged revisions 77517,77525 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 48149
diff changeset
249 self._maxheaderlen = 0
0895040adeff Merged revisions 77517,77525 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 48149
diff changeset
250 self._handle_multipart(msg)
0895040adeff Merged revisions 77517,77525 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 48149
diff changeset
251 finally:
0895040adeff Merged revisions 77517,77525 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 48149
diff changeset
252 self._maxheaderlen = old_maxheaderlen
0895040adeff Merged revisions 77517,77525 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 48149
diff changeset
253
37078
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
254 def _handle_message_delivery_status(self, msg):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
255 # We can't just write the headers directly to self's file object
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
256 # because this will leave an extra newline between the last header
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
257 # block and the boundary. Sigh.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
258 blocks = []
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
259 for part in msg.get_payload():
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
260 s = StringIO()
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
261 g = self.clone(s)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
262 g.flatten(part, unixfrom=False)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
263 text = s.getvalue()
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
264 lines = text.split('\n')
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
265 # Strip off the unnecessary trailing empty line
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
266 if lines and lines[-1] == '':
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
267 blocks.append(NL.join(lines[:-1]))
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
268 else:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
269 blocks.append(text)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
270 # Now join all the blocks with an empty line. This has the lovely
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
271 # effect of separating each block with an empty line, but not adding
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
272 # an extra one after the last one.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
273 self._fp.write(NL.join(blocks))
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
274
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
275 def _handle_message(self, msg):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
276 s = StringIO()
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
277 g = self.clone(s)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
278 # The payload of a message/rfc822 part should be a multipart sequence
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
279 # of length 1. The zeroth element of the list should be the Message
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
280 # object for the subpart. Extract that object, stringify it, and
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
281 # write it out.
58974
d3ae041e7b8c Merged revisions 78274 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 58352
diff changeset
282 # Except, it turns out, when it's a string instead, which happens when
d3ae041e7b8c Merged revisions 78274 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 58352
diff changeset
283 # and only when HeaderParser is used on a message of mime type
d3ae041e7b8c Merged revisions 78274 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 58352
diff changeset
284 # message/rfc822. Such messages are generated by, for example,
d3ae041e7b8c Merged revisions 78274 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 58352
diff changeset
285 # Groupwise when forwarding unadorned messages. (Issue 7970.) So
d3ae041e7b8c Merged revisions 78274 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 58352
diff changeset
286 # in that case we just emit the string body.
d3ae041e7b8c Merged revisions 78274 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 58352
diff changeset
287 payload = msg.get_payload()
d3ae041e7b8c Merged revisions 78274 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 58352
diff changeset
288 if isinstance(payload, list):
d3ae041e7b8c Merged revisions 78274 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 58352
diff changeset
289 g.flatten(msg.get_payload(0), unixfrom=False)
d3ae041e7b8c Merged revisions 78274 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 58352
diff changeset
290 payload = s.getvalue()
d3ae041e7b8c Merged revisions 78274 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 58352
diff changeset
291 self._fp.write(payload)
37078
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
292
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
293
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
294
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
295 _FMT = '[Non-text (%(type)s) part of message omitted, filename %(filename)s]'
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
296
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
297 class DecodedGenerator(Generator):
66760
26c6593571f1 Merged revisions 85146 via svnmerge from
R. David Murray <rdmurray@bitdance.com>
parents: 58973
diff changeset
298 """Generates a text representation of a message.
37078
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
299
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
300 Like the Generator base class, except that non-text parts are substituted
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
301 with a format string representing the part.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
302 """
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
303 def __init__(self, outfp, mangle_from_=True, maxheaderlen=78, fmt=None):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
304 """Like Generator.__init__() except that an additional optional
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
305 argument is allowed.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
306
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
307 Walks through all subparts of a message. If the subpart is of main
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
308 type `text', then it prints the decoded payload of the subpart.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
309
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
310 Otherwise, fmt is a format string that is used instead of the message
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
311 payload. fmt is expanded with the following keywords (in
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
312 %(keyword)s format):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
313
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
314 type : Full MIME type of the non-text part
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
315 maintype : Main MIME type of the non-text part
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
316 subtype : Sub-MIME type of the non-text part
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
317 filename : Filename of the non-text part
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
318 description: Description associated with the non-text part
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
319 encoding : Content transfer encoding of the non-text part
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
320
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
321 The default value for fmt is None, meaning
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
322
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
323 [Non-text (%(type)s) part of message omitted, filename %(filename)s]
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
324 """
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
325 Generator.__init__(self, outfp, mangle_from_, maxheaderlen)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
326 if fmt is None:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
327 self._fmt = _FMT
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
328 else:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
329 self._fmt = fmt
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
330
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
331 def _dispatch(self, msg):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
332 for part in msg.walk():
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
333 maintype = part.get_content_maintype()
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
334 if maintype == 'text':
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
335 print >> self, part.get_payload(decode=True)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
336 elif maintype == 'multipart':
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
337 # Just skip this
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
338 pass
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
339 else:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
340 print >> self, self._fmt % {
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
341 'type' : part.get_content_type(),
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
342 'maintype' : part.get_content_maintype(),
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
343 'subtype' : part.get_content_subtype(),
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
344 'filename' : part.get_filename('[no filename]'),
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
345 'description': part.get('Content-Description',
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
346 '[no description]'),
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
347 'encoding' : part.get('Content-Transfer-Encoding',
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
348 '[no encoding]'),
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
349 }
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
350
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
351
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
352
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
353 # Helper
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
354 _width = len(repr(sys.maxint-1))
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
355 _fmt = '%%0%dd' % _width
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
356
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
357 def _make_boundary(text=None):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
358 # Craft a random boundary. If text is given, ensure that the chosen
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
359 # boundary doesn't appear in the text.
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
360 token = random.randrange(sys.maxint)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
361 boundary = ('=' * 15) + (_fmt % token) + '=='
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
362 if text is None:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
363 return boundary
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
364 b = boundary
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
365 counter = 0
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
366 while True:
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
367 cre = re.compile('^--' + re.escape(b) + '(--)?$', re.MULTILINE)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
368 if not cre.search(text):
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
369 break
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
370 b = boundary + '.' + str(counter)
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
371 counter += 1
3f90a93ff5d0 Merge email package 4.0 from the sandbox, including documentation, test cases,
Barry Warsaw <barry@python.org>
parents:
diff changeset
372 return b