def handle(self, *args, **kwargs): # Get the binary buffer behind the text one try: self.input_file = self.input_file.detach() except io.UnsupportedOperation: pass msg = message_from_bytes(self.input_file.read()) handler = MailProcessor(msg) handler.process()
def setUp(self): """Create a MailProcessor object""" self.msg = Message() self.processor = MailProcessor(self.msg) self.DOMAIN = settings.DISTRO_TRACKER_FQDN
class MailProcessorTest(TestCase, HelperMixin): def setUp(self): """Create a MailProcessor object""" self.msg = Message() self.processor = MailProcessor(self.msg) self.DOMAIN = settings.DISTRO_TRACKER_FQDN def _test_find_addr_with(self, field): to_addr = 'foo@{}'.format(self.DOMAIN) self.msg.add_header(field, to_addr) addr = self.processor.find_delivery_address(self.msg) self.assertEqual(to_addr, addr) def test_find_addr_with_delivered_to(self): """Delivered-To is found and used""" self._test_find_addr_with('Delivered-To') def test_find_addr_with_envelope_to(self): """Envelope-To is found and used""" self._test_find_addr_with('Envelope-To') def test_find_addr_with_x_original_to(self): """X-Original-To is found and used""" self._test_find_addr_with('X-Original-To') def test_find_addr_with_x_envelope_to(self): """X-Envelope-To is found and used""" self._test_find_addr_with('X-Envelope-To') @override_settings(DISTRO_TRACKER_FQDN='domain.test') def test_find_addr_ignores_bad_domain(self): """Headers pointing to domain that do not match the FQDN are ignored """ to_addr = 'foo@{}'.format(self.DOMAIN) # Entirely different domain should be ignored self.msg.add_header('Envelope-To', to_addr) self.msg.add_header('Delivered-To', to_addr) # Subdomains should be ignored too self.msg.add_header('Delivered-To', '*****@*****.**') addr = self.processor.find_delivery_address(self.msg) self.assertIsNone(addr) def test_find_addr_with_multiple_field_copies(self): """All copies of the same fields are parsed""" to_addr = 'foo@{}'.format(self.DOMAIN) self.msg.add_header('Delivered-To', 'foo@bar') self.msg.add_header('Delivered-To', to_addr) self.msg.add_header('Delivered-To', 'foo@baz') addr = self.processor.find_delivery_address(self.msg) self.assertEqual(to_addr, addr) def test_find_addr_conflicting(self): """Fails when encountering multiple headers with the same domain""" self.msg.add_header('Delivered-To', 'foo@{}'.format(self.DOMAIN)) self.msg.add_header('Delivered-To', 'bar@{}'.format(self.DOMAIN)) with self.assertRaises(ConflictingDeliveryAddresses): self.processor.find_delivery_address(self.msg) def test_find_addr_duplicate_non_conflicting(self): """Does not fail when encountering same address in different headers""" to_addr = 'foo@{}'.format(self.DOMAIN) self.msg.add_header('Delivered-To', to_addr) self.msg.add_header('X-Original-To', to_addr) addr = self.processor.find_delivery_address(self.msg) self.assertEqual(to_addr, addr) def test_identify_service_without_details(self): """identify_service(foo@bar) returns (foo, None)""" (service, details) = self.processor.identify_service('foo@bar') self.assertEqual(service, 'foo') self.assertIsNone(details) def test_identify_service_with_details(self): """identify_service(foo+baz@bar) returns (foo, baz)""" (service, details) = self.processor.identify_service('foo+baz@bar') self.assertEqual(service, 'foo') self.assertEqual(details, 'baz') def test_identify_service_with_details_with_plus(self): """identify_service(foo+baz+baz@bar) returns (foo, baz+baz)""" (service, details) = self.processor.identify_service('foo+baz+baz@bar') self.assertEqual(service, 'foo') self.assertEqual(details, 'baz+baz') def _test_process_for_addr(self, local_part, method_name, *args, **kwargs): self.msg.add_header('Delivered-To', '{}@{}'.format(local_part, self.DOMAIN)) with mock.patch.object(self.processor, method_name) as func: self.processor.process() func.assert_called_once_with(*args, **kwargs) def test_process_control(self): '''control@ is processed by handle_control()''' self._test_process_for_addr('control', 'handle_control') def test_process_dispatch(self): '''dispatch@ is processed by handle_dispatch(None, None)''' self._test_process_for_addr('dispatch', 'handle_dispatch', None, None) def test_process_dispatch_with_package(self): '''dispatch+foo@ is processed by handle_dispatch(foo, None)''' self._test_process_for_addr('dispatch+foo', 'handle_dispatch', 'foo', None) def test_process_dispatch_with_package_and_keyword(self): '''dispatch+foo_bar@ is processed by handle_dispatch(foo, bar)''' self._test_process_for_addr('dispatch+foo_bar', 'handle_dispatch', 'foo', 'bar') def test_process_bounces(self): '''bounces+foo@ is processed by handle_bounces()''' self._test_process_for_addr('bounces+foo', 'handle_bounces', 'foo') def test_process_without_delivery_address(self): '''process() fails when no delivery address can be identified''' with self.assertRaises(MissingDeliveryAddress): self.processor.process() @override_settings(DISTRO_TRACKER_ACCEPT_UNQUALIFIED_EMAILS=False) def test_process_unknown_service_fails(self): '''process() fails when delivery address is not a known service''' self.msg.add_header('Delivered-To', 'unknown@{}'.format(self.DOMAIN)) with self.assertRaises(InvalidDeliveryAddress): self.processor.process() @override_settings(DISTRO_TRACKER_ACCEPT_UNQUALIFIED_EMAILS=True) def test_process_unknown_service_works_as_dispatch(self): '''process() fails when delivery address is not a known service''' self._test_process_for_addr('unknown', 'handle_dispatch', 'unknown', None) def test_load_mail_from_file(self): '''loads the mail to process from a file''' mail_path = os.path.join(settings.DISTRO_TRACKER_DATA_PATH, 'a-mail') self.create_mail(mail_path, subject='load_mail') self.processor.load_mail_from_file(mail_path) self.assertEqual(self.processor.message['Subject'], 'load_mail') def test_init_with_filename(self): '''can create object with filename''' mail_path = os.path.join(settings.DISTRO_TRACKER_DATA_PATH, 'a-mail') self.create_mail(mail_path, subject='load_mail') mail_proc = MailProcessor(mail_path) self.assertIsInstance(mail_proc.message, Message)