#! /usr/bin/env python
"""Decode MIME message"""
-from mimedecode_version import __version__, __author__, __copyright__, __license__
-
import sys, os
-import email
+from mimedecode_version import __version__, \
+ __author__, __copyright__, __license__
me = os.path.basename(sys.argv[0])
output("\n") # End of headers
-def recode(s, charset):
- return unicode(s, charset, "replace").encode(g.default_encoding, "replace")
-
def recode_if_needed(s, charset):
if charset and charset.lower() <> g.default_encoding:
- s = recode(s, charset)
+ s = unicode(s, charset, "replace").encode(g.default_encoding, "replace")
return s
set_header(msg, header, new_value)
-def _decode_header_param(s):
- return recode_if_needed(s[2], s[0])
-
def decode_header_param(msg, header, param):
"Decode mail header's parameter (if exists) and put it back, if it was encoded"
value = msg.get_param(param, header=header)
if value:
if isinstance(value, tuple):
- new_value = _decode_header_param(value)
+ new_value = recode_if_needed(value[2], value[0])
else:
new_value = _decode_header(value)
if new_value <> value: # do not bother to touch msg if not changed
return s
+mimetypes = None
+
+def _guess_extension(ctype):
+ global mimetypes
+ if mimetypes is None:
+ import mimetypes
+ mimetypes.init()
+ user_mime_type = os.path.expanduser('~/.mime.types')
+ if os.path.exists(user_mime_type):
+ mimetypes._db.read(user_mime_type)
+ return mimetypes.guess_extension(ctype)
+
def _save_message(msg, outstring, save_headers=False, save_body=False):
for header, param in (
("Content-Disposition", "filename"),
):
fname = msg.get_param(param, header=header)
if fname:
+ if isinstance(fname, tuple):
+ fname = fname[2] # Do not recode if it isn't recoded yet
+ try:
+ for forbidden in chr(0), '/', '\\':
+ if forbidden in fname:
+ raise ValueError
+ except ValueError:
+ continue
fname = '-' + fname
break
else:
fname = ''
g.save_counter += 1
fname = str(g.save_counter) + fname
+ if '.' not in fname:
+ ext = _guess_extension(msg.get_content_type())
+ if ext: fname += ext
global output
save_output = output
- outfile = open(os.path.join(g.destination_dir, fname), 'w')
+ outfile = open_output_file(fname)
output = outfile.write
if save_headers:
output_headers(msg)
ctype = msg.get_content_type()
if ctype:
masks.append(ctype)
- mtype = msg.get_content_maintype()
- if mtype:
+ mtype = ctype.split('/')[0]
masks.append(mtype + '/*')
masks.append('*/*')
left_binary = False
for content_type in masks:
- if content_type in g.binary_mask:
+ if content_type in g.totext_mask or \
+ content_type in g.decoded_binary_mask:
+ break
+ elif content_type in g.binary_mask:
left_binary = True
break
output("\nMessage body of type %s skipped.\n" % ctype)
break
elif content_type in g.error_mask:
- raise ValueError, "content type %s prohibited" % ctype
+ break
else:
# Neither content type nor masks were listed - decode by default
outstring = totext(msg, outstring)
elif content_type in g.save_message_mask:
_save_message(msg, outstring, save_headers=True, save_body=True)
+ for content_type in masks:
+ if content_type in g.error_mask:
+ raise ValueError, "content type %s prohibited" % ctype
+
def decode_multipart(msg):
"Decode multipart"
output(msg.as_string())
+def open_output_file(filename):
+ fullpath = os.path.abspath(os.path.join(g.destination_dir, filename))
+ full_dir = os.path.dirname(fullpath)
+ create = not os.path.isdir(full_dir)
+ if create:
+ os.makedirs(full_dir)
+ try:
+ return open(fullpath, 'w')
+ except:
+ if create:
+ os.removedirs(full_dir)
+
+
class GlobalOptions:
from m_lib.defenc import default_encoding
recode_charset = 1 # recode charset of message body
g.input_filename = '-'
infile = sys.stdin
if g.output_filename:
- outfile = open(os.path.join(g.destination_dir, g.output_filename), 'w')
+ outfile = open_output_file(g.output_filename)
else:
g.output_filename = '-'
outfile = sys.stdout
infile = open(arguments[0], 'r')
if la == 1:
if g.output_filename:
- outfile = open(os.path.join(g.destination_dir, g.output_filename), 'w')
+ outfile = open_output_file(g.output_filename)
else:
g.output_filename = '-'
outfile = sys.stdout
outfile = sys.stdout
else:
g.output_filename = arguments[1]
- outfile = open(os.path.join(g.destination_dir, g.output_filename), 'w')
+ outfile = open_output_file(g.output_filename)
else:
usage(1, 'Too many arguments')
g.outfile = outfile
output = outfile.write
+ import email
msg = email.message_from_file(infile)
for header, value in g.set_header_value:
- msg[header] = value
+ set_header(msg, header, value)
for header, param, value in g.set_header_param:
if header in msg: