X-Git-Url: https://git.phdru.name/?a=blobdiff_plain;f=mimedecode.py;h=9019669f150b3ed39c84eeb4f55906e6d3b1e8be;hb=b1853fe16abc5f255bb9cce7ce36d68dfb5e4e1a;hp=0ec5e799fd22ce1ceb6071706729ea8f082b7f8a;hpb=dbc1b161c526976b322f2fa9a7d2a75e3613485e;p=mimedecode.git diff --git a/mimedecode.py b/mimedecode.py index 0ec5e79..9019669 100755 --- a/mimedecode.py +++ b/mimedecode.py @@ -1,14 +1,16 @@ #! /usr/bin/env python """Decode MIME message""" -import sys, os +import os import subprocess -from mimedecode_version import __version__, \ - __author__, __copyright__, __license__ +import sys + +from mimedecode_version import __version__, __copyright__ + if sys.version_info[0] >= 3: # Replace email.message._formatparam with _formatparam from Python 2.7 # to avoid re-encoding non-ascii params. - import formatparam_27 + import formatparam_27 # noqa: F401: Imported for its side effect me = os.path.basename(sys.argv[0]) @@ -17,14 +19,15 @@ def version(exit=1): sys.stdout.write("""\ Broytman mimedecode.py version %s, %s """ % (__version__, __copyright__)) - if exit: sys.exit(0) + if exit: + sys.exit(0) def usage(code=0, errormsg=''): version(0) sys.stdout.write("""\ Usage: %s [-h|--help] [-V|--version] [-cCDP] [-H|--host=hostname] [-f charset] [-d header1[,h2,...]|*[,-h1,...]] [-p header1[,h2,h3,...]:param1[,p2,p3,...]] [-r header1[,h2,...]|*[,-h1,...]] [-R header1[,h2,h3,...]:param1[,p2,p3,...]] [--set-header header:value] [--set-param header:param=value] [-Bbeit mask] [--save-headers|body|message mask] [-O dest_dir] [-o output_file] [input_file [output_file]] -""" % me) +""" % me) # noqa: E501 if errormsg: sys.stderr.write(errormsg + os.linesep) sys.exit(code) @@ -93,8 +96,11 @@ def decode_header(msg, header): def decode_header_param(msg, header, param): - "Decode mail header's parameter (if exists) and put it back, if it was encoded" + """Decode mail header's parameter + Decode mail header's parameter (if exists) + and put it back if it was encoded. + """ if header in msg: value = msg.get_param(param, header=header) if value: @@ -161,17 +167,20 @@ def decode_headers(msg): for header_list, param_list in g.remove_headers_params: header_list = header_list.split(',') param_list = param_list.split(',') - remove_all_params = param_list[0] == '*' # Remove all params except listed + # Remove all params except listed. + remove_all_params = param_list[0] == '*' if remove_all_params: param_list = _get_exceptions(param_list) if header_list[0] == '*': # Remove for all headers except listed header_list = _get_exceptions(header_list) for header in msg.keys(): if header.lower() not in header_list: - _remove_headers_params(msg, header, remove_all_params, param_list) + _remove_headers_params( + msg, header, remove_all_params, param_list) else: # Decode for listed headers for header in header_list: - _remove_headers_params(msg, header, remove_all_params, param_list) + _remove_headers_params( + msg, header, remove_all_params, param_list) for header_list in g.decode_headers: header_list = header_list.split(',') @@ -187,17 +196,20 @@ def decode_headers(msg): for header_list, param_list in g.decode_header_params: header_list = header_list.split(',') param_list = param_list.split(',') - decode_all_params = param_list[0] == '*' # Decode all params except listed + # Decode all params except listed. + decode_all_params = param_list[0] == '*' if decode_all_params: param_list = _get_exceptions(param_list) if header_list[0] == '*': # Decode for all headers except listed header_list = _get_exceptions(header_list) for header in msg.keys(): if header.lower() not in header_list: - _decode_headers_params(msg, header, decode_all_params, param_list) + _decode_headers_params( + msg, header, decode_all_params, param_list) else: # Decode for listed headers for header in header_list: - _decode_headers_params(msg, header, decode_all_params, param_list) + _decode_headers_params( + msg, header, decode_all_params, param_list) def set_header(msg, header, value): @@ -222,7 +234,8 @@ caps = None # Globally stored mailcap database; initialized only if needed def decode_body(msg, s): "Decode body to plain text using first copiousoutput filter from mailcap" - import mailcap, tempfile + import mailcap + import tempfile global caps if caps is None: @@ -267,9 +280,13 @@ def decode_body(msg, s): if charset and not isinstance(s, bytes): s = s.encode(charset, "replace") set_content_type(msg, "text/plain") - msg["X-MIME-Autoconverted"] = "from %s to text/plain by %s id %s" % (content_type, g.host_name, command.split()[0]) + msg["X-MIME-Autoconverted"] = \ + "from %s to text/plain by %s id %s" \ + % (content_type, g.host_name, command.split()[0]) else: - msg["X-MIME-Autoconverted"] = "failed conversion from %s to text/plain by %s id %s" % (content_type, g.host_name, command.split()[0]) + msg["X-MIME-Autoconverted"] = \ + "failed conversion from %s to text/plain by %s id %s" \ + % (content_type, g.host_name, command.split()[0]) os.remove(filename) return s @@ -283,7 +300,9 @@ def recode_charset(msg, s): s = recode_if_needed(s, charset) content_type = msg.get_content_type() set_content_type(msg, content_type, g.default_encoding) - msg["X-MIME-Autoconverted"] = "from %s to %s by %s id %s" % (save_charset, g.default_encoding, g.host_name, me) + msg["X-MIME-Autoconverted"] = \ + "from %s to %s by %s id %s" \ + % (save_charset, g.default_encoding, g.host_name, me) return s @@ -337,15 +356,18 @@ def _save_message(msg, outstring, save_headers=False, save_body=False): fname = str(g.save_counter) + fname if '.' not in fname: ext = _guess_extension(msg.get_content_type()) - if ext: fname += ext + if ext: + fname += ext global output save_output = output outfile = open_output_file(fname) + def _output_bytes(s): if not isinstance(s, bytes): s = s.encode(g.default_encoding, "replace") outfile.write(s) + output = _output_bytes if save_headers: output_headers(msg) @@ -386,7 +408,8 @@ def decode_part(msg): else: # Decode from transfer ecoding to text or binary form outstring = msg.get_payload(decode=1) set_header(msg, "Content-Transfer-Encoding", "8bit") - msg["X-MIME-Autoconverted"] = "from %s to 8bit by %s id %s" % (encoding, g.host_name, me) + msg["X-MIME-Autoconverted"] = \ + "from %s to 8bit by %s id %s" % (encoding, g.host_name, me) for content_type in masks: if content_type in g.totext_mask: @@ -399,7 +422,8 @@ def decode_part(msg): break elif content_type in g.ignore_mask: output_headers(msg) - output("%sMessage body of type %s skipped.%s" % (os.linesep, ctype, os.linesep)) + output("%sMessage body of type %s skipped.%s" + % (os.linesep, ctype, os.linesep)) break elif content_type in g.error_mask: break @@ -439,7 +463,8 @@ def decode_multipart(msg): return elif content_type in g.ignore_mask: output_headers(msg) - output("%sMessage body of type %s skipped.%s" % (os.linesep, ctype, os.linesep)) + output("%sMessage body of type %s skipped.%s" + % (os.linesep, ctype, os.linesep)) if boundary: output("%s--%s--%s" % (os.linesep, boundary, os.linesep)) return @@ -476,8 +501,10 @@ def decode_multipart(msg): output_headers(msg) - if msg.preamble: # Preserve the first part, it is probably not a RFC822-message - output(msg.preamble) # Usually it is just a few lines of text (MIME warning) + # Preserve the first part, it is probably not a RFC822-message. + if msg.preamble: + # Usually it is just a few lines of text (MIME warning). + output(msg.preamble) if msg.preamble is not None: output(os.linesep) @@ -519,7 +546,7 @@ def open_output_file(filename): os.makedirs(full_dir) try: return open(fullpath, 'wb') - except: + except Exception: if create: os.removedirs(full_dir) @@ -552,9 +579,13 @@ class GlobalOptions: totext_mask = [] # A list of content-types to decode binary_mask = [] # A list of content-types to pass through - decoded_binary_mask = [] # A list of content-types to pass through (content-transfer-decoded) - ignore_mask = [] # Ignore (do not decode and do not include into output) but output a warning instead of the body - fully_ignore_mask = [] # Completely ignore - no headers, no body, no warning + # A list of content-types to pass through (content-transfer-decoded). + decoded_binary_mask = [] + # Ignore (do not decode and do not include into output) + # but output a warning instead of the body. + ignore_mask = [] + # Completely ignore - no headers, no body, no warning. + fully_ignore_mask = [] error_mask = [] # Raise error if encounter one of these save_counter = 0