Example #1
0
    def _exchange_online_delete_email_function(self, event, *args, **kwargs):
        """Function: Delete a message in the specified user's mailbox."""
        try:
            # Initialize the results payload
            rp = ResultPayload(CONFIG_DATA_SECTION, **kwargs)

            # Validate fields
            validate_fields(['exo_email_address', 'exo_messages_id'], kwargs)

            # Get the function parameters
            email_address = kwargs.get('exo_email_address')  # text
            mailfolders_id = kwargs.get('exo_mailfolders_id')  # text
            messages_id = kwargs.get('exo_messages_id')  # text

            LOG.info(u"exo_email_address: %s", email_address)
            LOG.info(u"exo_mailfolders_id: %s", mailfolders_id)
            LOG.info(u"exo_messages_id: %s", messages_id)

            yield StatusMessage(
                u"Starting delete message for email address: {}".format(
                    email_address))

            # Get the MS Graph helper class
            MS_graph_helper = MSGraphHelper(
                self.options.get("microsoft_graph_token_url"),
                self.options.get("microsoft_graph_url"),
                self.options.get("tenant_id"), self.options.get("client_id"),
                self.options.get("client_secret"),
                self.options.get("max_messages"),
                self.options.get("max_users"),
                self.options.get("max_retries_total", MAX_RETRIES_TOTAL),
                self.options.get("max_retries_backoff_factor",
                                 MAX_RETRIES_BACKOFF_FACTOR),
                self.options.get("max_batched_requests", MAX_BATCHED_REQUESTS),
                RequestsCommon(self.opts, self.options).get_proxies())

            # Call MS Graph API to get the user profile
            response = MS_graph_helper.delete_message(email_address,
                                                      mailfolders_id,
                                                      messages_id)

            # If message was deleted a 204 code is returned.
            if response.status_code == 204:
                success = True
                response_json = {'value': success}
            else:
                success = False
                response_json = response.json()

            results = rp.done(success, response_json)

            yield StatusMessage(
                u"Returning delete results for email address: {}".format(
                    email_address))

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception as err:
            LOG.error(err)
            yield FunctionError(err)
    def test_get_users(self, authenticate_mock, get_mock):
        """ Test Get User"""
        print("Test Get Users\n")

        try:
            authenticate_mock.return_value = True
            MS_graph_helper = MSGraphHelper(
                MOCKED_OPTS.get("microsoft_graph_token_url"),
                MOCKED_OPTS.get("microsoft_graph_url"),
                MOCKED_OPTS.get("tenant_id"), MOCKED_OPTS.get("client_id"),
                MOCKED_OPTS.get("client_secret"),
                MOCKED_OPTS.get("max_messages"), MOCKED_OPTS.get("max_users"),
                MOCKED_OPTS.get("max_retries_total"),
                MOCKED_OPTS.get("max_retries_backoff_factor"),
                MOCKED_OPTS.get("max_batched_requests"), None)
            content = {
                'value': [{
                    'userPrincipalName': '*****@*****.**'
                }, {
                    'userPrincipalName': '*****@*****.**'
                }]
            }
            get_mock.return_value = generate_response(content, 200)

            user_list = MS_graph_helper.get_users(None)
            assert len(user_list) == 2
            assert user_list[0] == '*****@*****.**'
            assert user_list[1] == '*****@*****.**'
        except IntegrationError as err:
            assert True
    def test_delete_message(self, authenticate_mock, delete_mock):
        """ Test """
        print("Test Delete Message\n")
        content = {"displayName": "Tester"}

        try:
            authenticate_mock.return_value = True
            MS_graph_helper = MSGraphHelper(
                MOCKED_OPTS.get("microsoft_graph_token_url"),
                MOCKED_OPTS.get("microsoft_graph_url"),
                MOCKED_OPTS.get("tenant_id"), MOCKED_OPTS.get("client_id"),
                MOCKED_OPTS.get("client_secret"),
                MOCKED_OPTS.get("max_messages"), MOCKED_OPTS.get("max_users"),
                MOCKED_OPTS.get("max_retries_total"),
                MOCKED_OPTS.get("max_retries_backoff_factor"),
                MOCKED_OPTS.get("max_batched_requests"), None)

            delete_mock.return_value = generate_response(content, 204)

            response = MS_graph_helper.delete_message("*****@*****.**",
                                                      None, "AAAA")
            assert response.status_code == 204

            delete_mock.return_value = generate_response(content, 300)
            response = MS_graph_helper.delete_message("*****@*****.**",
                                                      None, "AAAA")

        except IntegrationError as err:
            assert True
    def test_get_user_profile(self, authenticate_mock, get_mock):
        """ Test Get User Profile"""
        print("Test Get User Profile\n")

        try:
            authenticate_mock.return_value = True
            MS_graph_helper = MSGraphHelper(
                MOCKED_OPTS.get("microsoft_graph_token_url"),
                MOCKED_OPTS.get("microsoft_graph_url"),
                MOCKED_OPTS.get("tenant_id"), MOCKED_OPTS.get("client_id"),
                MOCKED_OPTS.get("client_secret"),
                MOCKED_OPTS.get("max_messages"), MOCKED_OPTS.get("max_users"),
                MOCKED_OPTS.get("max_retries_total"),
                MOCKED_OPTS.get("max_retries_backoff_factor"),
                MOCKED_OPTS.get("max_batched_requests"), None)
            content = {"displayName": "Tester"}

            # Test
            get_mock.return_value = generate_response(content, 200)
            response = MS_graph_helper.get_user_profile("*****@*****.**")
            assert response.status_code == 200
            assert response.content["displayName"] == "Tester"

            get_mock.return_value = generate_response(content, 404)
            response = MS_graph_helper.get_user_profile("*****@*****.**")
            assert response.status_code == 404
            assert response.content["displayName"] == "Tester"

            get_mock.return_value = generate_response(content, 300)
            response = MS_graph_helper.get_user_profile("*****@*****.**")

        except IntegrationError as err:
            assert True
    def _exchange_online_query_emails_function(self, event, *args, **kwargs):
        """Function: This function will query Exchange Online to find emails matching the specified input parameters."""
        try:
            # Initialize the results payload
            rp = ResultPayload(CONFIG_DATA_SECTION, **kwargs)

            # Validate fields
            validate_fields(['exo_email_address'], kwargs)

            # Get the function parameters
            email_address = kwargs.get('exo_email_address')  # text
            mail_folders = kwargs.get('exo_mail_folders')  # text
            sender = kwargs.get('exo_email_address_sender')  # text
            start_date = kwargs.get('exo_start_date')  # datetime
            end_date = kwargs.get('exo_end_date')  # datetime
            has_attachments = kwargs.get('exo_has_attachments')  # bool
            message_subject = kwargs.get('exo_message_subject')  # text
            message_body = kwargs.get('exo_message_body')  # text

            LOG.info(u"exo_email_address: %s", email_address)
            LOG.info(u"exo_mailfolders: %s", mail_folders)
            LOG.info(u"exo_email_address_sender: %s", sender)
            LOG.info(u"exo_start_date: %s", start_date)
            LOG.info(u"exo_end_date: %s", end_date)
            LOG.info(u"exo_email_has_attachments: %s", has_attachments)
            LOG.info(u"exo_message_subject: %s", message_subject)
            LOG.info(u"exo_message_body: %s", message_body)

            yield StatusMessage(u"Starting message query.")

            # Get the MS Graph helper class
            MS_graph_helper = MSGraphHelper(
                self.options.get("microsoft_graph_token_url"),
                self.options.get("microsoft_graph_url"),
                self.options.get("tenant_id"), self.options.get("client_id"),
                self.options.get("client_secret"),
                self.options.get("max_messages"),
                self.options.get("max_users"),
                RequestsCommon(self.opts, self.options).get_proxies())

            email_results = MS_graph_helper.query_messages(
                email_address, mail_folders, sender, start_date, end_date,
                has_attachments, message_subject, message_body)

            # Put query results in the results payload.
            results = rp.done(True, email_results)

            yield StatusMessage(u"Returning results from query.")

            LOG.debug(json.dumps(results['content']))

            # Produce a FunctionResult with the results
            yield FunctionResult(results)

        except Exception as err:
            LOG.error(err)
            yield FunctionError(err)
    def _exchange_online_send_message_function(self, event, *args, **kwargs):
        """Function: This function will create a message and send to the specified recipients."""
        try:
            rp = ResultPayload(CONFIG_DATA_SECTION, **kwargs)

            # Validate fields
            validate_fields(['exo_email_address', 'exo_recipients'], kwargs)

            # Get the function parameters:
            email_address = kwargs.get("exo_email_address")  # text
            recipients = kwargs.get("exo_recipients")  # text
            message_subject = kwargs.get("exo_message_subject")  # text
            message_body = kwargs.get("exo_message_body")  # text

            log = logging.getLogger(__name__)
            log.info(u"exo_email_address: %s", email_address)
            log.info(u"exo_recipients: %s", recipients)
            log.info(u"exo_message_subject: %s", message_subject)
            log.info(u"exo_message_body: %s", message_body)

            yield StatusMessage(u"Starting send message from email address: {}".format(email_address))

            # Get the MS Graph helper class
            MS_graph_helper = MSGraphHelper(self.options.get("microsoft_graph_token_url"),
                                            self.options.get("microsoft_graph_url"),
                                            self.options.get("tenant_id"),
                                            self.options.get("client_id"),
                                            self.options.get("client_secret"),
                                            self.options.get("max_messages"),
                                            self.options.get("max_users"),
                                            self.options.get("max_retries_total", MAX_RETRIES_TOTAL),
                                            self.options.get("max_retries_backoff_factor", MAX_RETRIES_BACKOFF_FACTOR),
                                            self.options.get("max_batched_requests", MAX_BATCHED_REQUESTS),
                                            RequestsCommon(self.opts, self.options).get_proxies())

            # Call MS Graph API to send the message
            response = MS_graph_helper.send_message(email_address, recipients, message_subject, message_body)

            # If message was sent a 202 code is returned...nothing is returned in the response.
            if response.status_code == 202:
                success = True
                response_json = {'value': success}
            else:
                success = False
                response_json = response.json()

            results = rp.done(success, response_json)

            yield StatusMessage(u"Returning send mail results by email address: {}".format(email_address))

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception as err:
            LOG.error(err)
            yield FunctionError(err)
    def _exchange_online_get_message_function(self, event, *args, **kwargs):
        """Function: This function returns the contents of an Exchange Online message."""
        try:
            # Initialize the results payload
            rp = ResultPayload(CONFIG_DATA_SECTION, **kwargs)

            # Validate fields
            validate_fields(['exo_email_address', 'exo_messages_id'], kwargs)

            # Get the function parameters:
            email_address = kwargs.get("exo_email_address")  # text
            message_id = kwargs.get("exo_messages_id")  # text

            LOG.info(u"exo_email_address: %s", email_address)
            LOG.info(u"exo_messages_id: %s", message_id)

            yield StatusMessage(
                u"Starting get message for email address: {}".format(
                    email_address))

            # Get the MS Graph helper class
            MS_graph_helper = MSGraphHelper(
                self.options.get("microsoft_graph_token_url"),
                self.options.get("microsoft_graph_url"),
                self.options.get("tenant_id"), self.options.get("client_id"),
                self.options.get("client_secret"),
                self.options.get("max_messages"),
                self.options.get("max_users"),
                RequestsCommon(self.opts, self.options).get_proxies())

            # Call MS Graph API to get the user profile
            response = MS_graph_helper.get_message(email_address, message_id)

            response_json = response.json()
            results = rp.done(True, response_json)

            # Add pretty printed string for easier to read output text in note.
            pretty_string = json.dumps(response_json,
                                       ensure_ascii=False,
                                       sort_keys=True,
                                       indent=4,
                                       separators=(',', ': '))
            results['pretty_string'] = pretty_string

            yield StatusMessage(
                u"Returning results for get message for email address: {}".
                format(email_address))

            LOG.debug(json.dumps(pretty_string))

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception as err:
            LOG.error(err)
            yield FunctionError(err)
    def _exchange_online_move_message_to_folder_function(self, event, *args, **kwargs):
        """Function: This function will move an Exchange Online message to the specified folder in the users mailbox."""
        try:
            # Initialize the results payload
            rp = ResultPayload(CONFIG_DATA_SECTION, **kwargs)

            # Validate fields
            validate_fields(['exo_email_address', 'exo_messages_id', 'exo_destination_mailfolder_id'], kwargs)

            # Get the function parameters:
            email_address = kwargs.get("exo_email_address")  # text
            message_id = kwargs.get("exo_messages_id")  # text
            mailfolders_id = kwargs.get("exo_mailfolders_id")  # text
            destination_id = kwargs.get("exo_destination_mailfolder_id")  # text

            LOG.info(u"exo_email_address: %s", email_address)
            LOG.info(u"exo_messages_id: %s", message_id)
            LOG.info(u"exo_mailfolders_id: %s", mailfolders_id)
            LOG.info(u"exo_destination_id: %s", destination_id)

            yield StatusMessage(u"Starting move message for email address: {} to mail folder {}".format(email_address, destination_id))

            # Get the MS Graph helper class
            MS_graph_helper = MSGraphHelper(self.options.get("microsoft_graph_token_url"),
                                            self.options.get("microsoft_graph_url"),
                                            self.options.get("tenant_id"),
                                            self.options.get("client_id"),
                                            self.options.get("client_secret"),
                                            self.options.get("max_messages"),
                                            self.options.get("max_users"),
                                            RequestsCommon(self.opts, self.options).get_proxies())

            # Call MS Graph API to get the user profile
            response = MS_graph_helper.move_message(email_address, mailfolders_id, message_id, destination_id)

            # If message was deleted a 201 code is returned.
            if response.status_code == 201:
                success = True
                new_message_id = response.json().get('id')
                response_json = {'new_message_id': new_message_id}
            else:
                success = False
                response_json = response.json()

            results = rp.done(success, response_json)

            yield StatusMessage(u"Returning delete results for email address: {}".format(email_address))

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception as err:
            LOG.error(err)
            yield FunctionError(err)
