Exemplo n.º 1
0
    def test_get_all_message_id_list_paged(self, get_http_mock):
        """
        Test the GmailConnector in retrieving all message id's without errors on the API call.
        Messages are paged and need two API calls.
        """
        mock_api_calls = [
            # Retrieve the history_id.
            HttpMock('lily/messaging/email/tests/data/get_history_id.json',
                     {'status': '200'}),
            # Retrieve a list of all the messages in the email box.
            HttpMock(
                'lily/messaging/email/tests/data/all_message_id_list_paged_1.json',
                {'status': '200'}),
            HttpMock(
                'lily/messaging/email/tests/data/all_message_id_list_paged_2.json',
                {'status': '200'}),
        ]

        # Mock the http instance with succesive http mock objects.
        get_http_mock.side_effect = mock_api_calls

        email_account = EmailAccount.objects.first()

        # Retrieve all messages.
        connector = GmailConnector(email_account)
        messages = connector.get_all_message_id_list()

        # Verify that all messages are retrieved and that the history id is set correct,
        self.assertEqual(
            len(messages), 10,
            "{0} Messages found, it should be {1}.".format(len(messages), 10))
        self.assertEqual(
            connector.history_id, u'8095',
            "History id {0} is incorrect, it should be {1}.".format(
                connector.history_id, 8095))
Exemplo n.º 2
0
    def test_execute_service_call_http_access_token_refresh_error(
            self, execute_service_mock):
        """
        Test if the execute service call raises an exception after it isn't able to get a correct access token
        and correctly deauthorizes the email account.
        """
        # Let the mocked execute service call raise an error.
        execute_service_mock.side_effect = HttpAccessTokenRefreshError()

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)
        try:
            # Execute service call.
            connector.execute_service_call(
                connector.gmail_service.service.users().messages().list(
                    userId='me',
                    quotaUser=email_account.id,
                    q='!in:chats',
                ))
            self.fail('HttpAccessTokenRefreshError should have been raised.')
        except HttpAccessTokenRefreshError:
            pass

        self.assertFalse(email_account.is_authorized,
                         "Email account shouldn't be authorized.")
Exemplo n.º 3
0
    def test_execute_service_call(self, get_http_mock):
        """
        Test if the execute service call returns the content of the json file.
        """
        # Mock the http instance.
        get_http_mock.return_value = HttpMock(
            'lily/messaging/email/tests/data/all_message_id_list_single_page.json',
            {'status': '200'})

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)

        # Execute service call.
        response = connector.execute_service_call(
            connector.gmail_service.service.users().messages().list(
                userId='me',
                quotaUser=email_account.id,
                q='!in:chats',
            ))

        # Verify that the service call returned the correct json object.
        with open(
                'lily/messaging/email/tests/data/all_message_id_list_single_page.json'
        ) as infile:
            json_obj = json.load(infile)
            self.assertEqual(response, json_obj)
Exemplo n.º 4
0
    def test_get_all_message_id_list_paged(self, get_http_mock):
        """
        Test the GmailConnector in retrieving all message id's without errors on the API call.
        Messages are paged and need two API calls.
        """
        mock_api_calls = [
            # Retrieve the history_id.
            HttpMock('lily/messaging/email/tests/data/get_history_id.json', {'status': '200'}),
            # Retrieve a list of all the messages in the email box.
            HttpMock('lily/messaging/email/tests/data/all_message_id_list_paged_1.json', {'status': '200'}),
            HttpMock('lily/messaging/email/tests/data/all_message_id_list_paged_2.json', {'status': '200'}),
        ]

        # Mock the http instance with succesive http mock objects.
        get_http_mock.side_effect = mock_api_calls

        email_account = EmailAccount.objects.first()

        # Retrieve all messages.
        connector = GmailConnector(email_account)
        messages = connector.get_all_message_id_list()

        # Verify that all messages are retrieved and that the history id is set correct,
        self.assertEqual(len(messages), 10, "{0} Messages found, it should be {1}.".format(len(messages), 10))
        self.assertEqual(connector.history_id, u'8095',
                         "History id {0} is incorrect, it should be {1}.".format(connector.history_id, 8095))
