From 0b6635046ff1b433df331489c41c1bda61a3806e Mon Sep 17 00:00:00 2001 From: Fedele Mantuano Date: Wed, 25 Jun 2025 23:51:52 +0200 Subject: [PATCH 1/2] Fixed issue Processing breaks if a "headers:" email header exists #139 --- src/mailparser/__main__.py | 2 +- src/mailparser/core.py | 8 +++----- tests/mails/mail_test_16 | 26 ++++++++++++++++++++++++++ tests/test_mail_parser.py | 15 +++++++++++++++ 4 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 tests/mails/mail_test_16 diff --git a/src/mailparser/__main__.py b/src/mailparser/__main__.py index c25d813..fb3d848 100644 --- a/src/mailparser/__main__.py +++ b/src/mailparser/__main__.py @@ -202,7 +202,7 @@ def main(): parser = get_parser(args) process_output(args, parser) except Exception as e: - log.error(f"An error occurred: {e}") + log.exception(f"An error occurred: {e}") sys.exit(1) diff --git a/src/mailparser/core.py b/src/mailparser/core.py index 7df9e32..7e02d13 100644 --- a/src/mailparser/core.py +++ b/src/mailparser/core.py @@ -638,14 +638,12 @@ def body(self): ) @property - def headers(self): + def headers(self) -> dict: """ Return only the headers as Python object """ - d = {} - for i in self.message.keys(): - d[i] = getattr(self, i) - return d + all_headers = set(self.message.keys()) - set(["headers"]) + return {i: getattr(self, i) for i in all_headers} @property def headers_json(self): diff --git a/tests/mails/mail_test_16 b/tests/mails/mail_test_16 new file mode 100644 index 0000000..6e70b28 --- /dev/null +++ b/tests/mails/mail_test_16 @@ -0,0 +1,26 @@ +Subject: Test spam mail (GTUBE) +Message-ID: +Date: Wed, 23 Jul 2003 23:30:00 +0200 +From: Sender +To: Recipient +Precedence: junk +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +headers: hello-world + +This is the GTUBE, the + Generic + Test for + Unsolicited + Bulk + Email + +If your spam filter supports it, the GTUBE provides a test by which you +can verify that the filter is installed correctly and is detecting incoming +spam. You can send yourself a test mail containing the following string of +characters (in upper case and with no white spaces and line breaks): + +XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X + +You should send this test mail from an account outside of your network. \ No newline at end of file diff --git a/tests/test_mail_parser.py b/tests/test_mail_parser.py index d951cfb..d9bf5ec 100644 --- a/tests/test_mail_parser.py +++ b/tests/test_mail_parser.py @@ -62,6 +62,7 @@ mail_test_13 = os.path.join(base_path, "mails", "mail_test_13") mail_test_14 = os.path.join(base_path, "mails", "mail_test_14") mail_test_15 = os.path.join(base_path, "mails", "mail_test_15") +mail_test_16 = os.path.join(base_path, "mails", "mail_test_16") mail_malformed_1 = os.path.join(base_path, "mails", "mail_malformed_1") mail_malformed_2 = os.path.join(base_path, "mails", "mail_malformed_2") mail_malformed_3 = os.path.join(base_path, "mails", "mail_malformed_3") @@ -646,3 +647,17 @@ def test_write_uuencode_attachment(self): md5.update(f.read()) shutil.rmtree(temp_dir) self.assertEqual(md5.hexdigest(), "4f2cf891e7cfb349fca812091f184ecc") + + def test_issue_139(self): + mail = mailparser.parse_from_file(mail_test_16) + assert mail.headers == { + "MIME-Version": "1.0", + "Precedence": "junk", + "Content-Type": "text/plain; charset=us-ascii", + "From": [("Sender", "sender@example.net")], + "Date": "Wed, 23 Jul 2003 23:30:00 +0200", + "Content-Transfer-Encoding": "7bit", + "Message-ID": "", + "Subject": "Test spam mail (GTUBE)", + "To": [("Recipient", "recipient@example.net")], + } From 8ddec4a1033609d6f1616b363dead8784dd8150f Mon Sep 17 00:00:00 2001 From: Fedele Mantuano Date: Wed, 25 Jun 2025 23:58:30 +0200 Subject: [PATCH 2/2] Fix newline at end of file in mail_test_16 --- tests/mails/mail_test_16 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/mails/mail_test_16 b/tests/mails/mail_test_16 index 6e70b28..f2148cb 100644 --- a/tests/mails/mail_test_16 +++ b/tests/mails/mail_test_16 @@ -23,4 +23,4 @@ characters (in upper case and with no white spaces and line breaks): XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X -You should send this test mail from an account outside of your network. \ No newline at end of file +You should send this test mail from an account outside of your network.