Skip to content

Commit

Permalink
Merge branch 'release/2.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
fedelemantuano committed Nov 12, 2017
2 parents b58e298 + 167dcea commit 92102bd
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 9 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ script:
- python -m mailparser -v
- python -m mailparser -h
- python -m mailparser -f tests/mails/mail_malformed_3 -j
- cat tests/mails/mail_malformed_3 | python -m mailparser -k -j
- python -m mailparser -f tests/mails/mail_test_6 -j

after_success:
Expand Down
4 changes: 3 additions & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ Import ``mailparser`` module:
import mailparser

mail = mailparser.parse_from_file(f)
mail = mailparser.parse_from_file_obj(fp)
mail = mailparser.parse_from_string(raw_mail)
mail = mailparser.parse_from_bytes(byte_mail)

Expand Down Expand Up @@ -124,7 +125,7 @@ These are all swithes:

::

usage: mailparser [-h] (-f FILE | -s STRING) [-j] [-b] [-a] [-r] [-t] [-m]
usage: mailparser [-h] (-f FILE | -s STRING | -k) [-j] [-b] [-a] [-r] [-t] [-m]
[-u] [-c] [-d] [-n] [-i Trust mail server string] [-p] [-z]
[-v]

Expand All @@ -136,6 +137,7 @@ These are all swithes:
Raw email file (default: None)
-s STRING_, --string STRING_
Raw email string (default: None)
-k, --stdin Enable parsing from stdin (default: False)
-j, --json Show the JSON of parsed mail (default: False)
-b, --body Print the body of mail (default: False)
-a, --attachments Print the attachments of mail (default: False)
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ Import `mailparser` module:
import mailparser
mail = mailparser.parse_from_file(f)
mail = mailparser.parse_from_file_obj(fp)
mail = mailparser.parse_from_string(raw_mail)
mail = mailparser.parse_from_bytes(byte_mail)
```
Expand Down Expand Up @@ -123,7 +124,7 @@ If you installed mailparser with `pip` or `setup.py` you can use it with command
These are all swithes:

```
usage: mailparser.py [-h] (-f FILE | -s STRING) [-j] [-b] [-a] [-r] [-t] [-m]
usage: mailparser.py [-h] (-f FILE | -s STRING | -k) [-j] [-b] [-a] [-r] [-t] [-m]
[-u] [-c] [-d] [-n] [-i Trust mail server string] [-p] [-z]
[-v]
Expand All @@ -134,6 +135,7 @@ optional arguments:
-f FILE, --file FILE Raw email file (default: None)
-s STRING, --string STRING
Raw email string (default: None)
-k, --stdin Enable parsing from stdin (default: False)
-j, --json Show the JSON of parsed mail (default: False)
-b, --body Print the body of mail (default: False)
-a, --attachments Print the attachments of mail (default: False)
Expand Down
2 changes: 1 addition & 1 deletion mailparser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@


from .mailparser import (MailParser, parse_from_file, parse_from_file_msg,
parse_from_string, parse_from_bytes)
parse_from_string, parse_from_bytes, parse_from_file_obj)
11 changes: 11 additions & 0 deletions mailparser/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import argparse
import os
import runpy
import sys

import simplejson as json

Expand Down Expand Up @@ -49,6 +50,12 @@ def get_args():
"--string",
dest="string",
help="Raw email string")
parsing_group.add_argument(
"-k",
"--stdin",
dest="stdin",
action="store_true",
help="Enable parsing from stdin")