def selftest_function(opts):
    """
    Placeholder for selftest function. An example use would be to test package api connectivity.
    Suggested return values are be unimplemented, success, or failure.
    """
    # Get app.config parameters.
    options = opts.get(CONFIG_DATA_SECTION, {})

    validate_fields([
        'microsoft_graph_token_url', 'microsoft_graph_url', 'tenant_id',
        'client_id', 'client_secret', 'max_messages', 'max_users'
    ], options)

    # Read configuration settings:
    token_url = options['microsoft_graph_token_url']
    graph_url = options['microsoft_graph_url']
    tenant_id = options['tenant_id']
    client_id = options['client_id']
    client_secret = options['client_secret']
    max_messages = options['max_messages']
    max_users = options['max_users']

    try:
        log.info(u'Calling MS Graph API with: \n token_url: ' + token_url +
                 u'\n MS Graph API url: ' + graph_url + u'\n tenant_id: ' +
                 tenant_id + u'\n client_id: ' + client_id +
                 u'\n max_messages: ' + max_messages + u'\n max_users: ' +
                 max_users)

        state, reason = "", ""

        # Create MSGraphHelper class object
        ms_graph_helper = MSGraphHelper(
            token_url, graph_url, tenant_id, client_id, client_secret,
            max_messages, max_users,
            RequestsCommon(opts, options).get_proxies())

        # Get a MS Graph session token
        session_token = ms_graph_helper.authenticate()

        if ms_graph_helper and session_token:
            state = "success"
        else:
            state = "failure"
            reason = "N/A"
    except IntegrationError as err:
        state = "failure"
        reason = err.value

    result = {"state": state, "reason": reason}

    log.info(result)
    return result