Exemplo n.º 5
0
    def test_execute_service_call_rate_limit_exceeded_once(
            self, get_http_mock):
        """
        Test if the execute service call returns the content of the json file after one rate limit error.
        """
        mock_api_calls = [
            # Simulate one rateLimitExceeded error.
            HttpMock('lily/messaging/email/tests/data/403.json',
                     {'status': '403'}),
            HttpMock(
                'lily/messaging/email/tests/data/all_message_id_list_single_page.json',
                {'status': '200'}),
        ]

        # Mock the http instance with succesive http mock objects.
        get_http_mock.side_effect = mock_api_calls

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)

        # Execute service call.
        response = connector.execute_service_call(
            connector.gmail_service.service.users().messages().list(
                userId='me',
                quotaUser=email_account.id,
                q='!in:chats',
            ))

        # Verify that the service call returned the correct json object.
        with open(
                'lily/messaging/email/tests/data/all_message_id_list_single_page.json'
        ) as infile:
            json_obj = json.load(infile)
            self.assertEqual(response, json_obj)
Exemplo n.º 6
0
    def test_execute_service_call_failed_service_call_exception(self, get_http_mock):
        """
        Test if the execute service call raises an exception after it fails after six rate limit errors.
        """
        mock_api_calls = [
            # Simulate one FailedServiceCallException by getting six times a rateLimitExceeded error.
            HttpMock('lily/messaging/email/tests/data/403.json', {'status': '403'}),
            HttpMock('lily/messaging/email/tests/data/403.json', {'status': '403'}),
            HttpMock('lily/messaging/email/tests/data/403.json', {'status': '403'}),
            HttpMock('lily/messaging/email/tests/data/403.json', {'status': '403'}),
            HttpMock('lily/messaging/email/tests/data/403.json', {'status': '403'}),
            HttpMock('lily/messaging/email/tests/data/403.json', {'status': '403'}),
        ]

        # Mock the http instance with succesive http mock objects.
        get_http_mock.side_effect = mock_api_calls

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)

        try:
            # Execute service call.
            connector.execute_service_call(
                connector.gmail_service.service.users().messages().list(
                    userId='me',
                    quotaUser=email_account.id,
                    q='!in:chats',
                ))
            self.fail('FailedServiceCallException should have been raised.')
        except FailedServiceCallException:
            pass
Exemplo n.º 7
0
    def test_cleanup(self, get_http_mock):
        """
        Test if the GmailConnector cleans up the right data.
        """

        mock_api_calls = [
            # Simulate one rateLimitExceeded error.
            HttpMock('lily/messaging/email/tests/data/get_history_id.json', {'status': '200'}),
            HttpMock('lily/messaging/email/tests/data/all_message_id_list_single_page.json', {'status': '200'}),
        ]

        get_http_mock.side_effect = mock_api_calls

        # Initialze a connector and retrieve the history id.
        email_account = EmailAccount.objects.first()
        connector = GmailConnector(email_account)
        connector.get_all_message_id_list()

        # Establish that the cleanup method up to test has actual data to cleanup.
        self.assertIsNotNone(connector.gmail_service)
        self.assertIsNotNone(connector.email_account)
        self.assertIsNotNone(connector.history_id)

        connector.cleanup()

        # Verify that data is cleaned up.
        self.assertIsNone(connector.gmail_service)
        self.assertIsNone(connector.email_account)
        self.assertIsNone(connector.history_id)
Exemplo n.º 8
0
    def test_execute_service_call_rate_limit_exceeded_once(self, get_http_mock):
        """
        Test if the execute service call returns the content of the json file after one rate limit error.
        """
        mock_api_calls = [
            # Simulate one rateLimitExceeded error.
            HttpMock('lily/messaging/email/tests/data/403.json', {'status': '403'}),
            HttpMock('lily/messaging/email/tests/data/all_message_id_list_single_page.json', {'status': '200'}),
        ]

        # Mock the http instance with succesive http mock objects.
        get_http_mock.side_effect = mock_api_calls

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)

        # Execute service call.
        response = connector.execute_service_call(
            connector.gmail_service.service.users().messages().list(
                userId='me',
                quotaUser=email_account.id,
                q='!in:chats',
            ))

        # Verify that the service call returned the correct json object.
        with open('lily/messaging/email/tests/data/all_message_id_list_single_page.json') as infile:
            json_obj = json.load(infile)
            self.assertEqual(response, json_obj)
