Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,20 @@ jobs:
sudo cpan -f -i Email::Outlook::Message

- name: Run tests
env:
PYTHONPATH: src
run: |
pytest
pytest --cov=mailparser --cov-report=xml
python -m mailparser -v
python -m mailparser -h
mail-parser -f tests/mails/mail_malformed_3 -j
cat tests/mails/mail_malformed_3 | mail-parser -k -j

- name: Run pre-commit
if: matrix.python-version == '3.10'
run: |
make pre-commit

- name: Report to Coveralls
if: matrix.python-version == '3.10'
uses: coverallsapp/github-action@v2.2.3
Expand All @@ -57,4 +64,4 @@ jobs:
name: build-artifacts
path: |
dist/mail-parser-*.tar.gz
dist/mail_parser-*.whl
dist/mail_parser-*.whl
29 changes: 29 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
args: ['--maxkb=5000']
- id: check-case-conflict
- id: check-json
- id: check-merge-conflict
- id: detect-aws-credentials
args: ["--allow-missing-credentials"]
- id: detect-private-key
- id: mixed-line-ending
- id: check-ast

- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.7.0
hooks:
# Run the linter.
- id: ruff
args: [ --fix ]
# Run the formatter.
- id: ruff-format
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@ dist: clean-all ## builds source and wheel package
python -m build

