diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 214895d..639f7b4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -51,6 +51,7 @@ repos: rev: v1.89.0 hooks: - id: semgrep + additional_dependencies: ["setuptools==81.0.0"] - repo: https://github.com/Yelp/detect-secrets rev: v1.5.0 hooks: diff --git a/LICENSE b/LICENSE index 01f84e5..86185fe 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright (c) 2017-2025 Splunk Inc. + Copyright (c) 2017-2026 Splunk Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/NOTICE b/NOTICE index 0176ec7..392f6d8 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Splunk SOAR App: MS Graph for Office 365 -Copyright (c) 2017-2025 Splunk Inc. +Copyright (c) 2017-2026 Splunk Inc. Third Party Software Attributions: @@@@============================================================================ diff --git a/README.md b/README.md index 352ea0e..53d1070 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # MS Graph for Office 365 Publisher: Splunk
-Connector Version: 4.1.0
+Connector Version: 4.2.0
Product Vendor: Microsoft
Product Name: Office 365 (MS Graph)
Minimum Product Version: 6.3.0 @@ -1604,7 +1604,7 @@ Search emails Type: **investigate**
Read only: **True** -If the query or internet_message_id parameters are included, the subject, sender, body, and range parameters will be ignored. The internet_message_id parameter will take precedence over the query parameter.

For details on formatting the query parameter, refer to Microsoft Graph Query Parameters. Query parameters can include OData system query options or other supported parameters.