Exemplo n.º 9
0
    def test_send_email_message_reply(self, get_http_mock):
        """
        Test the GmailConnector on replying on an email message.
        """
        message_id = '15af6279e8b72e9c'

        get_http_mock.return_value = HttpMock(
            'lily/messaging/email/tests/data/send_email_message_reply.json',
            {'status': '200'})

        email_account = EmailAccount.objects.first()
        email_outbox_message = """Content-Type: multipart/related;
 boundary="===============0529811256475331541=="
MIME-Version: 1.0
Subject: Mauris ex tortor, hendrerit non sem eu, mollis varius purus.
From: "Firstname Lastname" <*****@*****.**>
To: [email protected]

--===============0529811256475331541==
Content-Type: multipart/alternative;
 boundary="===============6835128886458232912=="
MIME-Version: 1.0

--===============6835128886458232912==
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit


In hac habitasse platea dictumst. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
himenaeos. Ut aliquet elit sed augue bibendum malesuada.

--===============6835128886458232912==
MIME-Version: 1.0
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: 7bit

<html><body><br/>In hac habitasse platea dictumst. Class aptent taciti sociosqu ad litora torquent per conubia nostra,
per inceptos himenaeos. Ut aliquet elit sed augue bibendum malesuada.</body></html>
--===============6835128886458232912==--

--===============0529811256475331541==--"""

        connector = GmailConnector(email_account)
        response = connector.send_email_message(email_outbox_message,
                                                message_id)

        # Verify that the service call returned the correct json object.
        with open(
                'lily/messaging/email/tests/data/send_email_message_reply.json'
        ) as infile:
            json_obj = json.load(infile)
            self.assertEqual(response, json_obj)
Exemplo n.º 10
0
    def test_send_email_message_reply(self, get_http_mock):
        """
        Test the GmailConnector on replying on an email message.
        """
        message_id = '15af6279e8b72e9c'

        get_http_mock.return_value = HttpMock('lily/messaging/email/tests/data/send_email_message_reply.json',
                                              {'status': '200'})

        email_account = EmailAccount.objects.first()
        email_outbox_message = """Content-Type: multipart/related;
 boundary="===============0529811256475331541=="
MIME-Version: 1.0
Subject: Mauris ex tortor, hendrerit non sem eu, mollis varius purus.
From: "Firstname Lastname" <*****@*****.**>
To: [email protected]

--===============0529811256475331541==
Content-Type: multipart/alternative;
 boundary="===============6835128886458232912=="
MIME-Version: 1.0

--===============6835128886458232912==
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit


In hac habitasse platea dictumst. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
himenaeos. Ut aliquet elit sed augue bibendum malesuada.

--===============6835128886458232912==
MIME-Version: 1.0
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: 7bit

<html><body><br/>In hac habitasse platea dictumst. Class aptent taciti sociosqu ad litora torquent per conubia nostra,
per inceptos himenaeos. Ut aliquet elit sed augue bibendum malesuada.</body></html>
--===============6835128886458232912==--

--===============0529811256475331541==--"""

        connector = GmailConnector(email_account)
        response = connector.send_email_message(email_outbox_message, message_id)

        # Verify that the service call returned the correct json object.
        with open('lily/messaging/email/tests/data/send_email_message_reply.json') as infile:
            json_obj = json.load(infile)
            self.assertEqual(response, json_obj)
Exemplo n.º 11
0
    def test_get_history_id(self, get_http_mock):
        """
        Test the GmailConnector in retrieving the history id.
        """
        get_http_mock.return_value = HttpMock('lily/messaging/email/tests/data/get_history_id.json', {'status': '200'})

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)
        response = connector.get_history_id()

        # Verify that the service call returned the correct json object.
        with open('lily/messaging/email/tests/data/get_history_id.json') as infile:
            json_obj = json.load(infile)
            self.assertEqual(response, json_obj)
Exemplo n.º 12
0
    def test_trash_email_message(self, get_http_mock):
        """
        Test the GmailConnector on trashing an email message.
        """
        message_id = '15af6279f554fd15'

        get_http_mock.return_value = HttpMock(
            'lily/messaging/email/tests/data/trash_email_message_{0}.json'.format(message_id), {'status': '200'})

        email_account = EmailAccount.objects.first()
        connector = GmailConnector(email_account)

        response = connector.trash_email_message(message_id)

        # Verify that the service call returned the correct json object.
        with open('lily/messaging/email/tests/data/trash_email_message_{0}.json'.format(message_id)) as infile:
            json_obj = json.load(infile)
            self.assertEqual(response, json_obj)
