예제 #1
0
def process_ingestion_emails():
    """
    Gets all new mail documents in the bucket and process each message.
    """
    processor = CalendarInteractionEmailProcessor()

    for message in get_mail_docs_in_bucket():
        source = message['source']
        try:
            documents.delete_document(bucket_id=BUCKET_ID,
                                      document_key=message['source'])
        except Exception as e:
            logger.exception('Error deleting message: "%s", error: "%s"',
                             source, e)
            continue

        try:
            email = mailparser.parse_from_bytes(message['content'])
            processed, reason = processor.process_email(message=email)
            if not processed:
                logger.error('Error parsing message: "%s", error: "%s"',
                             source, reason)
            else:
                logger.info(reason)
        except Exception as e:
            logger.exception('Error processing message: "%s", error: "%s"',
                             source, e)

        logger.info(
            'Successfully processed message "%s" and deleted document from bucket "%s"',
            source,
            BUCKET_ID,
        )
 def test_process_email_validation(
     self,
     interaction_data_overrides,
     expected_message,
     base_interaction_data_fixture,
     calendar_data_fixture,
     mock_notify_adviser_by_email,
     interaction_email_notification_feature_flag,
     mock_message,
     monkeypatch,
 ):
     """
     Test that process_email returns expected validation error messages when
     called with invalid data.
     """
     interaction_data = {**base_interaction_data_fixture, **interaction_data_overrides}
     self._get_email_parser_mock(interaction_data, monkeypatch)
     processor = CalendarInteractionEmailProcessor()
     result, message = processor.process_email(mock_message)
     assert result is False
     assert message == expected_message
     mock_notify_adviser_by_email.assert_called_once_with(
         Advisor.objects.filter(email=base_interaction_data_fixture['sender_email']).first(),
         Template.meeting_ingest_failure.value,
         context={
             'errors': [expected_message],
             'recipients': ', '.join(base_interaction_data_fixture['contact_emails']),
             'support_team_email': settings.DATAHUB_SUPPORT_EMAIL_ADDRESS,
         },
     )
 def test_process_email_meeting_exists(
     self,
     base_interaction_data_fixture,
     calendar_data_fixture,
     interaction_email_notification_feature_flag,
     mock_message,
     monkeypatch,
 ):
     """
     Test that process_email does not save another interaction when the meeting
     already exists as an interaction.
     """
     interaction_data = {**base_interaction_data_fixture}
     self._get_email_parser_mock(interaction_data, monkeypatch)
     processor = CalendarInteractionEmailProcessor()
     # Create the calendar interaction initially
     initial_result, initial_message = processor.process_email(mock_message)
     interaction_id = initial_message.split()[-1].strip('#')
     assert initial_result is True
     # Simulate processing the email again
     duplicate_result, duplicate_message = processor.process_email(mock_message)
     assert duplicate_result is False
     assert duplicate_message == 'Meeting already exists as an interaction'
     all_interactions_by_sender = Interaction.objects.filter(
         dit_participants__adviser=Advisor.objects.get(email=interaction_data['sender_email']),
     )
     assert all_interactions_by_sender.count() == 1
     assert all_interactions_by_sender[0].id == UUID(interaction_id)
 def test_process_email_parser_validation_error(
     self,
     base_interaction_data_fixture,
     calendar_data_fixture,
     mock_notify_adviser_by_email,
     interaction_email_notification_feature_flag,
     mock_message,
     monkeypatch,
     caplog,
     invalid_invite_exception_class,
     expected_to_notify,
 ):
     """
     Test that process_email returns an expected message when the parser
     raises a ValidationError.
     """
     caplog.set_level(logging.WARNING)
     interaction_data = {**base_interaction_data_fixture}
     mock_parser = self._get_email_parser_mock(interaction_data, monkeypatch)
     exception = invalid_invite_exception_class('There was a problem with the meeting format')
     mock_parser.side_effect = exception
     expected_exception_string = repr(exception)
     processor = CalendarInteractionEmailProcessor()
     result, message = processor.process_email(mock_message)
     assert result is False
     assert message == expected_exception_string
     expected_log = (
         'datahub.interaction.email_processors.processors',
         30,
         'Ingested email with ID "abc123" (received 2019-08-01T00:00:01) '
         f'was not valid: {expected_exception_string}',
     )
     assert expected_log in caplog.record_tuples
     if expected_to_notify:
         expected_error_message = (
             EXCEPTION_NOTIFY_MESSAGES[invalid_invite_exception_class]
         )
         mock_notify_adviser_by_email.assert_called_once_with(
             Advisor.objects.filter(
                 email=base_interaction_data_fixture['sender_email'],
             ).first(),
             Template.meeting_ingest_failure.value,
             context={
                 'errors': [expected_error_message],
                 'recipients': ', '.join(base_interaction_data_fixture['contact_emails']),
                 'support_team_email': settings.DATAHUB_SUPPORT_EMAIL_ADDRESS,
             },
         )
     else:
         mock_notify_adviser_by_email.assert_not_called()
    def test_process_email_successful(
        self,
        interaction_data_overrides,
        expected_subject,
        calendar_data_fixture,
        base_interaction_data_fixture,
        mock_notify_adviser_by_email,
        interaction_email_notification_feature_flag,
        mock_message,
        monkeypatch,
    ):
        """
        Test that process_email saves a draft interaction when the calendar
        parser yields good data.
        """
        interaction_data = {
            **base_interaction_data_fixture,
            **interaction_data_overrides,
        }
        email_parser_mock = self._get_email_parser_mock(interaction_data, monkeypatch)

        # Process the message and save a draft interaction
        processor = CalendarInteractionEmailProcessor()
        result, message = processor.process_email(mock_message)
        assert result is True
        interaction = Interaction.objects.get(source__meeting__id='12345')
        assert message == f'Successfully created interaction #{interaction.id}'

        # Verify dit_participants holds all of the advisers for the interaction
        expected_adviser_emails = {
            interaction_data['sender_email'],
            *interaction_data['secondary_adviser_emails'],
        }
        interaction_adviser_emails = {
            participant.adviser.email for participant
            in interaction.dit_participants.all()
        }
        assert interaction_adviser_emails == expected_adviser_emails

        # Verify contacts holds all of the expected contacts for the interaction
        interaction_contacts = interaction.contacts.all()
        email_contacts = email_parser_mock.return_value['contacts']
        for contact in email_contacts:
            if contact.company.name == interaction_data['top_company_name']:
                assert contact in interaction_contacts
        assert interaction.company.name == interaction_data['top_company_name']
        assert interaction.date == interaction_data['date']
        assert interaction.source == {
            'meeting': {'id': interaction_data['meeting_details']['uid']},
        }
        assert interaction.subject == expected_subject
        assert interaction.status == Interaction.Status.DRAFT

        sender_participant = interaction.dit_participants.get(
            adviser__email__iexact=interaction_data['sender_email'],
        )
        mock_notify_adviser_by_email.assert_called_once_with(
            sender_participant.adviser,
            Template.meeting_ingest_success.value,
            context={
                'interaction_url': interaction.get_absolute_url(),
                'recipients': '[email protected], [email protected]',
                'support_team_email': settings.DATAHUB_SUPPORT_EMAIL_ADDRESS,
            },
        )