"""Decode MIME message"""
import sys, os
+import subprocess
from mimedecode_version import __version__, \
__author__, __copyright__, __license__
+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
me = os.path.basename(sys.argv[0])
def output_headers(msg):
unix_from = msg.get_unixfrom()
if unix_from:
- output(unix_from + os.linesep)
+ output(unix_from)
+ output(os.linesep)
for key, value in msg.items():
- output("%s: %s%s" % (key, value, os.linesep))
+ output(key)
+ output(": ")
+ value = value.split(';', 1)
+ output(value[0])
+ if len(value) == 2:
+ output(";")
+ output(_decode_header(value[1], strip=False))
+ output(os.linesep)
output(os.linesep) # End of headers
def recode_if_needed(s, charset):
- if charset and charset.lower() != g.default_encoding:
- s = s.decode(charset, "replace").encode(g.default_encoding, "replace")
+ if bytes is str: # Python2
+ if isinstance(s, bytes) and \
+ charset and charset.lower() != g.default_encoding:
+ s = s.decode(charset, "replace").\
+ encode(g.default_encoding, "replace")
+ else: # Python3
+ if isinstance(s, bytes):
+ s = s.decode(charset, "replace")
return s
-def _decode_header(s):
+def _decode_header(s, strip=True):
"""Return a decoded string according to RFC 2047.
NOTE: This is almost the same as email.Utils.decode.
"""
rtn = []
for atom, charset in L:
- if charset is None:
- rtn.append(atom)
- else:
- rtn.append(recode_if_needed(atom, charset))
- rtn.append(' ')
- del rtn[-1] # remove the last space
+ atom = recode_if_needed(atom, charset or g.default_encoding)
+ if strip:
+ atom = atom.strip()
+ rtn.append(atom)
# Now that we've decoded everything, we just need to join all the parts
# together into the final string.
- return ''.join(rtn)
+ return ' '.join(rtn)
def decode_header(msg, header):
"Decode mail header (if exists) and put it back, if it was encoded"
def _get_exceptions(list):
- return [x[1:].lower() for x in list[1:] if x[0]=='-']
+ return [x[1:].lower() for x in list[1:] if x[0] == '-']
def _decode_headers_params(msg, header, decode_all_params, param_list):
if decode_all_params:
caps = mailcap.getcaps()
content_type = msg.get_content_type()
+ if content_type.startswith('text/'):
+ charset = msg.get_content_charset()
+ else:
+ charset = None
filename = tempfile.mktemp()
command = None
return s
outfile = open(filename, 'wb')
+ if charset and bytes is not str and isinstance(s, bytes): # Python3
+ s = s.decode(charset, "replace")
+ if not isinstance(s, bytes):
+ s = s.encode(g.default_encoding, "replace")
outfile.write(s)
outfile.close()
- pipe = os.popen(command, 'r')
- s = pipe.read()
- pipe.close()
+ pipe = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
+ new_s = pipe.stdout.read()
+ pipe.stdout.close()
+ if pipe.wait() == 0: # result=0, Ok
+ s = new_s
+ if bytes is not str and isinstance(s, bytes): # Python3
+ s = s.decode(g.default_encoding, "replace")
+ 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])
+ else:
+ 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)
- 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])
-
return s
global output
save_output = output
outfile = open_output_file(fname)
- output = outfile.write
+ 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)
if save_body:
outstring = totext(msg, outstring)
break
elif content_type in g.binary_mask or \
- content_type in g.decoded_binary_mask:
+ content_type in g.decoded_binary_mask:
output_headers(msg)
output(outstring)
break
from getopt import getopt, GetoptError
try:
- options, arguments = getopt(sys.argv[1:],
+ options, arguments = getopt(
+ sys.argv[1:],
'hVcCDPH:f:d:p:r:R:b:B:e:I:i:t:O:o:',
['help', 'version', 'host=',
'save-headers=', 'save-body=', 'save-message=',
g.host_name = socket.gethostname()
g.outfile = outfile
- output = outfile.write
+ if hasattr(outfile, 'buffer'):
+ def output_bytes(s):
+ if not isinstance(s, bytes):
+ s = s.encode(g.default_encoding, "replace")
+ outfile.buffer.write(s)
+ output = output_bytes
+ else:
+ output = outfile.write
import email
msg = email.message_from_file(infile)