Exemplo n.º 13
0
    def test_save_history_id(self, get_http_mock):
        """
        Test the GmailConnector in saving the updated historty id to the email account.
        """
        get_http_mock.return_value = HttpMock('lily/messaging/email/tests/data/get_history_archived.json',
                                              {'status': '200'})

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)
        # First do a history update, so a new history id is retreived.
        connector.get_history()
        # Save the history id to the email account.
        connector.save_history_id()

        # Verify that the history is indeed saved on the email account.
        email_account.refresh_from_db()
        self.assertEqual(email_account.history_id, 8170)
Exemplo n.º 14
0
    def test_extracting_attachment(self, get_message_info_mock, get_attachment_mock):
        message_id = '16740205f39700d1'
        self.mock_get_message_info(get_message_info_mock, message_id)
        self.mock_get_attachment(get_attachment_mock, message_id)

        connector = GmailConnector(self.email_account)
        message_info = connector.get_message_info(message_id)

        payload = message_info['payload']

        body_html = get_body_html_from_payload(payload, message_id)
        attachments = get_attachments_from_payload(payload, body_html, message_id, connector)
        self.email_message.attachments.add(bulk=False, *attachments)

        get_message_info_mock.assert_called_once()
        get_attachment_mock.assert_called_once()

        self.assertEqual(len(attachments), 1)
Exemplo n.º 15
0
    def test_get_history_id(self, get_http_mock):
        """
        Test the GmailConnector in retrieving the history id.
        """
        get_http_mock.return_value = HttpMock(
            'lily/messaging/email/tests/data/get_history_id.json',
            {'status': '200'})

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)
        response = connector.get_history_id()

        # Verify that the service call returned the correct json object.
        with open('lily/messaging/email/tests/data/get_history_id.json'
                  ) as infile:
            json_obj = json.load(infile)
            self.assertEqual(response, json_obj)
Exemplo n.º 16
0
    def test_get_message_info(self, get_http_mock):
        """
        Test the GmailConnector in retrieving the info of a single email message.
        """
        get_http_mock.return_value = HttpMock('lily/messaging/email/tests/data/get_message_info_15a6008a4baa65f3.json',
                                              {'status': '200'})

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)
        response = connector.get_message_info('15a6008a4baa65f3')

        # Verify that the service call returned the correct json object.
        with open('lily/messaging/email/tests/data/get_message_info_15a6008a4baa65f3.json') as infile:
            json_obj = json.load(infile)
            self.assertEqual(response, json_obj)

        # Verify that the history id is not retrieved from the get API response.
        self.assertEqual(connector.history_id, None)
Exemplo n.º 17
0
    def test_get_short_message_info(self, get_http_mock):
        """
        Test the GmailConnector in retrieving the short message info for a specific email message.
        """
        message_id = '15a6008a4baa65f3'
        get_http_mock.return_value = HttpMock(
            'lily/messaging/email/tests/data/get_short_message_info_{0}_archived.json'
            .format(message_id), {'status': '200'})

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)
        response = connector.get_short_message_info(message_id)

        # Verify that the service call returned the correct json object.
        with open(
                'lily/messaging/email/tests/data/get_short_message_info_{0}_archived.json'
                .format(message_id)) as infile:
            json_obj = json.load(infile)
            self.assertEqual(response, json_obj)
Exemplo n.º 18
0
    def test_get_labels_and_thread_id_for_message_id(self, get_http_mock):
        """
        Test the GmailConnector in retrieving the short message info for a specific email message.
        """
        message_id = '15a6008a4baa65f3'
        get_http_mock.return_value = HttpMock(
            'lily/messaging/email/tests/data/'
            'get_labels_and_thread_id_for_message_id_{0}_archived.json'.format(message_id),
            {'status': '200'})

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)
        response = connector.get_labels_and_thread_id_for_message_id(message_id)

        # Verify that the service call returned the correct json object.
        with open('lily/messaging/email/tests/data/get_labels_and_thread_id_for_message_id_{0}_archived.json'.format(
                message_id)) as infile:
            json_obj = json.load(infile)
            self.assertEqual(response, json_obj)