Example #10
0
    def _exchange_online_get_email_user_profile_function(self, event, *args, **kwargs):
        """Function: This function will get Exchange Online user profile for a given email address."""
        try:
            # Initialize the results payload
            rp = ResultPayload(CONFIG_DATA_SECTION, **kwargs)

            # Validate fields
            validate_fields(['exo_email_address'], kwargs)

            # Get the function parameters
            email_address = kwargs.get('exo_email_address')  # text

            LOG.info(u"exo_email_address: %s", email_address)

            yield StatusMessage(u"Starting user profile query for email address: {}".format(email_address))

            # Get the MS Graph helper class
            # Get the MS Graph helper class
            MS_graph_helper = MSGraphHelper(self.options.get("microsoft_graph_token_url"),
                                            self.options.get("microsoft_graph_url"),
                                            self.options.get("tenant_id"),
                                            self.options.get("client_id"),
                                            self.options.get("client_secret"),
                                            self.options.get("max_messages"),
                                            self.options.get("max_users"),
                                            self.options.get("max_retries_total", MAX_RETRIES_TOTAL),
                                            self.options.get("max_retries_backoff_factor", MAX_RETRIES_BACKOFF_FACTOR),
                                            self.options.get("max_batched_requests", MAX_BATCHED_REQUESTS),
                                            RequestsCommon(self.opts, self.options).get_proxies())
            # Call MS Graph API to get the user profile
            response = MS_graph_helper.get_user_profile(email_address)

            response_json = response.json()
            results = rp.done(True, response_json)

            # Add pretty printed string for easier to read output text in note.
            pretty_string = json.dumps(response_json, ensure_ascii=False, sort_keys=True, indent=4,
                                       separators=(',', ': '))
            results['pretty_string'] = pretty_string

            yield StatusMessage(u"Returning user profile results for email address: {}".format(email_address))

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception as err:
            LOG.error(err)
            yield FunctionError(err)
    def test_build_query_url(self, authenticate_mock):
        """ Test Build Query URL"""
        print("Test build MS Graph Query URL\n")
        try:
            authenticate_mock.return_value = True
            MS_graph_helper = MSGraphHelper(
                MOCKED_OPTS.get("microsoft_graph_token_url"),
                MOCKED_OPTS.get("microsoft_graph_url"),
                MOCKED_OPTS.get("tenant_id"), MOCKED_OPTS.get("client_id"),
                MOCKED_OPTS.get("client_secret"),
                MOCKED_OPTS.get("max_messages"), MOCKED_OPTS.get("max_users"),
                MOCKED_OPTS.get("max_retries_total"),
                MOCKED_OPTS.get("max_retries_backoff_factor"),
                MOCKED_OPTS.get("max_batched_requests"), None)

            # Param list: email_address, mail_folder, sender, start_date, end_date, has_attachments, message_subject,
            # message_body
            # Test sender, hasAttachments, message subject
            url = MS_graph_helper.build_MS_graph_query_url(
                "*****@*****.**", None, "*****@*****.**", None, None,
                True, "lunch", None)
            assert url == u'microsoft_graph_url/users/[email protected]/messages?$filter=(from/emailAddress/address%20eq%20\'[email protected]\')%20and%20(hasAttachments%20eq%20true)%20and%20(contains(subject,\'lunch\'))'

            # Test $search in query (message body)
            url = MS_graph_helper.build_MS_graph_query_url(
                "*****@*****.**", None, "*****@*****.**", None, None,
                True, None, "lunch")
            assert url == u'microsoft_graph_url/users/[email protected]/messages?$search="lunch"&?$filter=(from/emailAddress/address%20eq%20\'[email protected]\')%20and%20(hasAttachments%20eq%20true)'

            # Test query: sender, start date, hasAttachments
            url = MS_graph_helper.build_MS_graph_query_url(
                "*****@*****.**", None, "*****@*****.**",
                1577854800000, None, True, None, None)
            #assert url == u'microsoft_graph_url/users/[email protected]/messages?$filter=(receivedDateTime%20ge%202020-01-01T00:00:00Z)%20and%20(from/emailAddress/address%20eq%20"*****@*****.**")%20and%20(hasAttachments%20eq%20true)'

            # Test $search in query (sender, start date, hasAttachments)
            url = MS_graph_helper.build_MS_graph_query_url(
                "*****@*****.**", None, "*****@*****.**",
                1577854800000, None, None, None, "lunch")

            #assert url == u'microsoft_graph_url/users/[email protected]/messages?$search="lunch"&?$filter=(receivedDateTime%20ge%202020-01-01T00:00:00Z)%20and%20(from/emailAddress/address%20eq%20"*****@*****.**")'

            # Test $search in query sender, start and end date
            url = MS_graph_helper.build_MS_graph_query_url(
                "*****@*****.**", None, "*****@*****.**",
                1577854800000, 1577895870000, None, None, "lunch")

            #assert url == u'microsoft_graph_url/users/[email protected]/messages?$search="lunch"&?$filter=(receivedDateTime%20ge%202020-01-01T00:00:00Z)%20and%20(receivedDateTime%20le%202020-01-01T11:24:30Z)%20and%20(from/emailAddress/address%20eq%20"*****@*****.**")'

            # No query parameters will cause IntegrationError
            url = MS_graph_helper.build_MS_graph_query_url(
                "*****@*****.**", None, None, None, None, None, None,
                None)
        except IntegrationError as err:
            assert True
    def test_query_messages(self, authenticate_mock, mocked_get):
        """ Test Query Message Single User"""
        print("Test Query Messages Single User\n")
        try:
            authenticate_mock.return_value = True
            MS_graph_helper = MSGraphHelper(
                MOCKED_OPTS.get("microsoft_graph_token_url"),
                MOCKED_OPTS.get("microsoft_graph_url"),
                MOCKED_OPTS.get("tenant_id"), MOCKED_OPTS.get("client_id"),
                MOCKED_OPTS.get("client_secret"),
                MOCKED_OPTS.get("max_messages"), MOCKED_OPTS.get("max_users"),
                MOCKED_OPTS.get("max_retries_total"),
                MOCKED_OPTS.get("max_retries_backoff_factor"),
                MOCKED_OPTS.get("max_batched_requests"), None)

            # Mock the email lists for user 1
            content1 = {'value': [{'id': 'AAA'}, {'id': 'BBB'}]}

            mocked_get.side_effect = [generate_response(content1, 200)]

            result_list = MS_graph_helper.query_messages(
                "*****@*****.**", None, "*****@*****.**", None, None,
                None, "lunch", None)
            assert len(result_list) == 1
            assert result_list[0]['email_address'] == '*****@*****.**'
            assert result_list[0]['status_code'] == 200
            assert result_list[0]['email_list'][0]['id'] == 'AAA'
            assert result_list[0]['email_list'][1]['id'] == 'BBB'

            mocked_get.side_effect = [generate_response(content1, 404)]
            result_list = MS_graph_helper.query_messages(
                "*****@*****.**", None, None, None, None, None, "lunch",
                None)
            assert len(result_list) == 0

            mocked_get.side_effect = [generate_response(content1, 300)]
            result_list = MS_graph_helper.query_messages(
                "*****@*****.**", None, None, None, None, None, "lunch",
                None)
        except IntegrationError as err:
            assert True