If the limit parameter is not included, the action will default to limiting to ten emails that match the rest of the query. The get_folder_id parameter should be enabled only when you specified folder name/folder path in the folder parameter. If you provide folder ID in the folder parameter and set get_folder_id parameter to true, it will throw an error of folder ID not found for given folder name (because the action considers folder parameter value as folder name/folder path). The folder parameter must be either a (case sensitive) well-known name [list here; https://docs.microsoft.com/en-us/graph/api/resources/mailfolder?view=graph-rest-1.0] or the internal o365 folder ID. The action supports searching for a folder that is nested within another. To copy in such a folder, specify the complete folder path using the '/' (forward slash) as the separator.
e.g. to search in a folder named phishing which is nested within (is a child of) Inbox, set the value as Inbox/phishing. If a folder name has a literal forward slash('/') in the name escape it with a backslash('\\') to differentiate.
When the search_well_known_folders parameter is set to true, action will ignore values provided in the folder and get_folder_id parameters and the user will get details from all 17 well-known folders which are listed below:

If the limit parameter is provided, the user will get the number of messages provided in the limit from every folder if present. +If the query or internet_message_id parameters are included, the subject, sender, body, and range parameters will be ignored. The internet_message_id parameter will take precedence over the query parameter.

For details on formatting the query parameter, refer to Microsoft Graph Query Parameters. Query parameters can include OData system query options or other supported parameters.

If the limit parameter is not included, the action will default to limiting to ten emails that match the rest of the query. The get_folder_id parameter should be enabled only when you specified folder name/folder path in the folder parameter. If you provide folder ID in the folder parameter and set get_folder_id parameter to true, it will throw an error of folder ID not found for given folder name (because the action considers folder parameter value as folder name/folder path). The folder parameter must be either a (case sensitive) well-known name [list here; https://docs.microsoft.com/en-us/graph/api/resources/mailfolder?view=graph-rest-1.0] or the internal o365 folder ID. The action supports searching for a folder that is nested within another. To copy in such a folder, specify the complete folder path using the '/' (forward slash) as the separator.
e.g. to search in a folder named phishing which is nested within (is a child of) Inbox, set the value as Inbox/phishing. If a folder name has a literal forward slash('/') in the name escape it with a backslash('\\') to differentiate.
When the search_well_known_folders parameter is set to true, action will ignore values provided in the folder and get_folder_id parameters and the user will get details from all 17 well-known folders which are listed below:

When the search_recoverable_items_folders parameter is set to true, the action will add the following 9 subfolders from the Recoverable Items folder to the search scope:

If the limit parameter is provided, the user will get the number of messages provided in the limit from every folder if present. #### Action Parameters @@ -1612,6 +1612,7 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS --------- | -------- | ----------- | ---- | -------- **email_address** | required | User's email (mailbox to search in) | string | `email` | **folder** | optional | Destination folder; this must be either a (case-sensitive) well-known name or the internal o365 folder ID | string | `msgoffice365 mail folder` `msgoffice365 mail folder path` `msgoffice365 folder id` | +**search_recoverable_items_folders** | optional | Adds the subfolders within the Recoverable Items folder to the message search scope | boolean | | **search_well_known_folders** | optional | Checks all well known folders for messages, ignores folder name provided in parameter | boolean | | **get_folder_id** | optional | Assume the folder parameter contains a folder name/folder path, separated by '/'(forward slash) ; i.e. Inbox/dir1/dir2/dir3. If this parameter is enabled, it retrieves the folder ID for the provided folder name/folder path automatically and replaces the parameter value | boolean | | **subject** | optional | Substring to search in subject | string | `msgoffice365 subject` | @@ -1704,6 +1705,7 @@ action_result.summary.emails_matched | numeric | | 1 | action_result.message | string | | Emails matched: 1 | summary.total_objects | numeric | | 1 | summary.total_objects_successful | numeric | | 1 | +action_result.parameter.search_recoverable_items_folders | boolean | | | ## action: 'create folder' @@ -2216,7 +2218,7 @@ ______________________________________________________________________ Auto-generated Splunk SOAR Connector documentation. -Copyright 2025 Splunk Inc. +Copyright 2026 Splunk Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/__init__.py b/__init__.py index c8a2c5b..c6ac30e 100644 --- a/__init__.py +++ b/__init__.py @@ -1,6 +1,6 @@ # File: __init__.py # -# Copyright (c) 2017-2025 Splunk Inc. +# Copyright (c) 2017-2026 Splunk Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/office365.json b/office365.json index 2b1aa54..33c7f08 100644 --- a/office365.json +++ b/office365.json @@ -30,10 +30,13 @@ }, { "name": "Anton Neledov" + }, + { + "name": "Andrei Irimia" } ], - "license": "Copyright (c) 2017-2025 Splunk Inc.", - "app_version": "4.1.0", + "license": "Copyright (c) 2017-2026 Splunk Inc.", + "app_version": "4.2.0", "utctime_updated": "2026-01-09T05:33:39.032641Z", "package_name": "phantom_msgraphoffice365", "main_module": "office365_connector.py", @@ -5657,7 +5660,7 @@ "action": "run query", "identifier": "run_query", "description": "Search emails", - "verbose": "If the query or internet_message_id parameters are included, the subject, sender, body, and range parameters will be ignored. The internet_message_id parameter will take precedence over the query parameter.

For details on formatting the query parameter, refer to Microsoft Graph Query Parameters. Query parameters can include OData system query options or other supported parameters.

If the limit parameter is not included, the action will default to limiting to ten emails that match the rest of the query. The get_folder_id parameter should be enabled only when you specified folder name/folder path in the folder parameter. If you provide folder ID in the folder parameter and set get_folder_id parameter to true, it will throw an error of folder ID not found for given folder name (because the action considers folder parameter value as folder name/folder path). The folder parameter must be either a (case sensitive) well-known name [list here; https://docs.microsoft.com/en-us/graph/api/resources/mailfolder?view=graph-rest-1.0] or the internal o365 folder ID. The action supports searching for a folder that is nested within another. To copy in such a folder, specify the complete folder path using the '/' (forward slash) as the separator.
e.g. to search in a folder named phishing which is nested within (is a child of) Inbox, set the value as Inbox/phishing. If a folder name has a literal forward slash('/') in the name escape it with a backslash('\\') to differentiate.
When the search_well_known_folders parameter is set to true, action will ignore values provided in the folder and get_folder_id parameters and the user will get details from all 17 well-known folders which are listed below:

If the limit parameter is provided, the user will get the number of messages provided in the limit from every folder if present.", + "verbose": "If the query or internet_message_id parameters are included, the subject, sender, body, and range parameters will be ignored. The internet_message_id parameter will take precedence over the query parameter.

For details on formatting the query parameter, refer to Microsoft Graph Query Parameters. Query parameters can include OData system query options or other supported parameters.

If the limit parameter is not included, the action will default to limiting to ten emails that match the rest of the query. The get_folder_id parameter should be enabled only when you specified folder name/folder path in the folder parameter. If you provide folder ID in the folder parameter and set get_folder_id parameter to true, it will throw an error of folder ID not found for given folder name (because the action considers folder parameter value as folder name/folder path). The folder parameter must be either a (case sensitive) well-known name [list here; https://docs.microsoft.com/en-us/graph/api/resources/mailfolder?view=graph-rest-1.0] or the internal o365 folder ID. The action supports searching for a folder that is nested within another. To copy in such a folder, specify the complete folder path using the '/' (forward slash) as the separator.
e.g. to search in a folder named phishing which is nested within (is a child of) Inbox, set the value as Inbox/phishing. If a folder name has a literal forward slash('/') in the name escape it with a backslash('\\') to differentiate.
When the search_well_known_folders parameter is set to true, action will ignore values provided in the folder and get_folder_id parameters and the user will get details from all 17 well-known folders which are listed below:

When the search_recoverable_items_folders parameter is set to true, the action will add the following 9 subfolders from the Recoverable Items folder to the search scope:

If the limit parameter is provided, the user will get the number of messages provided in the limit from every folder if present.", "type": "investigate", "read_only": true, "parameters": { @@ -5683,16 +5686,21 @@ "default": "Inbox", "order": 1 }, + "search_recoverable_items_folders": { + "description": "Adds the subfolders within the Recoverable Items folder to the message search scope", + "data_type": "boolean", + "order": 2 + }, "search_well_known_folders": { "description": "Checks all well known folders for messages, ignores folder name provided in parameter", "data_type": "boolean", - "order": 2 + "order": 3 }, "get_folder_id": { "description": "Assume the folder parameter contains a folder name/folder path, separated by '/'(forward slash) ; i.e. Inbox/dir1/dir2/dir3. If this parameter is enabled, it retrieves the folder ID for the provided folder name/folder path automatically and replaces the parameter value", "data_type": "boolean", "default": true, - "order": 3 + "order": 4 }, "subject": { "description": "Substring to search in subject", @@ -5701,12 +5709,12 @@ "contains": [ "msgoffice365 subject" ], - "order": 4 + "order": 5 }, "body": { "description": "Substring to search in body", "data_type": "string", - "order": 5 + "order": 6 }, "sender": { "description": "Sender email address to match", @@ -5715,17 +5723,17 @@ "contains": [ "email" ], - "order": 6 + "order": 7 }, "limit": { "description": "Maximum emails to return", "data_type": "numeric", - "order": 7 + "order": 8 }, "query": { "description": "MS Graph query string", "data_type": "string", - "order": 8 + "order": 9 }, "internet_message_id": { "description": "Internet message ID", @@ -5734,7 +5742,7 @@ "contains": [ "msgoffice365 internet message id" ], - "order": 9 + "order": 10 } }, "output": [ @@ -6332,6 +6340,10 @@ "example_values": [ 1 ] + }, + { + "data_path": "action_result.parameter.search_recoverable_items_folders", + "data_type": "boolean" } ], "render": { @@ -8752,17 +8764,13 @@ ], "pip39_dependencies": { "wheel": [ - { - "module": "PyJWT", - "input_file": "wheels/py3/PyJWT-2.10.1-py3-none-any.whl" - }, { "module": "cffi", "input_file": "wheels/py39/cffi-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl" }, { "module": "cryptography", - "input_file": "wheels/py3/cryptography-46.0.3-cp38-abi3-manylinux_2_28_x86_64.whl" + "input_file": "wheels/py3/cryptography-46.0.5-cp38-abi3-manylinux_2_28_x86_64.whl" }, { "module": "msal", @@ -8772,6 +8780,10 @@ "module": "pycparser", "input_file": "wheels/py3/pycparser-2.23-py3-none-any.whl" }, + { + "module": "pyjwt", + "input_file": "wheels/py3/pyjwt-2.12.1-py3-none-any.whl" + }, { "module": "typing_extensions", "input_file": "wheels/py3/typing_extensions-4.15.0-py3-none-any.whl" @@ -8780,17 +8792,13 @@ }, "pip313_dependencies": { "wheel": [ - { - "module": "PyJWT", - "input_file": "wheels/py3/PyJWT-2.10.1-py3-none-any.whl" - }, { "module": "cffi", "input_file": "wheels/py313/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl" }, { "module": "cryptography", - "input_file": "wheels/py3/cryptography-46.0.3-cp311-abi3-manylinux_2_28_x86_64.whl" + "input_file": "wheels/py3/cryptography-46.0.5-cp311-abi3-manylinux_2_28_x86_64.whl" }, { "module": "msal", @@ -8798,7 +8806,11 @@ }, { "module": "pycparser", - "input_file": "wheels/py3/pycparser-2.23-py3-none-any.whl" + "input_file": "wheels/py3/pycparser-3.0-py3-none-any.whl" + }, + { + "module": "pyjwt", + "input_file": "wheels/py3/pyjwt-2.12.1-py3-none-any.whl" } ] } diff --git a/office365_connector.py b/office365_connector.py index 3db9d56..cce5723 100644 --- a/office365_connector.py +++ b/office365_connector.py @@ -1,6 +1,6 @@ # File: office365_connector.py # -# Copyright (c) 2017-2025 Splunk Inc. +# Copyright (c) 2017-2026 Splunk Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -2283,6 +2283,15 @@ def _handle_run_query(self, param): folder_ids.append(folder) endpoint += "/mailFolders/{folder_id}" + # Add the Recoverable Items folders to search scope + if param.get("search_recoverable_items_folders", False): + for folder in MSGOFFICE365_RECOVERABLE_ITEMS_FOLDERS_FILTER: + folder_ids.append(folder) + + # Modify endpoint if not already modified by well known folders or folder search scope + if "{folder_id}" not in endpoint: + endpoint += "/{folder_id}" if "/mailFolders" in endpoint else "/mailFolders/{folder_id}" + # that should be enough to create the endpoint endpoint += "/messages" diff --git a/office365_consts.py b/office365_consts.py index 45d4779..7cca2d9 100644 --- a/office365_consts.py +++ b/office365_consts.py @@ -1,6 +1,6 @@ # File: office365_consts.py # -# Copyright (c) 2017-2025 Splunk Inc. +# Copyright (c) 2017-2026 Splunk Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -42,6 +42,19 @@ "serverfailures", "syncissues", ] + +MSGOFFICE365_RECOVERABLE_ITEMS_FOLDERS_FILTER = [ + "recoverableitemsdeletions", + "recoverableitemspurges", + "recoverableitemsversions", + "recoverableitemsaudits", + "recoverableitemsdiscoveryholds", + "recoverableitemssubstrateholds", + "recoverableitemsversions", + "recoverableitemsroot", + "recoverableitemscalendarlogging", +] + MSGOFFICE365_STATE_FILE_CORRUPT_ERROR = ( "Error occurred while loading the state file. Resetting the state file with the default format. Please test the connectivity." ) diff --git a/office365_get_email.html b/office365_get_email.html index ba9f3ba..5149595 100644 --- a/office365_get_email.html +++ b/office365_get_email.html @@ -11,7 +11,7 @@ {% block widget_content %}