Exemplo n.º 19
0
    def test_trash_email_message(self, get_http_mock):
        """
        Test the GmailConnector on trashing an email message.
        """
        message_id = '15af6279f554fd15'

        get_http_mock.return_value = HttpMock(
            'lily/messaging/email/tests/data/trash_email_message_{0}.json'.
            format(message_id), {'status': '200'})

        email_account = EmailAccount.objects.first()
        connector = GmailConnector(email_account)

        response = connector.trash_email_message(message_id)

        # Verify that the service call returned the correct json object.
        with open(
                'lily/messaging/email/tests/data/trash_email_message_{0}.json'.
                format(message_id)) as infile:
            json_obj = json.load(infile)
            self.assertEqual(response, json_obj)
Exemplo n.º 20
0
    def test_get_all_message_id_list_http_access_token_refresh_error(self, execute_service_call_mock):
        """
        Test the GmailConnector in retrieving all message id's with a HttpAccessTokenRefreshError on the API call.
        """
        execute_service_call_mock.side_effect = HttpAccessTokenRefreshError()

        email_account = EmailAccount.objects.first()

        messages = None
        connector = GmailConnector(email_account)

        # Retrieve all messages.
        try:
            messages = connector.get_all_message_id_list()
            self.fail('HttpAccessTokenRefreshError should have been raised.')
        except HttpAccessTokenRefreshError:
            pass

        # Verify that no messages are retrieved and that the history id is not set,
        self.assertIsNone(messages)
        self.assertIsNone(connector.history_id)
Exemplo n.º 21
0
    def test_get_all_message_id_list_failed_service_call_error(self, execute_service_call_mock):
        """
        Test the GmailConnector in retrieving all message id's with a FailedServiceCallException on the API call.
        """
        execute_service_call_mock.side_effect = FailedServiceCallException()

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)

        # Retrieve all messages.
        messages = None
        try:
            messages = connector.get_all_message_id_list()
            self.fail('FailedServiceCallException should have been raised.')
        except FailedServiceCallException:
            pass

        # Verify that no messages are retrieved and that the history id is not set,
        self.assertIsNone(messages)
        self.assertIsNone(connector.history_id)
Exemplo n.º 22
0
    def test_cleanup(self, get_http_mock):
        """
        Test if the GmailConnector cleans up the right data.
        """

        mock_api_calls = [
            # Simulate one rateLimitExceeded error.
            HttpMock('lily/messaging/email/tests/data/get_history_id.json',
                     {'status': '200'}),
            HttpMock(
                'lily/messaging/email/tests/data/all_message_id_list_single_page.json',
                {'status': '200'}),
        ]

        get_http_mock.side_effect = mock_api_calls

        # Initialze a connector and retrieve the history id.
        email_account = EmailAccount.objects.first()
        connector = GmailConnector(email_account)
        connector.get_all_message_id_list()

        # Establish that the cleanup method up to test has actual data to cleanup.
        self.assertIsNotNone(connector.gmail_service)
        self.assertIsNotNone(connector.email_account)
        self.assertIsNotNone(connector.history_id)

        connector.cleanup()

        # Verify that data is cleaned up.
        self.assertIsNone(connector.gmail_service)
        self.assertIsNone(connector.email_account)
        self.assertIsNone(connector.history_id)
Exemplo n.º 23
0
    def test_get_message_info(self, get_http_mock):
        """
        Test the GmailConnector in retrieving the info of a single email message.
        """
        get_http_mock.return_value = HttpMock(
            'lily/messaging/email/tests/data/get_message_info_15a6008a4baa65f3.json',
            {'status': '200'})

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)
        response = connector.get_message_info('15a6008a4baa65f3')

        # Verify that the service call returned the correct json object.
        with open(
                'lily/messaging/email/tests/data/get_message_info_15a6008a4baa65f3.json'
        ) as infile:
            json_obj = json.load(infile)
            self.assertEqual(response, json_obj)

        # Verify that the history id is not retrieved from the get API response.
        self.assertEqual(connector.history_id, None)
