from __future__ import annotations import unittest from pathlib import Path from email_connect.models import MessageClass from email_connect.parser import parse_message_file FIXTURES = Path(__file__).parent / "fixtures" / "mailbox" class ParserTests(unittest.TestCase): def test_hard_bounce_maps_to_permanent_rejection(self) -> None: _inbound, parsed, candidate = parse_message_file(FIXTURES / "hard_bounce.eml", mailbox_id="test") self.assertEqual(parsed.message_class, MessageClass.HARD_BOUNCE) self.assertIsNotNone(candidate) self.assertEqual(candidate.event_type, "notification.endpoint.rejected_permanent") self.assertEqual(candidate.assessment_subclass, "fail.hard_bounce") def test_soft_bounce_maps_to_temporary_rejection(self) -> None: _inbound, parsed, candidate = parse_message_file(FIXTURES / "soft_bounce.eml", mailbox_id="test") self.assertEqual(parsed.message_class, MessageClass.SOFT_BOUNCE) self.assertIsNotNone(candidate) self.assertEqual(candidate.event_type, "notification.endpoint.rejected_temporary") def test_out_of_office_stays_undef(self) -> None: _inbound, parsed, candidate = parse_message_file(FIXTURES / "out_of_office.eml", mailbox_id="test") self.assertEqual(parsed.message_class, MessageClass.OUT_OF_OFFICE) self.assertIsNotNone(candidate) self.assertEqual(candidate.assessment_category.value, "undef") self.assertEqual(candidate.event_type, "interaction.out_of_office_received") def test_human_reply_is_email_channel_success_only(self) -> None: _inbound, parsed, candidate = parse_message_file(FIXTURES / "human_reply.eml", mailbox_id="test") self.assertEqual(parsed.message_class, MessageClass.HUMAN_REPLY) self.assertIsNotNone(candidate) self.assertEqual(candidate.event_type, "interaction.reply_received") self.assertEqual(candidate.assessment_subclass, "success.reply_received") if __name__ == "__main__": unittest.main()