Example #13
0
    def _exchange_online_delete_messages_from_query_results_function(self, event, *args, **kwargs):
        """Function: This Exchange Online function will delete a list of messages returned from the
        Query Message function.  The input to the function is a string containing the JSON results
        from the Query Messages function."""
        try:
            # Initialize the results payload
            rp = ResultPayload(CONFIG_DATA_SECTION, **kwargs)

            # Validate fields
            validate_fields(['exo_query_messages_results'], kwargs)

            # Get the function parameters
            query_results = kwargs.get('exo_query_messages_results')  # text

            LOG.info(u"exo_query_messages_results: %s", query_results)

            yield StatusMessage(u"Starting delete messages for query results")

            # Get the MS Graph helper class
            MS_graph_helper = MSGraphHelper(self.options.get("microsoft_graph_token_url"),
                                            self.options.get("microsoft_graph_url"),
                                            self.options.get("tenant_id"),
                                            self.options.get("client_id"),
                                            self.options.get("client_secret"),
                                            self.options.get("max_messages"),
                                            self.options.get("max_users"),
                                            RequestsCommon(self.opts, self.options).get_proxies())

            # Delete messages found in the query.
            delete_results = MS_graph_helper.delete_messages_from_query_results(query_results)

            results = rp.done(True, delete_results)

            yield StatusMessage(u"Returning Delete Messages From Query Results results.")

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception as err:
            LOG.error(err)
            yield FunctionError(err)
    def test_move_message(self, authenticate_mock, post_mock):
        """ Test Move Message"""
        print("Test Move Message\n")
        content = {"displayName": "Tester"}

        try:
            authenticate_mock.return_value = True
            MS_graph_helper = MSGraphHelper(
                MOCKED_OPTS.get("microsoft_graph_token_url"),
                MOCKED_OPTS.get("microsoft_graph_url"),
                MOCKED_OPTS.get("tenant_id"), MOCKED_OPTS.get("client_id"),
                MOCKED_OPTS.get("client_secret"),
                MOCKED_OPTS.get("max_messages"), MOCKED_OPTS.get("max_users"),
                MOCKED_OPTS.get("max_retries_total"),
                MOCKED_OPTS.get("max_retries_backoff_factor"),
                MOCKED_OPTS.get("max_batched_requests"), None)

            post_mock.return_value = generate_response(content, 201)

            response = MS_graph_helper.move_message(
                "*****@*****.**", None, "AAA",
                {'name': "recoverableitemsdeletions"})
            assert response.status_code == 201
            assert response.content["displayName"] == "Tester"

            post_mock.return_value = generate_response(content, 404)
            response = MS_graph_helper.move_message(
                "*****@*****.**", None, "AAA",
                {'name': "recoverableitemsdeletions"})
            assert response.status_code == 404
            assert response.content["displayName"] == "Tester"

            post_mock.return_value = generate_response(content, 300)
            response = MS_graph_helper.move_message(
                "*****@*****.**", None, "AAA",
                {'name': "recoverableitemsdeletions"})

        except IntegrationError as err:
            assert True