Exemplo n.º 24
0
    def test_get_all_message_id_list_failed_service_call_error(
            self, execute_service_call_mock):
        """
        Test the GmailConnector in retrieving all message id's with a FailedServiceCallException on the API call.
        """
        execute_service_call_mock.side_effect = FailedServiceCallException()

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)

        # Retrieve all messages.
        messages = None
        try:
            messages = connector.get_all_message_id_list()
            self.fail('FailedServiceCallException should have been raised.')
        except FailedServiceCallException:
            pass

        # Verify that no messages are retrieved and that the history id is not set,
        self.assertIsNone(messages)
        self.assertIsNone(connector.history_id)
Exemplo n.º 25
0
    def test_get_all_message_id_list_http_access_token_refresh_error(
            self, execute_service_call_mock):
        """
        Test the GmailConnector in retrieving all message id's with a HttpAccessTokenRefreshError on the API call.
        """
        execute_service_call_mock.side_effect = HttpAccessTokenRefreshError()

        email_account = EmailAccount.objects.first()

        messages = None
        connector = GmailConnector(email_account)

        # Retrieve all messages.
        try:
            messages = connector.get_all_message_id_list()
            self.fail('HttpAccessTokenRefreshError should have been raised.')
        except HttpAccessTokenRefreshError:
            pass

        # Verify that no messages are retrieved and that the history id is not set,
        self.assertIsNone(messages)
        self.assertIsNone(connector.history_id)
Exemplo n.º 26
0
    def test_execute_service_call_failed_service_call_exception(
            self, get_http_mock):
        """
        Test if the execute service call raises an exception after it fails after six rate limit errors.
        """
        mock_api_calls = [
            # Simulate one FailedServiceCallException by getting six times a rateLimitExceeded error.
            HttpMock('lily/messaging/email/tests/data/403.json',
                     {'status': '403'}),
            HttpMock('lily/messaging/email/tests/data/403.json',
                     {'status': '403'}),
            HttpMock('lily/messaging/email/tests/data/403.json',
                     {'status': '403'}),
            HttpMock('lily/messaging/email/tests/data/403.json',
                     {'status': '403'}),
            HttpMock('lily/messaging/email/tests/data/403.json',
                     {'status': '403'}),
            HttpMock('lily/messaging/email/tests/data/403.json',
                     {'status': '403'}),
        ]

        # Mock the http instance with succesive http mock objects.
        get_http_mock.side_effect = mock_api_calls

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)

        try:
            # Execute service call.
            connector.execute_service_call(
                connector.gmail_service.service.users().messages().list(
                    userId='me',
                    quotaUser=email_account.id,
                    q='!in:chats',
                ))
            self.fail('FailedServiceCallException should have been raised.')
        except FailedServiceCallException:
            pass
Exemplo n.º 27
0
    def test_execute_service_call_http_access_token_refresh_error(self, execute_service_mock):
        """
        Test if the execute service call raises an exception after it isn't able to get a correct access token
        and correctly deauthorizes the email account.
        """
        # Let the mocked execute service call raise an error.
        execute_service_mock.side_effect = HttpAccessTokenRefreshError()

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)
        try:
            # Execute service call.
            connector.execute_service_call(
                connector.gmail_service.service.users().messages().list(
                    userId='me',
                    quotaUser=email_account.id,
                    q='!in:chats',
                ))
            self.fail('HttpAccessTokenRefreshError should have been raised.')
        except HttpAccessTokenRefreshError:
            pass

        self.assertFalse(email_account.is_authorized, "Email account shouldn't be authorized.")
Exemplo n.º 28
0
    def test_execute_service_call(self, get_http_mock):
        """
        Test if the execute service call returns the content of the json file.
        """
        # Mock the http instance.
        get_http_mock.return_value = HttpMock('lily/messaging/email/tests/data/all_message_id_list_single_page.json',
                                              {'status': '200'})

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)

        # Execute service call.
        response = connector.execute_service_call(
            connector.gmail_service.service.users().messages().list(
                userId='me',
                quotaUser=email_account.id,
                q='!in:chats',
            ))

        # Verify that the service call returned the correct json object.
        with open('lily/messaging/email/tests/data/all_message_id_list_single_page.json') as infile:
            json_obj = json.load(infile)
            self.assertEqual(response, json_obj)
