1 """Various tools used by MIME-reading or MIME-writing programs."""
6 from test
.test_support
import catch_warning
7 from warnings
import filterwarnings
8 with
catch_warning(record
=False):
9 filterwarnings("ignore", ".*rfc822 has been removed", DeprecationWarning)
12 from warnings
import warnpy3k
13 warnpy3k("in 3.x, mimetools has been removed in favor of the email package",
16 __all__
= ["Message","choose_boundary","encode","decode","copyliteral",
19 class Message(rfc822
.Message
):
20 """A derived class of rfc822.Message that knows about MIME headers and
21 contains some hooks for decoding encoded and multipart messages."""
23 def __init__(self
, fp
, seekable
= 1):
24 rfc822
.Message
.__init
__(self
, fp
, seekable
)
25 self
.encodingheader
= \
26 self
.getheader('content-transfer-encoding')
28 self
.getheader('content-type')
38 self
.plisttext
= str[i
:]
42 fields
= str.split('/')
43 for i
in range(len(fields
)):
44 fields
[i
] = fields
[i
].strip().lower()
45 self
.type = '/'.join(fields
)
46 self
.maintype
= fields
[0]
47 self
.subtype
= '/'.join(fields
[1:])
55 # XXX Should parse quotes!
62 f
= f
[:i
].strip().lower() + \
64 self
.plist
.append(f
.strip())
70 def getparam(self
, name
):
71 name
= name
.lower() + '='
75 return rfc822
.unquote(p
[n
:])
78 def getparamnames(self
):
83 result
.append(p
[:i
].lower())
86 def getencoding(self
):
87 if self
.encodingheader
is None:
89 return self
.encodingheader
.lower()
94 def getmaintype(self
):
109 import dummy_thread
as thread
110 _counter_lock
= thread
.allocate_lock()
114 def _get_next_counter():
116 _counter_lock
.acquire()
119 _counter_lock
.release()
124 def choose_boundary():
125 """Return a string usable as a multipart boundary.
127 The string chosen is unique within a single program run, and
128 incorporates the user id (if available), process id (if available),
129 and current time. So it's very unlikely the returned string appears
130 in message text, but there's no guarantee.
132 The boundary contains dots so you have to quote it in the header."""
139 hostid
= socket
.gethostbyname(socket
.gethostname())
140 except socket
.gaierror
:
143 uid
= repr(os
.getuid())
144 except AttributeError:
147 pid
= repr(os
.getpid())
148 except AttributeError:
150 _prefix
= hostid
+ '.' + uid
+ '.' + pid
151 return "%s.%.3f.%d" % (_prefix
, time
.time(), _get_next_counter())
154 # Subroutines for decoding some common content-transfer-types
156 def decode(input, output
, encoding
):
157 """Decode common content-transfer-encodings (base64, quopri, uuencode)."""
158 if encoding
== 'base64':
160 return base64
.decode(input, output
)
161 if encoding
== 'quoted-printable':
163 return quopri
.decode(input, output
)
164 if encoding
in ('uuencode', 'x-uuencode', 'uue', 'x-uue'):
166 return uu
.decode(input, output
)
167 if encoding
in ('7bit', '8bit'):
168 return output
.write(input.read())
169 if encoding
in decodetab
:
170 pipethrough(input, decodetab
[encoding
], output
)
173 'unknown Content-Transfer-Encoding: %s' % encoding
175 def encode(input, output
, encoding
):
176 """Encode common content-transfer-encodings (base64, quopri, uuencode)."""
177 if encoding
== 'base64':
179 return base64
.encode(input, output
)
180 if encoding
== 'quoted-printable':
182 return quopri
.encode(input, output
, 0)
183 if encoding
in ('uuencode', 'x-uuencode', 'uue', 'x-uue'):
185 return uu
.encode(input, output
)
186 if encoding
in ('7bit', '8bit'):
187 return output
.write(input.read())
188 if encoding
in encodetab
:
189 pipethrough(input, encodetab
[encoding
], output
)
192 'unknown Content-Transfer-Encoding: %s' % encoding
194 # The following is no longer used for standard encodings
196 # XXX This requires that uudecode and mmencode are in $PATH
200 sed "s%^begin [0-7][0-7]* .*%begin 600 $TEMP%" | uudecode
206 'uuencode': uudecode_pipe
,
207 'x-uuencode': uudecode_pipe
,
208 'uue': uudecode_pipe
,
209 'x-uue': uudecode_pipe
,
210 'quoted-printable': 'mmencode -u -q',
211 'base64': 'mmencode -u -b',
215 'x-uuencode': 'uuencode tempfile',
216 'uuencode': 'uuencode tempfile',
217 'x-uue': 'uuencode tempfile',
218 'uue': 'uuencode tempfile',
219 'quoted-printable': 'mmencode -q',
220 'base64': 'mmencode -b',
223 def pipeto(input, command
):
224 pipe
= os
.popen(command
, 'w')
225 copyliteral(input, pipe
)
228 def pipethrough(input, command
, output
):
229 (fd
, tempname
) = tempfile
.mkstemp()
230 temp
= os
.fdopen(fd
, 'w')
231 copyliteral(input, temp
)
233 pipe
= os
.popen(command
+ ' <' + tempname
, 'r')
234 copybinary(pipe
, output
)
238 def copyliteral(input, output
):
240 line
= input.readline()
244 def copybinary(input, output
):
247 line
= input.read(BUFSIZE
)