Example #15
0
    def _exchange_online_create_meeting_function(self, event, *args, **kwargs):
        """Function: This function will create a meeting event and sent a mail message to the meeting participants."""
        try:
            # Initialize the results payload
            rp = ResultPayload(CONFIG_DATA_SECTION, **kwargs)

            # Validate fields
            validate_fields([
                'exo_meeting_email_address', 'exo_meeting_start_time',
                'exo_meeting_end_time', 'exo_meeting_subject',
                'exo_meeting_body'
            ], kwargs)

            # Get the function parameters:
            email_address = kwargs.get("exo_meeting_email_address")  # text
            start_time = kwargs.get("exo_meeting_start_time")  # datetimepicker
            end_time = kwargs.get("exo_meeting_end_time")  # datetimepicker
            subject = kwargs.get("exo_meeting_subject")  # text
            body = kwargs.get("exo_meeting_body")  # text
            required_attendees = kwargs.get(
                "exo_meeting_required_attendees")  # text
            optional_attendees = kwargs.get(
                "exo_meeting_optional_attendees")  # text
            location = kwargs.get("exo_meeting_location")  # text

            LOG.info(u"exo_meeting_email_address: %s", email_address)
            LOG.info(u"exo_meeting_start_time: %s", start_time)
            LOG.info(u"exo_meeting_end_time: %s", end_time)
            LOG.info(u"exo_meeting_subject: %s", subject)
            LOG.info(u"exo_meeting_body: %s", body)
            LOG.info(u"exo_meeting_required_attendees: %s", required_attendees)
            LOG.info(u"exo_meeting_optional_attendees: %s", optional_attendees)
            LOG.info(u"exo_meeting_location: %s", location)

            # Validate the meeting start/end time
            if start_time >= end_time:
                raise IntegrationError(
                    "Exchange Online meeting start time is behind end time.")

            # Check meeting time is not in the past.
            now_utc = datetime.datetime.utcnow()
            meeting_time_utc = datetime.datetime.utcfromtimestamp(start_time /
                                                                  1000)
            if now_utc > meeting_time_utc:
                raise IntegrationError(
                    "Exchange Online meeting start date/time is in the past.")

            yield StatusMessage(
                u"Starting create meeting for email address: {}".format(
                    email_address))

            # Get the MS Graph helper class
            MS_graph_helper = MSGraphHelper(
                self.options.get("microsoft_graph_token_url"),
                self.options.get("microsoft_graph_url"),
                self.options.get("tenant_id"), self.options.get("client_id"),
                self.options.get("client_secret"),
                self.options.get("max_messages"),
                self.options.get("max_users"),
                self.options.get("max_retries_total", MAX_RETRIES_TOTAL),
                self.options.get("max_retries_backoff_factor",
                                 MAX_RETRIES_BACKOFF_FACTOR),
                self.options.get("max_batched_requests", MAX_BATCHED_REQUESTS),
                RequestsCommon(self.opts, self.options).get_proxies())

            # Call MS Graph API to get the user profile
            response = MS_graph_helper.create_meeting(
                email_address, start_time, end_time, subject, body,
                required_attendees, optional_attendees, location)

            if response.status_code == 201:
                success = True
            else:
                success = False

            response_json = response.json()

            results = rp.done(success, response_json)

            # Add pretty printed string for easier to read output text in note.
            pretty_string = json.dumps(response_json,
                                       ensure_ascii=False,
                                       indent=4,
                                       separators=(',', ': '))
            results['pretty_string'] = pretty_string

            yield StatusMessage(
                u"Returning create meeting results for email address: {}".
                format(email_address))

            # Produce a FunctionResult with the results
            yield FunctionResult(results)

        except Exception as err:
            LOG.error(err)
            yield FunctionError(err)