Exemplo n.º 29
0
    def test_save_history_id(self, get_http_mock):
        """
        Test the GmailConnector in saving the updated historty id to the email account.
        """
        get_http_mock.return_value = HttpMock(
            'lily/messaging/email/tests/data/get_history_archived.json',
            {'status': '200'})

        email_account = EmailAccount.objects.first()

        connector = GmailConnector(email_account)
        # First do a history update, so a new history id is retreived.
        connector.get_history()
        # Save the history id to the email account.
        connector.save_history_id()

        # Verify that the history is indeed saved on the email account.
        email_account.refresh_from_db()
        self.assertEqual(email_account.history_id, 8170)
Exemplo n.º 30
0
    def get(self, request, format=None):
        with tracer.trace('SearchView.get: parameter setup'):
            user = request.user

            # Search query.
            q = request.query_params.get('q', '').strip()

            # Paging parameters.
            page = request.query_params.get('page', '0')
            page = int(page) + 1
            size = int(request.query_params.get('size', '20'))
            sort = request.query_params.get('sort', '-sent_date')

            # Mail labeling parameters.
            label_id = request.query_params.get('label', None)

            account_ids = request.query_params.get('account', None)  # None means search in all owned email accounts.

        with tracer.trace('SearchView.get: email_accounts setup'):
            # Get a list of all email accounts added by the user or publicly shared with the user as a group inbox.
            email_accounts = get_shared_email_accounts(user, True)

            if account_ids:
                # Only search within the email accounts indicated by the account_ids parameter.
                account_ids = account_ids.split(',')
                email_accounts = email_accounts.filter(pk__in=account_ids)

            email_accounts = email_accounts.exclude(
                Q(is_active=False) |
                Q(is_deleted=True) |
                Q(is_authorized=False)
            )

        message_list = EmailMessage.objects

        if q:
            # System Gmail labels visible in Lily, where the user can search in.
            gmail_labels = [
                settings.GMAIL_LABEL_INBOX,
                settings.GMAIL_LABEL_SPAM,
                settings.GMAIL_LABEL_TRASH,
                settings.GMAIL_LABEL_SENT,
                settings.GMAIL_LABEL_DRAFT
            ]

            if label_id and label_id not in gmail_labels:
                # Also retrieve related user set labels because later the label name will be queried.
                email_accounts = email_accounts.prefetch_related('labels')

            # Prevent too much calls on the search api, so restrict number of search results per email account.
            max_results = 3 * size

            messages_ids = []

            with tracer.trace('SearchView.get: for all accounts'):
                for email_account in email_accounts:
                    if label_id:
                        with tracer.trace('SearchView.get: building q with label lookup'):
                            # Retrieve the label corresponding to the label_id, otherwise Gmail defaults to all mail.
                            label_name = label_id
                            if label_id not in gmail_labels:
                                # Retrieve the label name if label_id will differ from the user set label name.
                                try:
                                    label_name = email_account.labels.get(label_id=label_id).name
                                except EmailLabel.DoesNotExist:
                                    logger.error(
                                        "Incorrect label id {0} with search request for account {1}.".format(
                                            label_id,
                                            email_account
                                        )
                                    )
                                    # Failing label lookup within one account should not halt the complete search.
                                    continue

                            q = u"{0} {1}:{2}".format(q, 'label', label_name)

                    with tracer.trace('SearchView.get: retrieving message_ids by Gmail API'):
                        try:
                            connector = GmailConnector(email_account)
                            messages = connector.search(query=q, size=max_results)
                            messages_ids.extend([message['id'] for message in messages])
                        except (InvalidCredentialsError, NotFoundError, HttpAccessTokenRefreshError,
                                FailedServiceCallException) as e:
                            logger.error(
                                "Failed to search within account {0} with error: {1}.".format(email_account, e)
                            )
                            # Failing search within one account should not halt the complete search.
                            continue

                # Retrieve messages from the database.
                message_list = message_list.filter(
                    message_id__in=messages_ids,
                    account__in=email_accounts
                )

        with tracer.trace('SearchView.get: retrieving messages from db'):
            message_list = message_list.order_by(sort)

            # Exclude fields that aren't serialized and potential large.
            message_list = message_list.defer("body_html", "body_text", "snippet")

            # The serializer will query for account, sender and star label, so instead of the extra separate queries,
            # retrieve them now.
            message_list = message_list.select_related('account', 'sender')
            message_list = message_list.prefetch_related('labels', 'received_by')

            # It's possible Google search returns message_id's that aren't in the database (due to 'sync from now').
            actual_number_of_results = len(message_list)

        with tracer.trace('SearchView.get: serializing messages'):
            # Construct paginator.
            limit = size * page
            offset = limit - size
            message_list = message_list[offset:limit]

            serializer = EmailMessageListSerializer(message_list, many=True)

            result = {
                'hits': serializer.data,
                'total': actual_number_of_results,
            }

        return Response(result)
