From 28a62cdbc655154c2703855918440c8289d17564 Mon Sep 17 00:00:00 2001 From: Sean Whalen Date: Thu, 11 Oct 2018 13:24:16 -0400 Subject: [PATCH] Really fix refactoring --- parsedmarc/__init__.py | 10 +++++- parsedmarc/utils.py | 72 +++++++++++++++++++++--------------------- 2 files changed, 45 insertions(+), 37 deletions(-) diff --git a/parsedmarc/__init__.py b/parsedmarc/__init__.py index 8da9c3d4..4d0b0d2d 100644 --- a/parsedmarc/__init__.py +++ b/parsedmarc/__init__.py @@ -31,10 +31,12 @@ import xmltodict import imapclient import imapclient.exceptions import dateparser +import mailparser from parsedmarc.__version__ import __version__ from parsedmarc.utils import get_base_domain, get_filename_safe_string from parsedmarc.utils import get_ip_address_country, get_ip_address_info +from parsedmarc.utils import is_outlook_msg, convert_outlook_msg from parsedmarc.utils import timestamp_to_human, parse_email, EmailParserError logger = logging.getLogger("parsedmarc") @@ -633,7 +635,13 @@ def parse_report_email(input_, nameservers=None, timeout=2.0): * ``report``: The parsed report """ result = None - msg = email.message_from_string(input_) + + try: + if is_outlook_msg(input_): + input_ = convert_outlook_msg(input_) + msg = mailparser.parse_from_string(input_).headers_json + except Exception as e: + raise ParserError(e.__str__()) msg_headers = msg.headers_json date = email.utils.format_datetime(datetime.utcnow()) subject = None diff --git a/parsedmarc/utils.py b/parsedmarc/utils.py index 7742f262..1b5fa827 100644 --- a/parsedmarc/utils.py +++ b/parsedmarc/utils.py @@ -324,6 +324,42 @@ def get_filename_safe_string(string): return string + def is_outlook_msg(suspect_bytes): + """Checks if the given content is a Outlook msg OLE file""" + return suspect_bytes.startswith(b"\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1") + +def convert_outlook_msg(msg_bytes): + """ + Uses the ``msgconvert`` Perl utility to convert an Outlook MS file to + standard RFC 822 format + + Args: + msg_bytes (bytes): the content of the .msg file + + Returns: + A RFC 822 string + """ + if not is_outlook_msg(msg_bytes): + raise ValueError("The supplied bytes are not an Outlook MSG file") + orig_dir = os.getcwd() + tmp_dir = tempfile.mkdtemp() + os.chdir(tmp_dir) + with open("sample.msg", "wb") as msg_file: + msg_file.write(msg_bytes) + try: + subprocess.check_call(["msgconvert", "sample.msg"]) + eml_path = "sample.eml" + with open(eml_path, "rb") as eml_file: + rfc822 = eml_file.read() + except FileNotFoundError: + raise EmailParserError( + "Failed to convert Outlook MSG: msgconvert utility not found") + finally: + os.chdir(orig_dir) + shutil.rmtree(tmp_dir) + + return rfc822 + def parse_email(data): """ @@ -335,42 +371,6 @@ def parse_email(data): Returns (dict): Parsed email data """ - def is_outlook_msg(suspect_bytes): - """Checks if the given content is a Outlook msg OLE file""" - return suspect_bytes.startswith(b"\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1") - - def convert_outlook_msg(msg_bytes): - """ - Uses the ``msgconvert`` Perl utility to convert an Outlook MS file to - standard RFC 822 format - - Args: - msg_bytes (bytes): the content of the .msg file - - Returns: - A RFC 822 string - """ - if not is_outlook_msg(msg_bytes): - raise ValueError("The supplied bytes are not an Outlook MSG file") - orig_dir = os.getcwd() - tmp_dir = tempfile.mkdtemp() - os.chdir(tmp_dir) - with open("sample.msg", "wb") as msg_file: - msg_file.write(msg_bytes) - try: - subprocess.check_call(["msgconvert", "sample.msg"]) - eml_path = "sample.eml" - with open(eml_path, "rb") as eml_file: - rfc822 = eml_file.read() - except FileNotFoundError: - raise EmailParserError( - "Failed to convert Outlook MSG: msgconvert utility not found") - finally: - os.chdir(orig_dir) - shutil.rmtree(tmp_dir) - - return rfc822 - if type(data) == bytes: if is_outlook_msg(data): data = convert_outlook_msg(data)