1 """Various tools used by MIME-reading or MIME-writing programs."""
8 __all__
= ["Message","choose_boundary","encode","decode","copyliteral",
11 class Message(rfc822
.Message
):
12 """A derived class of rfc822.Message that knows about MIME headers and
13 contains some hooks for decoding encoded and multipart messages."""
15 def __init__(self
, fp
, seekable
= 1):
16 rfc822
.Message
.__init
__(self
, fp
, seekable
)
17 self
.encodingheader
= \
18 self
.getheader('content-transfer-encoding')
20 self
.getheader('content-type')
30 self
.plisttext
= str[i
:]
34 fields
= str.split('/')
35 for i
in range(len(fields
)):
36 fields
[i
] = fields
[i
].strip().lower()
37 self
.type = '/'.join(fields
)
38 self
.maintype
= fields
[0]
39 self
.subtype
= '/'.join(fields
[1:])
47 # XXX Should parse quotes!
54 f
= f
[:i
].strip().lower() + \
56 self
.plist
.append(f
.strip())
62 def getparam(self
, name
):
63 name
= name
.lower() + '='
67 return rfc822
.unquote(p
[n
:])
70 def getparamnames(self
):
75 result
.append(p
[:i
].lower())
78 def getencoding(self
):
79 if self
.encodingheader
is None:
81 return self
.encodingheader
.lower()
86 def getmaintype(self
):
101 def choose_boundary():
102 """Return a random string usable as a multipart boundary.
103 The method used is so that it is *very* unlikely that the same
104 string of characters will every occur again in the Universe,
105 so the caller needn't check the data it is packing for the
106 occurrence of the boundary.
108 The boundary contains dots so you have to quote it in the header."""
116 hostid
= socket
.gethostbyname(socket
.gethostname())
125 _prefix
= hostid
+ '.' + uid
+ '.' + pid
126 timestamp
= '%.3f' % time
.time()
127 seed
= `random
.randint(0, 32767)`
128 return _prefix
+ '.' + timestamp
+ '.' + seed
131 # Subroutines for decoding some common content-transfer-types
133 def decode(input, output
, encoding
):
134 """Decode common content-transfer-encodings (base64, quopri, uuencode)."""
135 if encoding
== 'base64':
137 return base64
.decode(input, output
)
138 if encoding
== 'quoted-printable':
140 return quopri
.decode(input, output
)
141 if encoding
in ('uuencode', 'x-uuencode', 'uue', 'x-uue'):
143 return uu
.decode(input, output
)
144 if encoding
in ('7bit', '8bit'):
145 return output
.write(input.read())
146 if decodetab
.has_key(encoding
):
147 pipethrough(input, decodetab
[encoding
], output
)
150 'unknown Content-Transfer-Encoding: %s' % encoding
152 def encode(input, output
, encoding
):
153 """Encode common content-transfer-encodings (base64, quopri, uuencode)."""
154 if encoding
== 'base64':
156 return base64
.encode(input, output
)
157 if encoding
== 'quoted-printable':
159 return quopri
.encode(input, output
, 0)
160 if encoding
in ('uuencode', 'x-uuencode', 'uue', 'x-uue'):
162 return uu
.encode(input, output
)
163 if encoding
in ('7bit', '8bit'):
164 return output
.write(input.read())
165 if encodetab
.has_key(encoding
):
166 pipethrough(input, encodetab
[encoding
], output
)
169 'unknown Content-Transfer-Encoding: %s' % encoding
171 # The following is no longer used for standard encodings
173 # XXX This requires that uudecode and mmencode are in $PATH
177 sed "s%^begin [0-7][0-7]* .*%begin 600 $TEMP%" | uudecode
183 'uuencode': uudecode_pipe
,
184 'x-uuencode': uudecode_pipe
,
185 'uue': uudecode_pipe
,
186 'x-uue': uudecode_pipe
,
187 'quoted-printable': 'mmencode -u -q',
188 'base64': 'mmencode -u -b',
192 'x-uuencode': 'uuencode tempfile',
193 'uuencode': 'uuencode tempfile',
194 'x-uue': 'uuencode tempfile',
195 'uue': 'uuencode tempfile',
196 'quoted-printable': 'mmencode -q',
197 'base64': 'mmencode -b',
200 def pipeto(input, command
):
201 pipe
= os
.popen(command
, 'w')
202 copyliteral(input, pipe
)
205 def pipethrough(input, command
, output
):
206 tempname
= tempfile
.mktemp()
207 temp
= open(tempname
, 'w')
208 copyliteral(input, temp
)
210 pipe
= os
.popen(command
+ ' <' + tempname
, 'r')
211 copybinary(pipe
, output
)
215 def copyliteral(input, output
):
217 line
= input.readline()
221 def copybinary(input, output
):
224 line
= input.read(BUFSIZE
)