Exemplo n.º 31
0
    def get(self, request, format=None):
        user = request.user

        # Search query.
        q = request.query_params.get('q', '').strip()

        # Paging parameters.
        page = request.query_params.get('page', '0')
        page = int(page) + 1
        size = int(request.query_params.get('size', '20'))
        sort = request.query_params.get('sort', '-sent_date')

        # Mail labeling parameters.
        label_id = request.query_params.get('label', None)

        account_ids = request.query_params.get(
            'account', None)  # None means search in all owned email accounts.

        # Get a list of all email accounts added by the user or publicly shared with the user as a group inbox.
        email_accounts = get_shared_email_accounts(user, True)

        if account_ids:
            # Only search within the email accounts indicated by the account_ids parameter.
            account_ids = account_ids.split(',')
            email_accounts = email_accounts.filter(pk__in=account_ids)

        email_accounts = email_accounts.exclude(
            Q(is_active=False) | Q(is_deleted=True) | Q(is_authorized=False))

        message_list = EmailMessage.objects

        if q:
            # System Gmail labels visible in Lily, where the user can search in.
            gmail_labels = [
                settings.GMAIL_LABEL_INBOX, settings.GMAIL_LABEL_SPAM,
                settings.GMAIL_LABEL_TRASH, settings.GMAIL_LABEL_SENT,
                settings.GMAIL_LABEL_DRAFT
            ]

            if label_id and label_id not in gmail_labels:
                # Also retrieve related user set labels because later the label name will be queried.
                email_accounts = email_accounts.prefetch_related('labels')

            # Prevent too much calls on the search api, so restrict number of search results per email account.
            max_results = 3 * size

            messages_ids = []

            for email_account in email_accounts:
                if label_id:
                    # Retrieve the label corresponding to the label_id, otherwise Gmail defaults to all mail.
                    label_name = label_id
                    if label_id not in gmail_labels:
                        # Retrieve the label name if label_id will differ from the user set label name.
                        try:
                            label_name = email_account.labels.get(
                                label_id=label_id).name
                        except EmailLabel.DoesNotExist:
                            logger.error(
                                "Incorrect label id {0} with search request for account {1}."
                                .format(label_id, email_account))
                            # Failing label lookup within one account should not halt the complete search.
                            continue

                    q = u"{0} {1}:{2}".format(q, 'label', label_name)

                try:
                    connector = GmailConnector(email_account)
                    messages = connector.search(query=q, size=max_results)
                    messages_ids.extend(
                        [message['id'] for message in messages])
                except (InvalidCredentialsError, NotFoundError,
                        HttpAccessTokenRefreshError,
                        FailedServiceCallException) as e:
                    logger.error(
                        "Failed to search within account {0} with error: {1}.".
                        format(email_account, e))
                    # Failing search within one account should not halt the complete search.
                    continue

                # Retrieve messages from the database.
                message_list = message_list.filter(message_id__in=messages_ids,
                                                   account__in=email_accounts)

        message_list = message_list.order_by(sort)

        # Exclude fields that aren't serialized and potential large.
        message_list = message_list.defer("body_html", "body_text", "snippet")

        # The serializer will query for account, sender and star label, so instead of the extra separate queries,
        # retrieve them now.
        message_list = message_list.select_related('account', 'sender')
        message_list = message_list.prefetch_related('labels', 'received_by')

        # It's possible Google search returns message_id's that aren't in the database (due to 'sync from now').
        actual_number_of_results = len(message_list)

        # Construct paginator.
        limit = size * page
        offset = limit - size
        message_list = message_list[offset:limit]

        serializer = EmailMessageListSerializer(message_list, many=True)

        result = {
            'hits': serializer.data,
            'total': actual_number_of_results,
        }

        return Response(result)