release: dist ## package and upload a release
twine upload dist/*
twine upload dist/*
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![PyPI version](https://badge.fury.io/py/mail-parser.svg)](https://badge.fury.io/py/mail-parser)
![PyPI - Version](https://img.shields.io/pypi/v/mail-parser)
[![Coverage Status](https://coveralls.io/repos/github/SpamScope/mail-parser/badge.svg?branch=develop)](https://coveralls.io/github/SpamScope/mail-parser?branch=develop)

![SpamScope](https://raw.githubusercontent.com/SpamScope/spamscope/develop/docs/logo/spamscope.png)
Expand Down Expand Up @@ -288,4 +288,4 @@ Then you can try to run the command line tool:
$ mail-parser -f tests/mails/mail_malformed_3 -j
```

If all is ok, you can start to develop.
If all is ok, you can start to develop.
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ RUN apt-get -yqq update; \
apt-get -yqq --no-install-recommends install libemail-outlook-message-perl; \
apt-get clean; \
rm -rf /var/lib/apt/lists/*; \
git clone -b $BRANCH --single-branch https://github.com/SpamScope/mail-parser.git $MAIL_PARSER_PATH; \
git clone -b $BRANCH --single-branch https://github.com/SpamScope/mail-parser.git $MAIL_PARSER_PATH; \
cd $MAIL_PARSER_PATH && python setup.py install
ENTRYPOINT ["mailparser"]
CMD ["-h"]
2 changes: 1 addition & 1 deletion docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ This command runs mail-parser help as default, but you can use all others option

To share the "mails" directory between your host and the container, create a "mails" directory on your host.

There also is an example of `docker-compose`
There also is an example of `docker-compose`

From the `docker-compose.yml` directory, run:

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[build-system]
requires = ["setuptools >= 40.6.0", "wheel"]
build-backend = "setuptools.build_meta"
build-backend = "setuptools.build_meta"
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,4 @@ addopts =
--cov-report=html
--junitxml=junit.xml
--verbose
testpaths = tests
testpaths = tests
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
import setuptools

if __name__ == "__main__":
setuptools.setup()
setuptools.setup()
18 changes: 14 additions & 4 deletions src/mailparser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,23 @@
limitations under the License.
"""


from .mailparser import (
from mailparser.mailparser import (
MailParser,
parse_from_bytes,
parse_from_file,
parse_from_file_msg,
parse_from_file_obj,
parse_from_string)
parse_from_string,
)

from mailparser.utils import get_header

from .utils import get_header
__all__ = [
"MailParser",
"parse_from_bytes",
"parse_from_file",
"parse_from_file_msg",
"parse_from_file_obj",
"parse_from_string",
"get_header",
]
95 changes: 45 additions & 50 deletions src/mailparser/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,159 +35,155 @@

current = os.path.realpath(os.path.dirname(__file__))

__version__ = runpy.run_path(
os.path.join(current, "version.py"))["__version__"]
__version__ = runpy.run_path(os.path.join(current, "version.py"))["__version__"]


def get_args():
parser = argparse.ArgumentParser(
description="Wrapper for email Python Standard Library",
epilog="It takes as input a raw mail and generates a parsed object.",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)

parsing_group = parser.add_mutually_exclusive_group(required=True)
parsing_group.add_argument(
"-f",
"--file",
dest="file",
help="Raw email file")
parsing_group.add_argument(
"-s",
"--string",
dest="string",
help="Raw email string")
parsing_group.add_argument("-f", "--file", dest="file", help="Raw email file")
parsing_group.add_argument("-s", "--string", dest="string", help="Raw email string")
parsing_group.add_argument(
"-k",
"--stdin",
dest="stdin",
action="store_true",
help="Enable parsing from stdin")
help="Enable parsing from stdin",
)

parser.add_argument(
"-l",
"--log-level",
dest="log_level",
default="WARNING",
choices=["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "NOTSET"],
help="Set log level")
help="Set log level",
)

parser.add_argument(
"-j",
"--json",
dest="json",
action="store_true",
help="Show the JSON of parsed mail")
help="Show the JSON of parsed mail",
)

parser.add_argument(
"-b",
"--body",
dest="body",
action="store_true",
help="Print the body of mail")
"-b", "--body", dest="body", action="store_true", help="Print the body of mail"
)

parser.add_argument(
"-a",
"--attachments",
dest="attachments",
action="store_true",
help="Print the attachments of mail")
help="Print the attachments of mail",
)

parser.add_argument(
"-r",
"--headers",
dest="headers",
action="store_true",
help="Print the headers of mail")
help="Print the headers of mail",
)

parser.add_argument(
"-t",
"--to",
dest="to",
action="store_true",
help="Print the to of mail")
"-t", "--to", dest="to", action="store_true", help="Print the to of mail"
)

parser.add_argument(
"-dt",
"--delivered-to",
dest="delivered_to",
action="store_true",
help="Print the delivered-to of mail")
help="Print the delivered-to of mail",
)

parser.add_argument(
"-m",
"--from",
dest="from_",
action="store_true",
help="Print the from of mail")
"-m", "--from", dest="from_", action="store_true", help="Print the from of mail"
)

parser.add_argument(
"-u",
"--subject",
dest="subject",
action="store_true",
help="Print the subject of mail")
help="Print the subject of mail",
)

parser.add_argument(
"-c",
"--receiveds",
dest="receiveds",
action="store_true",
help="Print all receiveds of mail")
help="Print all receiveds of mail",
)

parser.add_argument(
"-d",
"--defects",
dest="defects",
action="store_true",
help="Print the defects of mail")
help="Print the defects of mail",
)

parser.add_argument(
"-o",
"--outlook",
dest="outlook",
action="store_true",
help="Analyze Outlook msg")
help="Analyze Outlook msg",
)

parser.add_argument(
"-i",
"--senderip",
dest="senderip",
metavar="Trust mail server string",
help="Extract a reliable sender IP address heuristically")
help="Extract a reliable sender IP address heuristically",
)

parser.add_argument(
"-p",
"--mail-hash",
dest="mail_hash",
action="store_true",
help="Print mail fingerprints without headers")
help="Print mail fingerprints without headers",
)

parser.add_argument(
"-z",
"--attachments-hash",
dest="attachments_hash",
action="store_true",
help="Print attachments with fingerprints")
help="Print attachments with fingerprints",
)

parser.add_argument(
"-sa",
"--store-attachments",
dest="store_attachments",
action="store_true",
help="Store attachments on disk")
help="Store attachments on disk",
)

parser.add_argument(
"-ap",
"--attachments-path",
dest="attachments_path",
default="/tmp",
help="Path where store attachments")
help="Path where store attachments",
)

parser.add_argument(
'-v',
'--version',
action='version',
version='%(prog)s {}'.format(__version__))
"-v", "--version", action="version", version="%(prog)s {}".format(__version__)
)

return parser

Expand All @@ -206,8 +202,7 @@ def main():
parser = mailparser.parse_from_string(args.string)
elif args.stdin:
if args.outlook:
raise MailParserOutlookError(
"You can't use stdin with msg Outlook")
raise MailParserOutlookError("You can't use stdin with msg Outlook")
parser = mailparser.parse_from_file_obj(sys.stdin)

if args.json:
Expand Down Expand Up @@ -260,5 +255,5 @@ def main():
write_attachments(parser.attachments, args.attachments_path)


if __name__ == '__main__':
if __name__ == "__main__":
main()
Loading