1 """Various tools used by MIME-reading or MIME-writing programs."""
10 class Message(rfc822
.Message
):
11 """A derived class of rfc822.Message that knows about MIME headers and
12 contains some hooks for decoding encoded and multipart messages."""
14 def __init__(self
, fp
, seekable
= 1):
15 rfc822
.Message
.__init
__(self
, fp
, seekable
)
16 self
.encodingheader
= \
17 self
.getheader('content-transfer-encoding')
19 self
.getheader('content-type')
28 i
= string
.index(str, ';')
29 self
.plisttext
= str[i
:]
33 fields
= string
.splitfields(str, '/')
34 for i
in range(len(fields
)):
35 fields
[i
] = string
.lower(string
.strip(fields
[i
]))
36 self
.type = string
.joinfields(fields
, '/')
37 self
.maintype
= fields
[0]
38 self
.subtype
= string
.joinfields(fields
[1:], '/')
46 # XXX Should parse quotes!
47 end
= string
.index(str, ';')
52 i
= string
.index(f
, '=')
53 f
= string
.lower(string
.strip(f
[:i
])) + \
54 '=' + string
.strip(f
[i
+1:])
55 self
.plist
.append(string
.strip(f
))
61 def getparam(self
, name
):
62 name
= string
.lower(name
) + '='
66 return rfc822
.unquote(p
[n
:])
69 def getparamnames(self
):
72 i
= string
.find(p
, '=')
74 result
.append(string
.lower(p
[:i
]))
77 def getencoding(self
):
78 if self
.encodingheader
== None:
80 return string
.lower(self
.encodingheader
)
85 def getmaintype(self
):
100 def choose_boundary():
101 """Return a random string usable as a multipart boundary.
102 The method used is so that it is *very* unlikely that the same
103 string of characters will every occur again in the Universe,
104 so the caller needn't check the data it is packing for the
105 occurrence of the boundary.
107 The boundary contains dots so you have to quote it in the header."""
115 hostid
= socket
.gethostbyname(socket
.gethostname())
124 _prefix
= hostid
+ '.' + uid
+ '.' + pid
125 timestamp
= '%.3f' % time
.time()
126 seed
= `random
.randint(0, 32767)`
127 return _prefix
+ '.' + timestamp
+ '.' + seed
130 # Subroutines for decoding some common content-transfer-types
132 def decode(input, output
, encoding
):
133 """Decode common content-transfer-encodings (base64, quopri, uuencode)."""
134 if encoding
== 'base64':
136 return base64
.decode(input, output
)
137 if encoding
== 'quoted-printable':
139 return quopri
.decode(input, output
)
140 if encoding
in ('uuencode', 'x-uuencode', 'uue', 'x-uue'):
142 return uu
.decode(input, output
)
143 if encoding
in ('7bit', '8bit'):
144 output
.write(input.read())
145 if decodetab
.has_key(encoding
):
146 pipethrough(input, decodetab
[encoding
], output
)
149 'unknown Content-Transfer-Encoding: %s' % encoding
151 def encode(input, output
, encoding
):
152 """Encode common content-transfer-encodings (base64, quopri, uuencode)."""
153 if encoding
== 'base64':
155 return base64
.encode(input, output
)
156 if encoding
== 'quoted-printable':
158 return quopri
.encode(input, output
, 0)
159 if encoding
in ('uuencode', 'x-uuencode', 'uue', 'x-uue'):
161 return uu
.encode(input, output
)
162 if encoding
in ('7bit', '8bit'):
163 output
.write(input.read())
164 if encodetab
.has_key(encoding
):
165 pipethrough(input, encodetab
[encoding
], output
)
168 'unknown Content-Transfer-Encoding: %s' % encoding
170 # The following is no longer used for standard encodings
172 # XXX This requires that uudecode and mmencode are in $PATH
176 sed "s%^begin [0-7][0-7]* .*%begin 600 $TEMP%" | uudecode
182 'uuencode': uudecode_pipe
,
183 'x-uuencode': uudecode_pipe
,
184 'uue': uudecode_pipe
,
185 'x-uue': uudecode_pipe
,
186 'quoted-printable': 'mmencode -u -q',
187 'base64': 'mmencode -u -b',
191 'x-uuencode': 'uuencode tempfile',
192 'uuencode': 'uuencode tempfile',
193 'x-uue': 'uuencode tempfile',
194 'uue': 'uuencode tempfile',
195 'quoted-printable': 'mmencode -q',
196 'base64': 'mmencode -b',
199 def pipeto(input, command
):
200 pipe
= os
.popen(command
, 'w')
201 copyliteral(input, pipe
)
204 def pipethrough(input, command
, output
):
205 tempname
= tempfile
.mktemp()
207 temp
= open(tempname
, 'w')
209 print '*** Cannot create temp file', `tempname`
211 copyliteral(input, temp
)
213 pipe
= os
.popen(command
+ ' <' + tempname
, 'r')
214 copybinary(pipe
, output
)
218 def copyliteral(input, output
):
220 line
= input.readline()
224 def copybinary(input, output
):
227 line
= input.read(BUFSIZE
)