parser.add_argument(
"-j",
Expand Down Expand Up @@ -197,6 +204,10 @@ def main():
parser = mailparser.parse_from_file(args.file)
elif args.string:
parser = mailparser.parse_from_string(args.string)
elif args.stdin:
if args.outlook:
raise RuntimeError("You can't use stdin with msg Outlook")
parser = mailparser.parse_from_file_obj(sys.stdin)

if args.json:
j = json.loads(parser.parsed_mail_json)
Expand Down
48 changes: 44 additions & 4 deletions mailparser/mailparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,18 @@
EPILOGUE_DEFECTS = {"StartBoundaryNotFoundDefect"}


def parse_from_file_obj(fp):
"""Parsing email from a file-like object.
Args:
fp (file-like object): file-like object of raw email
Returns:
Instance of MailParser with raw email parsed
"""
return MailParser.from_file_obj(fp).parse()


def parse_from_file(fp):
"""Parsing email from file.
Expand Down Expand Up @@ -98,6 +110,22 @@ def __init__(self, message=None):
"""Init a new object from a message object structure. """
self._message = message

@classmethod
def from_file_obj(cls, fp):
"""Init a new object from a file-like object.
Not for Outlook msg.
Args:
fp (file-like object): file-like object of raw email
Returns:
Instance of MailParser
"""

message = email.message_from_file(fp)

return cls(message)

@classmethod
def from_file(cls, fp, is_outlook=False):
"""Init a new object from a file path.
Expand Down Expand Up @@ -164,6 +192,19 @@ def from_bytes(cls, bt):
message = email.message_from_bytes(bt)
return cls(message)

def parse_from_file_obj(self, fp):
"""Parse the raw email from a file path.
Args:
fp (file-like object): file-like object of raw email
Returns:
Instance of MailParser
"""

self._message = email.message_from_file(fp)
return self.parse()

def parse_from_file(self, fp):
"""Parse the raw email from a file path.
Expand All @@ -179,7 +220,7 @@ def parse_from_file(self, fp):
return self.parse()

def parse_from_file_msg(self, fp):
"""Parse the raw email from a file Outlook.
"""Parse the raw email from a file path Outlook.
Args:
fp (string): file path of raw email
Expand Down Expand Up @@ -286,8 +327,7 @@ def parse(self):
"""

if not self.message.keys():
raise ValueError("This email doesn't have headers:\n\n{}".format(
self.message_as_string))
raise ValueError("This email doesn't have headers")

# Reset for new mail
self._reset()
Expand Down Expand Up @@ -321,9 +361,9 @@ def parse(self):
if not p.is_multipart():
filename = ported_string(p.get_filename())
charset = p.get_content_charset('utf-8')
binary = False

if filename:
binary = False
mail_content_type = ported_string(p.get_content_type())
transfer_encoding = ported_string(
p.get('content-transfer-encoding', '')).lower()
Expand Down
2 changes: 1 addition & 1 deletion mailparser/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
limitations under the License.
"""

__version__ = "2.0.1"
__version__ = "2.1.0"

if __name__ == "__main__":
print(__version__)
60 changes: 59 additions & 1 deletion tests/test_mail_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

sys.path.append(root)
import mailparser
from mailparser.utils import fingerprints, msgconvert
from mailparser.utils import fingerprints, msgconvert, ported_open


class TestMailParser(unittest.TestCase):
Expand Down Expand Up @@ -286,6 +286,11 @@ def test_parser_methods(self):
n.parse_from_string(m.message_as_string)
self.assertEqual(len(result["attachments"]), 1)

o = mailparser.MailParser()
with open(mail_test_3) as fp:
o.parse_from_file_obj(fp)
self.assertEqual(len(result["attachments"]), 1)

def test_bug_UnicodeDecodeError(self):
m = mailparser.parse_from_file(mail_test_6)
self.assertIsInstance(m.parsed_mail_obj, dict)
Expand Down Expand Up @@ -326,6 +331,59 @@ def test_msgconvert(self):
m = mailparser.parse_from_file(f)
self.assertEqual(m.from_, "<[email protected]>")

def test_from_file_obj(self):
with ported_open(mail_test_2) as fp:
mail = mailparser.parse_from_file_obj(fp)
trust = "smtp.customers.net"

self.assertEqual(False, mail.has_defects)

result = mail.parsed_mail_obj
self.assertIsInstance(result, dict)
self.assertNotIn("defects", result)
self.assertNotIn("anomalies", result)
self.assertIn("has_defects", result)
self.assertIn("has_anomalies", result)

result = mail.get_server_ipaddress(trust)
self.assertIsInstance(result, six.text_type)

result = mail.parsed_mail_json
self.assertIsInstance(result, six.text_type)

result = mail.headers
self.assertIsInstance(result, six.text_type)

result = mail.body
self.assertIsInstance(result, six.text_type)

result = mail.date_mail
self.assertIsInstance(result, datetime.datetime)

result = mail.from_
self.assertIsInstance(result, six.text_type)

result = mail.to_
self.assertIsInstance(result, six.text_type)

result = mail.subject
self.assertIsInstance(result, six.text_type)

result = mail.message_id
self.assertIsInstance(result, six.text_type)

result = mail.attachments_list
self.assertIsInstance(result, list)

result = mail.date_mail
self.assertIsInstance(result, datetime.datetime)

result = mail.defects
self.assertIsInstance(result, list)

result = mail.anomalies
self.assertIsInstance(result, list)


if __name__ == '__main__':
unittest.main(verbosity=2)
3 changes: 3 additions & 0 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ def test_required(self):
with self.assertRaises(SystemExit):
self.parser.parse_args(["--file", "test", "--string", "test"])

with self.assertRaises(SystemExit):
self.parser.parse_args(["--file", "test", "--stdin"])

with self.assertRaises(SystemExit):
self.parser.parse_args(["--file"])

Expand Down

0 comments on commit 92102bd

Please sign in to comment.