From ddf13ea837603b95a428f102dac336801f7887e5 Mon Sep 17 00:00:00 2001 From: derikroby-solve42 Date: Wed, 3 Sep 2025 11:51:18 +0200 Subject: [PATCH 1/2] Some context: Here the change in constant was introduced because mail replies were not split correctly in ticket 175. It is fixed with the change in the constant and mail replies are parsed correctly now. Reason for not split: original regex searched for "schrieb am" but we had "Am schrieb" in our mail. --- mailparser_reply/constants.py | 4 +- test/__init__.py | 0 test/emails/email_schrieb_am.txt | 63 ++++++++++++++++++++++++++++++++ test/test_email_reply_parser.py | 16 ++++++++ 4 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 test/__init__.py create mode 100644 test/emails/email_schrieb_am.txt diff --git a/mailparser_reply/constants.py b/mailparser_reply/constants.py index bf57794..f1ebace 100644 --- a/mailparser_reply/constants.py +++ b/mailparser_reply/constants.py @@ -76,9 +76,9 @@ 'sent_from': 'Sent from my|Get Outlook for', }, 'de': { - 'wrote_header': r'^(?!Am.*Am\s.+?schrieb.*:)(' + 'wrote_header': [r'^(?!Am.*Am\s.+?schrieb.*:)(' + QUOTED_MATCH_INCLUDE - + r'Am\s(?:.+?\s?)schrieb\s(?:.+?\s?.+?):)$', + + r'Am\s(?:.+?\s?)schrieb\s(?:.+?\s?.+?):)$',r'^(\s*(?:> ?)*[^\s<>]+@[^\s<>]+>?\s*schrieb\s*am\s+.+?:\s*)$'], 'from_header': r'((?:(?:^|\n|\n' + QUOTED_MATCH_INCLUDE + r')[* ]*(?:Von|Gesendet|An|Betreff|Datum|Cc|Organisation):[ *]*(?:\s{,2}).*){2,}(?:\n.*){,1})', diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/emails/email_schrieb_am.txt b/test/emails/email_schrieb_am.txt new file mode 100644 index 0000000..99b86c4 --- /dev/null +++ b/test/emails/email_schrieb_am.txt @@ -0,0 +1,63 @@ +Guten Abend, + +Ich habe soeben eine Zahlungserinnerung bezüglich der Rechnung vom 29/09 erhalten. + +Ich habe den Betrag nicht überwiesen, da die Lizenz für die Software nie aktiviert wurde und Sie mir geraten hatten, mich direkt mit dem Hersteller des Produkts in Verbindung zu setzen. Das habe ich getan, aber bisher keine Rückmeldung erhalten. + +Mit freundlichen Grüßen, + +Alex Beispiel + +support@techportal.com> schrieb am Mi. 3. Okt. 2025 um 17:26: + +> Sehr geehrter Herr Beispiel +> +> +> +> In diesem Fall stehen Aussage gegen Aussage. Da wir als Vermittlungsplattform nicht abschließend bewerten können, welche Partei korrekt handelt, schlagen wir vor, dass Sie direkt mit dem Anbieter kommunizieren und eine Lösung finden. +> +> +> +> Mögliche Optionen könnten sein: +> +> * Eine neue Lizenzaktivierung durch die Firma SoftLine GmbH +> * Oder: eine reduzierte Rechnung über 30 EUR für den bisherigen Aufwand +> * Oder eine alternative Lösung, mit der beide Parteien einverstanden sind +> +> +> +> Hier finden Sie die Kontaktdaten der Firma: +> +> SoftLine GmbH +> +> Technoweg 7/4 1010 +> +> Beispielstadt +> +> +491778889900 +> +> softline-support@gmx.net +> +> +> +> Mit besten Grüßen +> +> **Miriam Schulze** +> +> ![cid:image001.png@01D3CE5D.dsdsdsd](cid:_kCB-KMeAh3M2LYmMNWNcUMoDgE) +> +> **TechPortal Support** +> +> TechPort GmbH +> +> Digitalstraße 12/5 · 54321 Musterstadt · GERMANY +> +> HRB: 999999 · Amtsgericht Musterstadt +> +> USt-ID: DE1234751230 +> +> support@techportal.com +> +> +> +> +49 (0) 321 456 654 diff --git a/test/test_email_reply_parser.py b/test/test_email_reply_parser.py index 1b127a7..287ef0b 100644 --- a/test/test_email_reply_parser.py +++ b/test/test_email_reply_parser.py @@ -211,6 +211,22 @@ def test_swedish_realistic_anonymized(self): self.assertIn("Kan inte se att det står något", mail.replies[1].body) self.assertIn("Jag har försökt få tag", mail.replies[2].body) + def test_german_schrieb_am_email(self): + mail = self.get_email('email_schrieb_am', parse=True, languages=['de']) + + # Should be split into customer reply and quoted response + self.assertEqual(2, len(mail.replies)) + + # The latest reply (customer complaint) + self.assertIn("Zahlungserinnerung bezüglich der Rechnung", mail.replies[0].body) + self.assertNotIn("Zahlungserinnerung bezüglich der Rechnung", mail.replies[1].body) + self.assertIn("In diesem Fall stehen Aussage gegen Aussage", mail.replies[1].body) + self.assertNotIn("In diesem Fall stehen Aussage gegen Aussage", mail.replies[0].body) + + # The quoted reply should have "schrieb am" in headers + self.assertIn("schrieb am", mail.replies[1].headers) + self.assertTrue(mail.replies[1].body.strip().startswith("> Sehr geehrter Herr Beispiel")) + def get_email(self, name: str, parse: bool = True, languages: list = None): """ Return EmailMessage instance or text content """ with open(f'test/emails/{name}.txt', encoding='utf-8') as f: From c501ec9199b41d5f1ec95b395f6de3c15c851f09 Mon Sep 17 00:00:00 2001 From: derikroby-solve42 Date: Wed, 3 Sep 2025 14:01:15 +0200 Subject: [PATCH 2/2] formatting in constants and removing pii --- mailparser_reply/constants.py | 4 +++- test/emails/email_schrieb_am.txt | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/mailparser_reply/constants.py b/mailparser_reply/constants.py index f1ebace..0213a5b 100644 --- a/mailparser_reply/constants.py +++ b/mailparser_reply/constants.py @@ -78,7 +78,9 @@ 'de': { 'wrote_header': [r'^(?!Am.*Am\s.+?schrieb.*:)(' + QUOTED_MATCH_INCLUDE - + r'Am\s(?:.+?\s?)schrieb\s(?:.+?\s?.+?):)$',r'^(\s*(?:> ?)*[^\s<>]+@[^\s<>]+>?\s*schrieb\s*am\s+.+?:\s*)$'], + + r'Am\s(?:.+?\s?)schrieb\s(?:.+?\s?.+?):)$', + r'^(\s*(?:> ?)*[^\s<>]+@[^\s<>]+>?\s*schrieb\s*am\s+.+?:\s*)$' + ], 'from_header': r'((?:(?:^|\n|\n' + QUOTED_MATCH_INCLUDE + r')[* ]*(?:Von|Gesendet|An|Betreff|Datum|Cc|Organisation):[ *]*(?:\s{,2}).*){2,}(?:\n.*){,1})', diff --git a/test/emails/email_schrieb_am.txt b/test/emails/email_schrieb_am.txt index 99b86c4..c899df6 100644 --- a/test/emails/email_schrieb_am.txt +++ b/test/emails/email_schrieb_am.txt @@ -42,9 +42,8 @@ support@techportal.com> schrieb am Mi. 3. Okt. 2025 um 17:26: > > Mit besten Grüßen > -> **Miriam Schulze** +> **Martina Musterfrau** > -> ![cid:image001.png@01D3CE5D.dsdsdsd](cid:_kCB-KMeAh3M2LYmMNWNcUMoDgE) > > **TechPortal Support** > @@ -60,4 +59,4 @@ support@techportal.com> schrieb am Mi. 3. Okt. 2025 um 17:26: > > > -> +49 (0) 321 456 654 +> +49 (0) 123 456 789