Example #16
0
    def _exchange_online_query_emails_function(self, event, *args, **kwargs):
        """Function: This function will query Exchange Online to find emails matching the specified input parameters."""
        try:
            # Initialize the results payload
            rp = ResultPayload(CONFIG_DATA_SECTION, **kwargs)

            # Validate fields
            validate_fields(['exo_email_address', 'exo_query_output_format'],
                            kwargs)

            # Get the function parameters
            incident_id = kwargs.get('incident_id')  # number
            email_address = kwargs.get('exo_email_address')  # text
            mail_folders = kwargs.get('exo_mail_folders')  # text
            sender = kwargs.get('exo_email_address_sender')  # text
            start_date = kwargs.get('exo_start_date')  # datetime
            end_date = kwargs.get('exo_end_date')  # datetime
            has_attachments = kwargs.get('exo_has_attachments')  # bool
            message_subject = kwargs.get('exo_message_subject')  # text
            message_body = kwargs.get('exo_message_body')  # text
            query_output_format = self.get_select_param(
                kwargs.get('exo_query_output_format')
            )  # select values: "Exchange Online data table", "Incident attachment", "Incident note"

            LOG.info(u"incident_id: %s", str(incident_id))
            LOG.info(u"exo_email_address: %s", email_address)
            LOG.info(u"exo_mailfolders: %s", mail_folders)
            LOG.info(u"exo_email_address_sender: %s", sender)
            LOG.info(u"exo_start_date: %s", start_date)
            LOG.info(u"exo_end_date: %s", end_date)
            LOG.info(u"exo_email_has_attachments: %s", has_attachments)
            LOG.info(u"exo_message_subject: %s", message_subject)
            LOG.info(u"exo_message_body: %s", message_body)
            LOG.info(u"exo_query_output_format: %s", query_output_format)

            yield StatusMessage(u"Starting message query.")

            # Get the MS Graph helper class
            MS_graph_helper = MSGraphHelper(
                self.options.get("microsoft_graph_token_url"),
                self.options.get("microsoft_graph_url"),
                self.options.get("tenant_id"), self.options.get("client_id"),
                self.options.get("client_secret"),
                self.options.get("max_messages"),
                self.options.get("max_users"),
                self.options.get("max_retries_total", MAX_RETRIES_TOTAL),
                self.options.get("max_retries_backoff_factor",
                                 MAX_RETRIES_BACKOFF_FACTOR),
                self.options.get("max_batched_requests", MAX_BATCHED_REQUESTS),
                RequestsCommon(self.opts, self.options).get_proxies())

            email_results = MS_graph_helper.query_messages(
                email_address, mail_folders, sender, start_date, end_date,
                has_attachments, message_subject, message_body)

            query_results = {
                "incident_id": incident_id,
                "exo_query_output_format": query_output_format,
                "email_results": email_results
            }

            # Put query results in the results payload.
            results = rp.done(True, query_results)

            metrics = results.get("metrics")
            query_time_ms = metrics.get("execution_time_ms")
            # Write query results to an attachment or note as specified by the user in activity field.
            # Writing results to the data table takes place in the post processor script.
            self.write_results_to_note_or_attachment(
                email_address, mail_folders, sender, start_date, end_date,
                has_attachments, message_subject, message_body, query_results,
                query_time_ms)

            # Produce a FunctionResult with the results
            yield FunctionResult(results)

        except Exception as err:
            LOG.error(err)
            yield FunctionError(err)
