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
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
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
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)
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)
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