Example #17
0
    def _exchange_online_delete_messages_from_query_results_function(
            self, event, *args, **kwargs):
        """Function: This Exchange Online function will delete a list of messages returned from the
        Query Message function.  The input to the function is a string containing the JSON results
        from the Query Messages function."""
        try:
            # Initialize the results payload
            rp = ResultPayload(CONFIG_DATA_SECTION, **kwargs)

            # Validate fields
            validate_fields(['exo_query_messages_results'], kwargs)

            # Get the function parameters

            query_results = kwargs.get('exo_query_messages_results')  # text

            LOG.info(u"exo_query_messages_results: %s", query_results)

            yield StatusMessage(u"Starting delete messages for query results")

            # Get the MS Graph helper class
            MS_graph_helper = MSGraphHelper(
                self.options.get("microsoft_graph_token_url"),
                self.options.get("microsoft_graph_url"),
                self.options.get("tenant_id"), self.options.get("client_id"),
                self.options.get("client_secret"),
                self.options.get("max_messages"),
                self.options.get("max_users"),
                self.options.get("max_retries_total", MAX_RETRIES_TOTAL),
                self.options.get("max_retries_backoff_factor",
                                 MAX_RETRIES_BACKOFF_FACTOR),
                self.options.get("max_batched_requests", MAX_BATCHED_REQUESTS),
                RequestsCommon(self.opts, self.options).get_proxies())

            # Convert string to JSON.
            try:
                query_results_json = json.loads(query_results)
                query_message_results = query_results_json.get('email_results')
                query_output_format = query_results_json.get(
                    'exo_query_output_format')
                incident_id = int(query_results_json.get('incident_id'))
            except ValueError as err:
                raise IntegrationError(
                    "Invalid JSON string in Delete Message from Query Results."
                )

            # Delete messages found in the query.
            delete_results = MS_graph_helper.delete_messages_from_query_results(
                query_message_results)

            delete_message_results = {
                "incident_id": incident_id,
                "exo_query_output_format": query_output_format,
                "delete_results": delete_results
            }

            results = rp.done(True, delete_message_results)

            metrics = results.get("metrics")
            execution_time_ms = metrics.get("execution_time_ms")

            # Write delete messages from query results to an attachment or note as specified by the user
            # in activity field.
            # Writing results to the data table takes place in the post processor script.
            self.write_results_to_note_or_attachment(delete_message_results,
                                                     execution_time_ms)

            yield StatusMessage(
                u"Returning Delete Messages From Query Results results.")

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception as err:
            LOG.error(err)
            yield FunctionError(err)
def selftest_function(opts):
    """
    Placeholder for selftest function. An example use would be to test package api connectivity.
    Suggested return values are be unimplemented, success, or failure.
    """
    # Get app.config parameters.
    options = opts.get(CONFIG_DATA_SECTION, {})

    validate_fields([
        'microsoft_graph_token_url', 'microsoft_graph_url', 'tenant_id',
        'client_id', 'client_secret', 'max_messages', 'max_users'
    ], options)

    # Read configuration settings:
    token_url = options.get('microsoft_graph_token_url')
    graph_url = options.get('microsoft_graph_url')
    tenant_id = options.get('tenant_id')
    client_id = options.get('client_id')
    client_secret = options.get('client_secret')
    max_messages = int(options.get('max_messages'))
    max_users = int(options.get('max_users'))
    max_retries_total = int(options.get('max_retries_total',
                                        MAX_RETRIES_TOTAL))
    max_retries_backoff_factor = int(
        options.get('max_retries_backoff_factor', MAX_RETRIES_BACKOFF_FACTOR))
    max_batched_requests = int(
        options.get("max_batched_requests", MAX_BATCHED_REQUESTS))
    try:
        log.info(u'Calling MS Graph API with: \n token_url: %s', token_url)
        log.info(u'MS Graph API url: %s', graph_url)
        log.info(u'tenant_id: %s', tenant_id)
        log.info(u'client_id: %s', client_id)
        log.info(u'max_messages: %s', str(max_messages))
        log.info(u'max_users: %s', str(max_users))
        log.info(u'max_retries_total: %s', str(max_retries_total))
        log.info(u'max_retries_backoff_factor: %s',
                 str(max_retries_backoff_factor))
        log.info(u'max_batched_requests: %s', str(max_batched_requests))

        state, reason = "", ""

        # Create MSGraphHelper class object
        ms_graph_helper = MSGraphHelper(
            token_url, graph_url, tenant_id, client_id, client_secret,
            max_messages, max_users, max_retries_total,
            max_retries_backoff_factor, max_batched_requests,
            RequestsCommon(opts, options).get_proxies())

        # Get a MS Graph session token
        session_token = ms_graph_helper.authenticate()

        if ms_graph_helper and session_token:
            state = "success"
        else:
            state = "failure"
            reason = "authenication failure"
    except IntegrationError as err:
        state = "failure"
        reason = err.value

    result = {"state": state, "reason": reason}

    log.info(result)
    return result
    def _exchange_online_write_message_as_attachment_function(
            self, event, *args, **kwargs):
        """Function: This function will get the mime content of an Exchange Online message and write it as an
           attachment."""
        try:
            # Initialize the results payload
            rp = ResultPayload(CONFIG_DATA_SECTION, **kwargs)

            # Validate fields
            validate_fields(
                ['incident_id', 'exo_email_address', 'exo_messages_id'],
                kwargs)

            # Get the function parameters:
            incident_id = kwargs.get("incident_id")  # number
            task_id = kwargs.get("task_id")  # number
            email_address = kwargs.get("exo_email_address")  # text
            message_id = kwargs.get("exo_messages_id")  # text
            attachment_name = kwargs.get("exo_attachment_name")  # text

            LOG.info(u"incident_id: %s", incident_id)
            LOG.info(u"task_id: %s", task_id)
            LOG.info(u"exo_email_address: %s", email_address)
            LOG.info(u"exo_messages_id: %s", message_id)
            LOG.info(u"exo_attachment_name: %s", attachment_name)

            yield StatusMessage(
                u"Starting to get message mime for email address: {}".format(
                    email_address))

            # Get the MS Graph helper class
            MS_graph_helper = MSGraphHelper(
                self.options.get("microsoft_graph_token_url"),
                self.options.get("microsoft_graph_url"),
                self.options.get("tenant_id"), self.options.get("client_id"),
                self.options.get("client_secret"),
                self.options.get("max_messages"),
                self.options.get("max_users"),
                RequestsCommon(self.opts, self.options).get_proxies())

            # Call MS Graph API to get the user profile
            response = MS_graph_helper.get_message_mime(
                email_address, message_id)

            datastream = BytesIO(response.content)

            if attachment_name is None:
                attachment_name = u"message-{}-{}.eml".format(
                    email_address, message_id)
                LOG.info(u"attachment_name: %s", attachment_name)

            # Get the rest client so we can add the attachment to the incident.
            rest_client = self.rest_client()

            # Write the file as attachement: failures will raise an exception
            write_file_attachment(rest_client, attachment_name, datastream,
                                  incident_id, task_id)

            results_data = {"attachment_name": attachment_name}
            results = rp.done(True, results_data)

            yield StatusMessage(
                u"Returning results for get message mime for email address: {0}\n attachment name: {1}"
                .format(email_address, attachment_name))

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception as err:
            LOG.error(err)
            yield FunctionError(err)
    def test_query_messages_all_users(self, authenticate_mock, mocked_get,
                                      mocked_post):
        """ Test Query Messages All Users"""
        print("Test Query Messages All Users\n")
        try:
            authenticate_mock.return_value = True
            MS_graph_helper = MSGraphHelper(
                MOCKED_OPTS.get("microsoft_graph_token_url"),
                MOCKED_OPTS.get("microsoft_graph_url"),
                MOCKED_OPTS.get("tenant_id"), MOCKED_OPTS.get("client_id"),
                MOCKED_OPTS.get("client_secret"),
                MOCKED_OPTS.get("max_messages"), MOCKED_OPTS.get("max_users"),
                MOCKED_OPTS.get("max_retries_total"),
                MOCKED_OPTS.get("max_retries_backoff_factor"),
                MOCKED_OPTS.get("max_batched_requests"), None)

            # Mock the users
            content1 = {
                'value': [{
                    'userPrincipalName': '*****@*****.**'
                }, {
                    'userPrincipalName': '*****@*****.**'
                }]
            }

            # Mock the responses from the POST to $batch endpoint.
            content2 = {
                'responses': [{
                    'id': '1',
                    'status': 200,
                    'body': {
                        'value': [{
                            'id': 'AAA'
                        }, {
                            'id': 'BBB'
                        }]
                    }
                }, {
                    'id': '2',
                    'status': 200,
                    'body': {
                        'value': [{
                            'id': 'CCC'
                        }]
                    }
                }]
            }

            mocked_get.side_effect = [generate_response(content1, 200)]
            mocked_post.side_effect = [generate_response(content2, 200)]

            email_list = MS_graph_helper.query_messages(
                "all", None, None, None, None, None, "lunch", None)
            assert len(email_list) == 2
            assert email_list[0]['email_address'] == '*****@*****.**'
            assert email_list[0]['status_code'] == 200
            assert email_list[0]['email_list'][0]['id'] == 'AAA'
            assert email_list[0]['email_list'][1]['id'] == 'BBB'
            assert email_list[1]['email_address'] == '*****@*****.**'
            assert email_list[1]['status_code'] == 200
            assert email_list[1]['email_list'][0]['id'] == 'CCC'
        except IntegrationError as err:
            assert True