diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 353ad10..0c2c1f1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,11 +1,11 @@ repos: - repo: https://github.com/phantomcyber/dev-cicd-tools - rev: v1.11 + rev: v1.12 hooks: - id: org-hook - id: package-app-dependencies - repo: https://github.com/Yelp/detect-secrets - rev: v1.1.0 + rev: v1.2.0 hooks: - id: detect-secrets args: ['--no-verify', '--exclude-files', '^office365.json$'] diff --git a/NOTICE b/NOTICE index ed91f00..52bcf7f 100644 --- a/NOTICE +++ b/NOTICE @@ -4,7 +4,7 @@ Copyright (c) 2017-2022 Splunk Inc. Third-party Software Attributions: Library: Django -Version: 3.2.12 +Version: 3.2.13 License: BSD 3 0.9.0 thru 1.2 1991-1995 CWI yes 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes diff --git a/README.md b/README.md index b6c652e..3f4f7d3 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,11 @@ # MS Graph for Office 365 Publisher: Splunk -Connector Version: 2\.4\.14 +Connector Version: 2\.5\.0 Product Vendor: Microsoft Product Name: Office 365 \(MS Graph\) Product Version Supported (regex): "\.\*" -Minimum Product Version: 5\.1\.0 +Minimum Product Version: 5\.2\.0 This app connects to Office 365 using the MS Graph API to support investigate and generic actions related to the email messages and calendar events @@ -24,6 +24,13 @@ This app connects to Office 365 using the MS Graph API to support investigate an [comment]: # "either express or implied. See the License for the specific language governing permissions" [comment]: # "and limitations under the License." [comment]: # "" +## Playbook Backward Compatibility + +- The 'id' field of email artifact has been renamed to 'messageId'. Hence, it is requested to the + end-user to please update their existing playbooks by re-inserting \| modifying \| deleting the + corresponding action blocks to ensure the correct functioning of the playbooks created on the + earlier versions of the app. + ## Authentication This app requires registration of a Microsoft Graph Application. To do so, navigate to the URL @@ -32,13 +39,23 @@ registrations** . On the next page, select **New registration** and give your app a name. -Once the app is created, follow the below three steps: +Once the app is created, follow the below-mentioned steps: - Under **Certificates & secrets** select **New client secret** . Note down this key somewhere secure, as it cannot be retrieved after closing the window. -- Under **Overview** select **Add a redirect URI** . In the **Add Platform** window, select - **Web** . The **Redirect URLs** field will be filled in the later steps. -- Under **API Permissions** the following **Application Permissions** need to be added: + +- Under **Authentication** , select **Add a platform** . In the **Add a platform** window, select + **Web** . The **Redirect URLs** should be filled right here. We will get **Redirect URLs** from + the Phantom asset we create below in the section titled **Phantom Graph Asset** . + +- Under **API Permissions** Click on **Add a permission** . + +- Under the **Microsoft API** section, select **Microsoft Graph** . + +- Provide the following Application permissions to the app: + + + - Mail.Read (https://graph.microsoft.com/Mail.Read) - Mail.ReadWrite (https://graph.microsoft.com/Mail.ReadWrite) @@ -50,15 +67,15 @@ Once the app is created, follow the below three steps: - For non-admin access, use User.Read (Delegated permission) instead (https://graph.microsoft.com/User.Read) - - Group.Read.All (https://graph.microsoft.com/Group.Read.All)- It is required only if you want - to run the **list events** action for the group's calendar and for the **list groups** - action + - Group.Read.All (https://graph.microsoft.com/Group.Read.All) - It is required only if you + want to run the **list events** action for the group's calendar and for the **list groups** + action. - - Calendar.Read (https://graph.microsoft.com/Calendars.Read)- It is required only if you want - to run the **list events** action for the user's calendar + - Calendar.Read (https://graph.microsoft.com/Calendars.Read) - It is required only if you want + to run the **list events** action for the user's calendar. - - MailboxSettings.Read (https://graph.microsoft.com/MailboxSettings.Read)- It is required only - if you want to run the **oof status** action + - MailboxSettings.Read (https://graph.microsoft.com/MailboxSettings.Read) - It is required + only if you want to run the **oof status** action. After making these changes, click **Add permissions** , then select **Grant admin consent for Test Phantom** at the bottom of the screen. @@ -67,44 +84,89 @@ Phantom** at the bottom of the screen. When creating an asset for the **MS Graph for Office 365** app, place **Application ID** of the app created during the app registration on the Azure Portal in the **Application ID** field and place -the client secret generated during the app registration process in the **Client Secret** field. +the client secret generated during the app registration process in the **Application Secret** field. Then, after filling out the **Tenant** field, click **SAVE** . Both the Application/Client ID and the Tenant ID can be found in the **Overview** tab on your app's Azure page. After saving, a new field will appear in the **Asset Settings** tab. Take the URL found in the **POST incoming for MS Graph for Office 365 to this location** field and place it in the **Redirect -URLs** field mentioned in a previous step. To this URL, add **/result** . After doing so the URL +URLs** field mentioned in the previous step. To this URL, add **/result** . After doing so the URL should look something like: - https:///rest/handler/msgraphforoffice365_0a0a4087-10e8-4c96-9872-b740ff26d8bb//result +https://\/rest/handler/msgraphforoffice365_0a0a4087-10e8-4c96-9872-b740ff26d8bb/\/result -Once again, click save at the bottom of the screen. +Once again, click SAVE at the bottom of the screen. + +Additionally, updating the Base URL in the Company Settings is also required. Navigate to +**Administration \> Company Settings \> Info** to configure the **Base URL For Splunk SOAR** . Then, +select **Save Changes** . + ## User Permissions To complete the authorization process, this app needs permission to view assets, which is not -granted by default. First, under **asset settings** , check which user has listed under **Select a -user on behalf of which automated actions can be executed** . By default, the user will be -**automation** , but this user can be changed by clicking **EDIT** at the bottom of the window. To -give this user permission to view assets, follow these steps: +granted by default. First, navigate to **Asset Settings \> Advanced** , to check which user is +listed under **Select a user on behalf of which automated actions can be executed** . By default, +the user will be **automation** , but this user can be changed by clicking **EDIT** at the bottom of +the window. To give this user permission to view assets, follow these steps: - In the main drop-down menu, select **Administration** , then select the **User Management** , - and under that tab, select **Roles** . Finally, click **+ ROLE** . + and under that tab, select **Roles & Permissions** . Finally, click **+ ROLE** . - In the **Add Role** wizard, give the role a name (e.g **Asset Viewer** ), and provide a - description. Subsequently, under **Available Users** , add the user assigned to the asset viewed - earlier. Then click the **Permissions** tab. -- On the permission tab, under **Available Privileges** , give the role the **View Assets** + description. Subsequently, under the **Users tab** , click **ADD USERS** to add the user + assigned to the asset viewed earlier. Then click the **Permissions** tab. +- In the permission tab, under **Basic Permissions** , give the role the **View Assets** privilege. Then click **SAVE** . ### Test connectivity -After setting up the asset and user, click the **TEST CONNECTIVITY** button. A window should pop up -and display a URL. Navigate to this URL in a separate browser tab. This new tab will redirect to a -Microsoft login page. Log in to a Microsoft account with administrator privileges to the desired -mailboxes. After logging in, review the requested permissions listed, then click **Accept** . -Finally, close that tab. The test connectivity window should show success. +#### Admin User Workflow + +- Configure the asset with required details while keeping the **Admin Access Required** as + checked. +- While configuring the asset for the first time, keep **Admin Consent Already Provided** as + unchecked. +- The **Redirect URLs** must be configured before executing test connectivity. To configure + **Redirect URLs** , checkout the section titled **Phantom Graph Asset** above. +- After setting up the asset and user, click the **TEST CONNECTIVITY** button. +- A window should pop up and display a URL. You will be asked to open the link in a new tab. Open + the link in the same browser so that you are logged into Splunk Phantom for the redirect. If you + wish to use a different browser, log in to the Splunk Phantom first, and then open the provided + link. This new tab will redirect to the Microsoft login page. +- Log in to the Microsoft account with the admin user. +- You will be prompted to agree to the permissions requested by the App. +- Review the requested permissions listed, then click **Accept** . +- If all goes well the browser should instruct you to close the tab. +- Now go back and check the message on the Test Connectivity dialog box, it should say **Test + Connectivity Passed** . +- For subsequent test connectivity or action runs, you can keep **Admin Consent Already Provided** + config parameter as checked. This will skip the interactive flow and use the client credentials + for generating tokens. + +#### Non-Admin User Workflow + +- Configure the asset with required details while keeping the **Admin Access Required** as + unchecked. **Admin Consent Already Provided** config parameter will be ignored in the non-admin + workflow. +- Provide **Access Scope** parameter in the asset configuration. All the actions will get executed + according to the scopes provided in the **Access Scope** config parameter. +- The **Redirect URLs** must be configured before executing test connectivity. To configure + **Redirect URLs** , checkout the section titled **Phantom Graph Asset** above. +- After setting up the asset and user, click the **TEST CONNECTIVITY** button. +- A window should pop up and display a URL. You will be asked to open the link in a new tab. Open + the link in the same browser so that you are logged into Splunk Phantom for the redirect. If you + wish to use a different browser, log in to the Splunk Phantom first, and then open the provided + link. This new tab will redirect to the Microsoft login page. +- Log in to the Microsoft account. +- You will be prompted to agree to the permissions requested by the App. +- Review the requested permissions listed, then click **Accept** . +- If all goes well the browser should instruct you to close the tab. +- Now go back and check the message on the Test Connectivity dialog box, it should say **Test + Connectivity Passed** . + + The app should now be ready to be used. @@ -114,6 +176,8 @@ The app should now be ready to be used. - email_address - Ingest from the provided email address. - folder - To fetch the emails from the given folder name (must be provided if running ingestion) +- get_folder_id - Retrieve the folder ID for the provided folder name/folder path automatically + and replace the folder parameter value. - first_run_max_emails - Maximum containers to poll for the first scheduled polling (default - 1000). - max_containers - Maximum containers to poll after the first scheduled poll completes (default - @@ -124,6 +188,24 @@ The app should now be ready to be used. - extract_domains - Extract the domain names present in the emails. - extract_hashes - Extract the hashes present in the emails (MD5). +## Guidelines to provide folder parameter value + +This is applicable to 'on poll', 'copy email', 'move email', and 'run query' actions. + +- The **get_folder_id** parameter should be enabled only when you have 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 ( + ) or the + internal o365 folder ID. +- The folder parameter supports nested folder paths. To specify the complete folder path using the + **'/'** (forward slash) as the separator. + e.g. to specify 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. + ## State file permissions Please check the permissions for the state file as mentioned below. @@ -179,6 +261,16 @@ Please check the permissions for the state file as mentioned below. +## Port Details + +The app uses HTTP/ HTTPS protocol for communicating with the Office365 server. Below are the default +ports used by the Splunk SOAR Connector. + +| Service Name | Transport Protocol | Port | +|--------------|--------------------|------| +| http | tcp | 80 | +| https | tcp | 443 | + ### Configuration Variables The below configuration variables are required for this Connector to operate. These variables are specified when configuring a Office 365 \(MS Graph\) asset in SOAR. @@ -193,7 +285,9 @@ VARIABLE | REQUIRED | TYPE | DESCRIPTION **scope** | optional | string | Access Scope \(for use with non\-admin access; space\-separated\) **ph\_2** | optional | ph | **email\_address** | optional | string | User Email Mailbox \(On Poll\) -**folder** | optional | string | Mailbox folder to ingest \(On Poll\) +**folder** | optional | string | Mailbox folder name/folder path or the internal o365 folder ID to ingest \(On Poll\) +**get\_folder\_id** | optional | boolean | Retrieve the folder ID for the provided folder name/folder path automatically and replace the folder parameter value \(On Poll\) +**ph\_3** | optional | ph | **first\_run\_max\_emails** | optional | numeric | Maximum Containers for scheduled polling first time **max\_containers** | optional | numeric | Maximum Containers for scheduled polling **extract\_attachments** | optional | boolean | Extract Attachments @@ -201,6 +295,8 @@ VARIABLE | REQUIRED | TYPE | DESCRIPTION **extract\_ips** | optional | boolean | Extract IPs **extract\_domains** | optional | boolean | Extract Domain Names **extract\_hashes** | optional | boolean | Extract Hashes +**ph\_4** | optional | ph | +**ingest\_manner** | required | string | How to Ingest \(during ingestion, should the app get the latest emails or the oldest\) ### Supported Actions [test connectivity](#action-test-connectivity) - Use supplied credentials to generate a token with MS Graph @@ -244,10 +340,10 @@ No parameters are required for this action #### Action Output DATA PATH | TYPE | CONTAINS --------- | ---- | -------- -action\_result\.status | string | action\_result\.data | string | -action\_result\.summary | string | +action\_result\.status | string | action\_result\.message | string | +action\_result\.summary | string | summary\.total\_objects | numeric | summary\.total\_objects\_successful | numeric | @@ -265,12 +361,20 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS #### Action Output DATA PATH | TYPE | CONTAINS --------- | ---- | -------- -action\_result\.status | string | action\_result\.parameter\.user\_id | string | `msgoffice365 user id` `msgoffice365 user principle name` `email` +action\_result\.data\.\*\.\@odata\.context | string | `url` action\_result\.data\.\*\.\@odata\.etag | string | +action\_result\.data\.\*\.externalAudience | string | +action\_result\.data\.\*\.externalReplyMessage | string | +action\_result\.data\.\*\.internalReplyMessage | string | +action\_result\.data\.\*\.scheduledEndDateTime\.dateTime | string | +action\_result\.data\.\*\.scheduledEndDateTime\.timeZone | string | +action\_result\.data\.\*\.scheduledStartDateTime\.dateTime | string | +action\_result\.data\.\*\.scheduledStartDateTime\.timeZone | string | action\_result\.data\.\*\.status | string | -action\_result\.summary\.events\_matched | numeric | +action\_result\.status | string | action\_result\.message | string | +action\_result\.summary\.events\_matched | numeric | summary\.total\_objects | numeric | summary\.total\_objects\_successful | numeric | @@ -291,12 +395,12 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS #### Action Output DATA PATH | TYPE | CONTAINS --------- | ---- | -------- -action\_result\.status | string | action\_result\.parameter\.filter | string | action\_result\.parameter\.group\_id | string | `msgoffice365 group id` action\_result\.parameter\.limit | numeric | action\_result\.parameter\.user\_id | string | `msgoffice365 user id` `msgoffice365 user principle name` `email` action\_result\.data\.\*\.\@odata\.etag | string | +action\_result\.data\.\*\.allowNewTimeProposals | boolean | action\_result\.data\.\*\.attendee\_list | string | action\_result\.data\.\*\.attendees\.\*\.emailAddress\.address | string | `email` action\_result\.data\.\*\.attendees\.\*\.emailAddress\.name | string | @@ -306,17 +410,22 @@ action\_result\.data\.\*\.attendees\.\*\.type | string | action\_result\.data\.\*\.body\.content | string | action\_result\.data\.\*\.body\.contentType | string | action\_result\.data\.\*\.bodyPreview | string | +action\_result\.data\.\*\.calendar\@odata\.associationLink | string | `url` +action\_result\.data\.\*\.calendar\@odata\.navigationLink | string | `url` action\_result\.data\.\*\.categories\.\*\.name | string | action\_result\.data\.\*\.changeKey | string | action\_result\.data\.\*\.createdDateTime | string | action\_result\.data\.\*\.end\.dateTime | string | action\_result\.data\.\*\.end\.timeZone | string | action\_result\.data\.\*\.hasAttachments | boolean | +action\_result\.data\.\*\.hideAttendees | boolean | action\_result\.data\.\*\.iCalUId | string | action\_result\.data\.\*\.id | string | action\_result\.data\.\*\.importance | string | action\_result\.data\.\*\.isAllDay | boolean | action\_result\.data\.\*\.isCancelled | boolean | +action\_result\.data\.\*\.isDraft | boolean | +action\_result\.data\.\*\.isOnlineMeeting | boolean | action\_result\.data\.\*\.isOrganizer | boolean | action\_result\.data\.\*\.isReminderOn | boolean | action\_result\.data\.\*\.lastModifiedDateTime | string | @@ -344,6 +453,9 @@ action\_result\.data\.\*\.locations\.\*\.locationType | string | action\_result\.data\.\*\.locations\.\*\.locationUri | string | `url` action\_result\.data\.\*\.locations\.\*\.uniqueId | string | action\_result\.data\.\*\.locations\.\*\.uniqueIdType | string | +action\_result\.data\.\*\.occurrenceId | string | +action\_result\.data\.\*\.onlineMeeting | string | +action\_result\.data\.\*\.onlineMeetingProvider | string | action\_result\.data\.\*\.onlineMeetingUrl | string | `url` action\_result\.data\.\*\.organizer\.emailAddress\.address | string | `email` action\_result\.data\.\*\.organizer\.emailAddress\.name | string | @@ -360,11 +472,13 @@ action\_result\.data\.\*\.showAs | string | action\_result\.data\.\*\.start\.dateTime | string | action\_result\.data\.\*\.start\.timeZone | string | action\_result\.data\.\*\.subject | string | +action\_result\.data\.\*\.transactionId | string | action\_result\.data\.\*\.type | string | action\_result\.data\.\*\.webLink | string | `url` action\_result\.data\.locations\.\*\.displayName | string | -action\_result\.summary\.events\_matched | numeric | +action\_result\.status | string | action\_result\.message | string | +action\_result\.summary\.events\_matched | numeric | summary\.total\_objects | numeric | summary\.total\_objects\_successful | numeric | @@ -383,7 +497,6 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS #### Action Output DATA PATH | TYPE | CONTAINS --------- | ---- | -------- -action\_result\.status | string | action\_result\.parameter\.filter | string | action\_result\.parameter\.limit | numeric | action\_result\.data\.\*\.businessPhones | string | @@ -397,8 +510,9 @@ action\_result\.data\.\*\.officeLocation | string | action\_result\.data\.\*\.preferredLanguage | string | action\_result\.data\.\*\.surname | string | action\_result\.data\.\*\.userPrincipalName | string | `msgoffice365 user principle name` `email` -action\_result\.summary\.total\_users\_returned | numeric | +action\_result\.status | string | action\_result\.message | string | +action\_result\.summary\.total\_users\_returned | numeric | summary\.total\_objects | numeric | summary\.total\_objects\_successful | numeric | @@ -417,7 +531,6 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS #### Action Output DATA PATH | TYPE | CONTAINS --------- | ---- | -------- -action\_result\.status | string | action\_result\.parameter\.filter | string | action\_result\.parameter\.limit | numeric | action\_result\.data\.\*\.classification | string | @@ -426,24 +539,34 @@ action\_result\.data\.\*\.creationOptions | string | action\_result\.data\.\*\.deletedDateTime | string | action\_result\.data\.\*\.description | string | action\_result\.data\.\*\.displayName | string | +action\_result\.data\.\*\.expirationDateTime | string | action\_result\.data\.\*\.groupTypes | string | action\_result\.data\.\*\.id | string | `msgoffice365 group id` action\_result\.data\.\*\.isAssignableToRole | string | action\_result\.data\.\*\.mail | string | `email` action\_result\.data\.\*\.mailEnabled | boolean | action\_result\.data\.\*\.mailNickname | string | +action\_result\.data\.\*\.membershipRule | string | +action\_result\.data\.\*\.membershipRuleProcessingState | string | +action\_result\.data\.\*\.onPremisesDomainName | string | action\_result\.data\.\*\.onPremisesLastSyncDateTime | string | +action\_result\.data\.\*\.onPremisesNetBiosName | string | +action\_result\.data\.\*\.onPremisesSamAccountName | string | action\_result\.data\.\*\.onPremisesSecurityIdentifier | string | action\_result\.data\.\*\.onPremisesSyncEnabled | string | action\_result\.data\.\*\.preferredDataLocation | string | +action\_result\.data\.\*\.preferredLanguage | string | action\_result\.data\.\*\.proxyAddresses | string | action\_result\.data\.\*\.renewedDateTime | string | action\_result\.data\.\*\.resourceBehaviorOptions | string | action\_result\.data\.\*\.resourceProvisioningOptions | string | action\_result\.data\.\*\.securityEnabled | boolean | +action\_result\.data\.\*\.securityIdentifier | string | +action\_result\.data\.\*\.theme | string | action\_result\.data\.\*\.visibility | string | -action\_result\.summary\.total\_groups\_returned | numeric | +action\_result\.status | string | action\_result\.message | string | +action\_result\.summary\.total\_groups\_returned | numeric | summary\.total\_objects | numeric | summary\.total\_objects\_successful | numeric | @@ -464,17 +587,19 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS #### Action Output DATA PATH | TYPE | CONTAINS --------- | ---- | -------- -action\_result\.status | string | action\_result\.parameter\.folder\_id | string | `msgoffice365 folder id` action\_result\.parameter\.user\_id | string | `msgoffice365 user id` `msgoffice365 user principle name` `email` action\_result\.data\.\*\.childFolderCount | numeric | action\_result\.data\.\*\.displayName | string | action\_result\.data\.\*\.id | string | `msgoffice365 folder id` +action\_result\.data\.\*\.isHidden | boolean | action\_result\.data\.\*\.parentFolderId | string | `msgoffice365 folder id` +action\_result\.data\.\*\.sizeInBytes | numeric | action\_result\.data\.\*\.totalItemCount | numeric | action\_result\.data\.\*\.unreadItemCount | numeric | -action\_result\.summary\.total\_folders\_returned | numeric | +action\_result\.status | string | action\_result\.message | string | +action\_result\.summary\.total\_folders\_returned | numeric | summary\.total\_objects | numeric | summary\.total\_objects\_successful | numeric | @@ -497,7 +622,6 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS #### Action Output DATA PATH | TYPE | CONTAINS --------- | ---- | -------- -action\_result\.status | string | action\_result\.parameter\.email\_address | string | `email` action\_result\.parameter\.folder | string | `msgoffice365 mail folder` `msgoffice365 mail folder path` `msgoffice365 folder id` action\_result\.parameter\.get\_folder\_id | boolean | @@ -515,7 +639,9 @@ action\_result\.data\.\*\.ccRecipients\.email | string | `email` action\_result\.data\.\*\.ccRecipients\.name | string | action\_result\.data\.\*\.changeKey | string | action\_result\.data\.\*\.conversationId | string | +action\_result\.data\.\*\.conversationIndex | string | action\_result\.data\.\*\.createdDateTime | string | +action\_result\.data\.\*\.flag\.flagStatus | string | action\_result\.data\.\*\.from\.emailAddress\.address | string | `email` action\_result\.data\.\*\.from\.emailAddress\.name | string | action\_result\.data\.\*\.hasAttachments | boolean | @@ -523,7 +649,7 @@ action\_result\.data\.\*\.id | string | `msgoffice365 message id` action\_result\.data\.\*\.importance | string | action\_result\.data\.\*\.inferenceClassification | string | action\_result\.data\.\*\.internetMessageId | string | `msgoffice365 internet message id` -action\_result\.data\.\*\.isDeliveryReceiptRequested | string | +action\_result\.data\.\*\.isDeliveryReceiptRequested | boolean | action\_result\.data\.\*\.isDraft | boolean | action\_result\.data\.\*\.isRead | boolean | action\_result\.data\.\*\.isReadReceiptRequested | boolean | @@ -538,8 +664,9 @@ action\_result\.data\.\*\.subject | string | `msgoffice365 subject` action\_result\.data\.\*\.toRecipients\.\*\.emailAddress\.address | string | `email` action\_result\.data\.\*\.toRecipients\.\*\.emailAddress\.name | string | action\_result\.data\.\*\.webLink | string | `url` -action\_result\.summary | string | +action\_result\.status | string | action\_result\.message | string | +action\_result\.summary | string | summary\.total\_objects | numeric | summary\.total\_objects\_successful | numeric | @@ -562,7 +689,6 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS #### Action Output DATA PATH | TYPE | CONTAINS --------- | ---- | -------- -action\_result\.status | string | action\_result\.parameter\.email\_address | string | `email` action\_result\.parameter\.folder | string | `msgoffice365 mail folder` `msgoffice365 mail folder path` `msgoffice365 folder id` action\_result\.parameter\.get\_folder\_id | boolean | @@ -580,7 +706,9 @@ action\_result\.data\.\*\.ccRecipients\.email | string | `email` action\_result\.data\.\*\.ccRecipients\.name | string | action\_result\.data\.\*\.changeKey | string | action\_result\.data\.\*\.conversationId | string | +action\_result\.data\.\*\.conversationIndex | string | action\_result\.data\.\*\.createdDateTime | string | +action\_result\.data\.\*\.flag\.flagStatus | string | action\_result\.data\.\*\.from\.emailAddress\.address | string | `email` action\_result\.data\.\*\.from\.emailAddress\.name | string | action\_result\.data\.\*\.hasAttachments | boolean | @@ -588,7 +716,7 @@ action\_result\.data\.\*\.id | string | `msgoffice365 message id` action\_result\.data\.\*\.importance | string | action\_result\.data\.\*\.inferenceClassification | string | action\_result\.data\.\*\.internetMessageId | string | `msgoffice365 internet message id` -action\_result\.data\.\*\.isDeliveryReceiptRequested | string | +action\_result\.data\.\*\.isDeliveryReceiptRequested | boolean | action\_result\.data\.\*\.isDraft | boolean | action\_result\.data\.\*\.isRead | boolean | action\_result\.data\.\*\.isReadReceiptRequested | boolean | @@ -603,8 +731,9 @@ action\_result\.data\.\*\.subject | string | `msgoffice365 subject` action\_result\.data\.\*\.toRecipients\.\*\.emailAddress\.address | string | `email` action\_result\.data\.\*\.toRecipients\.\*\.emailAddress\.name | string | action\_result\.data\.\*\.webLink | string | `url` -action\_result\.summary | string | +action\_result\.status | string | action\_result\.message | string | +action\_result\.summary | string | summary\.total\_objects | numeric | summary\.total\_objects\_successful | numeric | @@ -623,12 +752,12 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS #### Action Output DATA PATH | TYPE | CONTAINS --------- | ---- | -------- -action\_result\.status | string | action\_result\.parameter\.email\_address | string | `email` action\_result\.parameter\.id | string | `msgoffice365 message id` action\_result\.data | string | -action\_result\.summary | string | +action\_result\.status | string | action\_result\.message | string | +action\_result\.summary | string | summary\.total\_objects | numeric | summary\.total\_objects\_successful | numeric | @@ -649,20 +778,21 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS #### Action Output DATA PATH | TYPE | CONTAINS --------- | ---- | -------- -action\_result\.status | string | action\_result\.parameter\.download\_attachments | boolean | action\_result\.parameter\.email\_address | string | `email` +action\_result\.parameter\.extract\_headers | boolean | action\_result\.parameter\.id | string | `msgoffice365 message id` action\_result\.data\.\*\.\@odata\.context | string | `url` action\_result\.data\.\*\.\@odata\.etag | string | +action\_result\.data\.\*\.attachments\.\*\.\@odata\.mediaContentType | string | action\_result\.data\.\*\.attachments\.\*\.\@odata\.type | string | action\_result\.data\.\*\.attachments\.\*\.attachmentType | string | -action\_result\.data\.\*\.attachments\.\*\.itemType | string | action\_result\.data\.\*\.attachments\.\*\.contentId | string | `email` action\_result\.data\.\*\.attachments\.\*\.contentLocation | string | action\_result\.data\.\*\.attachments\.\*\.contentType | string | action\_result\.data\.\*\.attachments\.\*\.id | string | action\_result\.data\.\*\.attachments\.\*\.isInline | boolean | +action\_result\.data\.\*\.attachments\.\*\.itemType | string | action\_result\.data\.\*\.attachments\.\*\.lastModifiedDateTime | string | action\_result\.data\.\*\.attachments\.\*\.name | string | action\_result\.data\.\*\.attachments\.\*\.size | numeric | @@ -677,15 +807,76 @@ action\_result\.data\.\*\.ccRecipients\.email | string | `email` action\_result\.data\.\*\.ccRecipients\.name | string | action\_result\.data\.\*\.changeKey | string | action\_result\.data\.\*\.conversationId | string | +action\_result\.data\.\*\.conversationIndex | string | action\_result\.data\.\*\.createdDateTime | string | +action\_result\.data\.\*\.flag\.flagStatus | string | action\_result\.data\.\*\.from\.emailAddress\.address | string | `email` action\_result\.data\.\*\.from\.emailAddress\.name | string | `email` action\_result\.data\.\*\.hasAttachments | boolean | action\_result\.data\.\*\.id | string | `msgoffice365 message id` action\_result\.data\.\*\.importance | string | action\_result\.data\.\*\.inferenceClassification | string | +action\_result\.data\.\*\.internetMessageHeaders\.Accept\-Language | string | +action\_result\.data\.\*\.internetMessageHeaders\.Authentication\-Results | string | +action\_result\.data\.\*\.internetMessageHeaders\.Content\-Language | string | +action\_result\.data\.\*\.internetMessageHeaders\.Content\-Transfer\-Encoding | string | +action\_result\.data\.\*\.internetMessageHeaders\.Content\-Type | string | +action\_result\.data\.\*\.internetMessageHeaders\.DKIM\-Signature | string | +action\_result\.data\.\*\.internetMessageHeaders\.Date | string | +action\_result\.data\.\*\.internetMessageHeaders\.From | string | +action\_result\.data\.\*\.internetMessageHeaders\.In\-Reply\-To | string | +action\_result\.data\.\*\.internetMessageHeaders\.MIME\-Version | string | +action\_result\.data\.\*\.internetMessageHeaders\.Message\-ID | string | +action\_result\.data\.\*\.internetMessageHeaders\.Received | string | +action\_result\.data\.\*\.internetMessageHeaders\.Received\-SPF | string | +action\_result\.data\.\*\.internetMessageHeaders\.References | string | +action\_result\.data\.\*\.internetMessageHeaders\.Return\-Path | string | `email` +action\_result\.data\.\*\.internetMessageHeaders\.Subject | string | +action\_result\.data\.\*\.internetMessageHeaders\.Thread\-Index | string | +action\_result\.data\.\*\.internetMessageHeaders\.Thread\-Topic | string | +action\_result\.data\.\*\.internetMessageHeaders\.To | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-EOPAttributedMessage | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-EOPTenantAttributedMessage | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Forefront\-Antispam\-Report | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Gm\-Message\-State | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Google\-DKIM\-Signature | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Google\-Smtp\-Source | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-AntiSpam\-MessageData | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-AuthAs | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-AuthSource | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-FromEntityHeader | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-Id | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-MailboxType | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-Network\-Message\-Id | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-OriginalArrivalTime | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-UserPrincipalName | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-AuthAs | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-AuthMechanism | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-AuthSource | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-ExpirationInterval | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-ExpirationIntervalReason | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-ExpirationStartTime | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-ExpirationStartTimeReason | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-MessageDirectionality | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-Network\-Message\-Id | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-SCL | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Processed\-By\-BccFoldering | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Transport\-CrossTenantHeadersStamped | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Transport\-EndToEndLatency | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Has\-Attach | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Office365\-Filtering\-Correlation\-Id | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Oob\-TLC\-OOBClassifiers | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-PublicTrafficType | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-TNEF\-Correlator | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-TrafficTypeDiagnostic | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Microsoft\-Antispam | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Microsoft\-Antispam\-Mailbox\-Delivery | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Microsoft\-Antispam\-Message\-Info | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Originating\-IP | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Received | string | +action\_result\.data\.\*\.internetMessageHeaders\.subject | string | action\_result\.data\.\*\.internetMessageId | string | `msgoffice365 internet message id` -action\_result\.data\.\*\.isDeliveryReceiptRequested | string | +action\_result\.data\.\*\.isDeliveryReceiptRequested | boolean | action\_result\.data\.\*\.isDraft | boolean | action\_result\.data\.\*\.isRead | boolean | action\_result\.data\.\*\.isReadReceiptRequested | boolean | @@ -700,53 +891,11 @@ action\_result\.data\.\*\.subject | string | `msgoffice365 subject` action\_result\.data\.\*\.toRecipients\.\*\.emailAddress\.address | string | `email` action\_result\.data\.\*\.toRecipients\.\*\.emailAddress\.name | string | action\_result\.data\.\*\.webLink | string | `url` -action\_result\.summary | string | +action\_result\.status | string | action\_result\.message | string | +action\_result\.summary | string | summary\.total\_objects | numeric | -summary\.total\_objects\_successful | numeric | -action\_result\.data\.\*\.flag\.flagStatus | string | -action\_result\.data\.\*\.internetMessageHeaders\.Return\-Path | string | `email` -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-ExpirationInterval | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Transport\-EndToEndLatency | string | -action\_result\.data\.\*\.internetMessageHeaders\.Received\-SPF | string | -action\_result\.data\.\*\.internetMessageHeaders\.Authentication\-Results | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-Microsoft\-Antispam | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Processed\-By\-BccFoldering | string | -action\_result\.data\.\*\.internetMessageHeaders\.Message\-ID | string | -action\_result\.data\.\*\.internetMessageHeaders\.subject | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-ExpirationStartTime | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Oob\-TLC\-OOBClassifiers | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-EOPTenantAttributedMessage | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-EOPAttributedMessage | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-AuthAs | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-Microsoft\-Antispam\-Mailbox\-Delivery | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-Google\-DKIM\-Signature | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-ExpirationIntervalReason | string | -action\_result\.data\.\*\.internetMessageHeaders\.Date | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-AuthSource | string | -action\_result\.data\.\*\.internetMessageHeaders\.Received | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Transport\-CrossTenantHeadersStamped | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-Received | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-Microsoft\-Antispam\-Message\-Info | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-Id | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Office365\-Filtering\-Correlation\-Id | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-Network\-Message\-Id | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-TrafficTypeDiagnostic | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-FromEntityHeader | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-Network\-Message\-Id | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-PublicTrafficType | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-OriginalArrivalTime | string | -action\_result\.data\.\*\.internetMessageHeaders\.MIME\-Version | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-SCL | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-Gm\-Message\-State | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-MessageDirectionality | string | -action\_result\.data\.\*\.internetMessageHeaders\.DKIM\-Signature | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-Forefront\-Antispam\-Report | string | -action\_result\.data\.\*\.internetMessageHeaders\.Content\-Type | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-Google\-Smtp\-Source | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-ExpirationStartTimeReason | string | -action\_result\.data\.\*\.conversationIndex | string | -action\_result\.parameter\.extract\_headers | boolean | +summary\.total\_objects\_successful | numeric | ## action: 'get email properties' Get non\-standard email properties from the server @@ -770,69 +919,88 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS #### Action Output DATA PATH | TYPE | CONTAINS --------- | ---- | -------- -action\_result\.status | string | -action\_result\.data\.\*\.body\.content | string | -action\_result\.data\.\*\.body\.contentType | string | -action\_result\.data\.\*\.sender\.emailAddress\.name | string | `email` -action\_result\.data\.\*\.sender\.emailAddress\.address | string | `email` -action\_result\.data\.\*\.\@odata\.context | string | `url` -action\_result\.data\.\*\.uniqueBody\.content | string | -action\_result\.data\.\*\.uniqueBody\.contentType | string | -action\_result\.data\.\*\.subject | string | -action\_result\.data\.\*\.id | string | -action\_result\.data\.\*\.\@odata\.etag | string | -action\_result\.message | string | -action\_result\.parameter\.properties\_list | string | -action\_result\.parameter\.get\_unique\_body | boolean | -action\_result\.parameter\.get\_headers | boolean | +action\_result\.parameter\.email\_address | string | `email` action\_result\.parameter\.get\_body | boolean | +action\_result\.parameter\.get\_headers | boolean | action\_result\.parameter\.get\_sender | boolean | -action\_result\.parameter\.email\_address | string | `email` +action\_result\.parameter\.get\_unique\_body | boolean | action\_result\.parameter\.id | string | `msgoffice365 message id` -action\_result\.summary | string | -summary\.total\_objects | numeric | -summary\.total\_objects\_successful | numeric | -action\_result\.data\.\*\.internetMessageHeaders\.Return\-Path | string | `email` -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-ExpirationInterval | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Transport\-EndToEndLatency | string | -action\_result\.data\.\*\.internetMessageHeaders\.Received\-SPF | string | +action\_result\.parameter\.properties\_list | string | +action\_result\.data\.\*\.\@odata\.context | string | `url` +action\_result\.data\.\*\.\@odata\.etag | string | +action\_result\.data\.\*\.body\.content | string | +action\_result\.data\.\*\.body\.contentType | string | +action\_result\.data\.\*\.id | string | +action\_result\.data\.\*\.internetMessageHeaders\.Accept\-Language | string | action\_result\.data\.\*\.internetMessageHeaders\.Authentication\-Results | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-Microsoft\-Antispam | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Processed\-By\-BccFoldering | string | +action\_result\.data\.\*\.internetMessageHeaders\.Content\-Language | string | +action\_result\.data\.\*\.internetMessageHeaders\.Content\-Transfer\-Encoding | string | +action\_result\.data\.\*\.internetMessageHeaders\.Content\-Type | string | +action\_result\.data\.\*\.internetMessageHeaders\.DKIM\-Signature | string | +action\_result\.data\.\*\.internetMessageHeaders\.Date | string | +action\_result\.data\.\*\.internetMessageHeaders\.From | string | +action\_result\.data\.\*\.internetMessageHeaders\.In\-Reply\-To | string | +action\_result\.data\.\*\.internetMessageHeaders\.MIME\-Version | string | action\_result\.data\.\*\.internetMessageHeaders\.Message\-ID | string | -action\_result\.data\.\*\.internetMessageHeaders\.subject | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-ExpirationStartTime | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Oob\-TLC\-OOBClassifiers | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-EOPTenantAttributedMessage | string | +action\_result\.data\.\*\.internetMessageHeaders\.Received | string | +action\_result\.data\.\*\.internetMessageHeaders\.Received\-SPF | string | +action\_result\.data\.\*\.internetMessageHeaders\.References | string | +action\_result\.data\.\*\.internetMessageHeaders\.Return\-Path | string | `email` +action\_result\.data\.\*\.internetMessageHeaders\.Subject | string | +action\_result\.data\.\*\.internetMessageHeaders\.Thread\-Index | string | +action\_result\.data\.\*\.internetMessageHeaders\.Thread\-Topic | string | +action\_result\.data\.\*\.internetMessageHeaders\.To | string | action\_result\.data\.\*\.internetMessageHeaders\.X\-EOPAttributedMessage | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-AuthAs | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-Microsoft\-Antispam\-Mailbox\-Delivery | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-EOPTenantAttributedMessage | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Forefront\-Antispam\-Report | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Gm\-Message\-State | string | action\_result\.data\.\*\.internetMessageHeaders\.X\-Google\-DKIM\-Signature | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-ExpirationIntervalReason | string | -action\_result\.data\.\*\.internetMessageHeaders\.Date | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-AuthSource | string | -action\_result\.data\.\*\.internetMessageHeaders\.Received | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Transport\-CrossTenantHeadersStamped | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-Received | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-Microsoft\-Antispam\-Message\-Info | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-Id | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Office365\-Filtering\-Correlation\-Id | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-Network\-Message\-Id | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-TrafficTypeDiagnostic | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Google\-Smtp\-Source | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-AntiSpam\-MessageData | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-AuthAs | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-AuthSource | string | action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-FromEntityHeader | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-Id | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-MailboxType | string | action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-Network\-Message\-Id | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-PublicTrafficType | string | action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-OriginalArrivalTime | string | -action\_result\.data\.\*\.internetMessageHeaders\.MIME\-Version | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-SCL | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-Gm\-Message\-State | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-MessageDirectionality | string | -action\_result\.data\.\*\.internetMessageHeaders\.DKIM\-Signature | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-Forefront\-Antispam\-Report | string | -action\_result\.data\.\*\.internetMessageHeaders\.Content\-Type | string | -action\_result\.data\.\*\.internetMessageHeaders\.X\-Google\-Smtp\-Source | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-CrossTenant\-UserPrincipalName | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-AuthAs | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-AuthMechanism | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-AuthSource | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-ExpirationInterval | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-ExpirationIntervalReason | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-ExpirationStartTime | string | action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-ExpirationStartTimeReason | string | -action\_result\.data\.\*\.receivedDateTime | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-MessageDirectionality | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-Network\-Message\-Id | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Organization\-SCL | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Processed\-By\-BccFoldering | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Transport\-CrossTenantHeadersStamped | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Exchange\-Transport\-EndToEndLatency | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Has\-Attach | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Office365\-Filtering\-Correlation\-Id | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-Oob\-TLC\-OOBClassifiers | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-PublicTrafficType | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-TNEF\-Correlator | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-MS\-TrafficTypeDiagnostic | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Microsoft\-Antispam | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Microsoft\-Antispam\-Mailbox\-Delivery | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Microsoft\-Antispam\-Message\-Info | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Originating\-IP | string | +action\_result\.data\.\*\.internetMessageHeaders\.X\-Received | string | +action\_result\.data\.\*\.internetMessageHeaders\.subject | string | +action\_result\.data\.\*\.receivedDateTime | string | +action\_result\.data\.\*\.sender\.emailAddress\.address | string | `email` +action\_result\.data\.\*\.sender\.emailAddress\.name | string | `email` +action\_result\.data\.\*\.subject | string | +action\_result\.data\.\*\.uniqueBody\.content | string | +action\_result\.data\.\*\.uniqueBody\.contentType | string | +action\_result\.status | string | +action\_result\.message | string | +action\_result\.summary | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | ## action: 'run query' Search emails @@ -859,7 +1027,6 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS #### Action Output DATA PATH | TYPE | CONTAINS --------- | ---- | -------- -action\_result\.status | string | action\_result\.parameter\.body | string | action\_result\.parameter\.email\_address | string | `email` action\_result\.parameter\.folder | string | `msgoffice365 mail folder` `msgoffice365 mail folder path` `msgoffice365 folder id` @@ -867,20 +1034,30 @@ action\_result\.parameter\.get\_folder\_id | boolean | action\_result\.parameter\.internet\_message\_id | string | `msgoffice365 internet message id` action\_result\.parameter\.limit | numeric | action\_result\.parameter\.query | string | +action\_result\.parameter\.search\_well\_known\_folders | boolean | action\_result\.parameter\.sender | string | `email` action\_result\.parameter\.subject | string | `msgoffice365 subject` action\_result\.data\.\*\.\@odata\.etag | string | +action\_result\.data\.\*\.\@odata\.type | string | +action\_result\.data\.\*\.allowNewTimeProposals | string | +action\_result\.data\.\*\.bccRecipients\.\*\.emailAddress\.address | string | +action\_result\.data\.\*\.bccRecipients\.\*\.emailAddress\.name | string | action\_result\.data\.\*\.bccRecipients\.email | string | `email` action\_result\.data\.\*\.bccRecipients\.name | string | action\_result\.data\.\*\.body\.content | string | action\_result\.data\.\*\.body\.contentType | string | action\_result\.data\.\*\.bodyPreview | string | action\_result\.data\.\*\.categories | string | +action\_result\.data\.\*\.ccRecipients\.\*\.emailAddress\.address | string | +action\_result\.data\.\*\.ccRecipients\.\*\.emailAddress\.name | string | action\_result\.data\.\*\.ccRecipients\.email | string | `email` action\_result\.data\.\*\.ccRecipients\.name | string | action\_result\.data\.\*\.changeKey | string | action\_result\.data\.\*\.conversationId | string | +action\_result\.data\.\*\.conversationIndex | string | action\_result\.data\.\*\.createdDateTime | string | +action\_result\.data\.\*\.endDateTime\.dateTime | string | +action\_result\.data\.\*\.endDateTime\.timeZone | string | action\_result\.data\.\*\.flag\.flagStatus | string | action\_result\.data\.\*\.from\.emailAddress\.address | string | `email` action\_result\.data\.\*\.from\.emailAddress\.name | string | @@ -889,54 +1066,45 @@ action\_result\.data\.\*\.id | string | `msgoffice365 message id` action\_result\.data\.\*\.importance | string | action\_result\.data\.\*\.inferenceClassification | string | action\_result\.data\.\*\.internetMessageId | string | `msgoffice365 internet message id` -action\_result\.data\.\*\.isDeliveryReceiptRequested | string | +action\_result\.data\.\*\.isAllDay | boolean | +action\_result\.data\.\*\.isDelegated | boolean | +action\_result\.data\.\*\.isDeliveryReceiptRequested | boolean | action\_result\.data\.\*\.isDraft | boolean | +action\_result\.data\.\*\.isOutOfDate | boolean | action\_result\.data\.\*\.isRead | boolean | action\_result\.data\.\*\.isReadReceiptRequested | boolean | action\_result\.data\.\*\.lastModifiedDateTime | string | +action\_result\.data\.\*\.meetingMessageType | string | +action\_result\.data\.\*\.meetingRequestType | string | action\_result\.data\.\*\.parentFolderId | string | `msgoffice365 folder id` +action\_result\.data\.\*\.previousEndDateTime | string | +action\_result\.data\.\*\.previousEndDateTime\.dateTime | string | +action\_result\.data\.\*\.previousEndDateTime\.timeZone | string | +action\_result\.data\.\*\.previousLocation | string | +action\_result\.data\.\*\.previousStartDateTime | string | +action\_result\.data\.\*\.previousStartDateTime\.dateTime | string | +action\_result\.data\.\*\.previousStartDateTime\.timeZone | string | action\_result\.data\.\*\.receivedDateTime | string | +action\_result\.data\.\*\.recurrence | string | action\_result\.data\.\*\.replyTo | string | +action\_result\.data\.\*\.replyTo\.\*\.emailAddress\.address | string | +action\_result\.data\.\*\.replyTo\.\*\.emailAddress\.name | string | +action\_result\.data\.\*\.responseRequested | boolean | action\_result\.data\.\*\.sender\.emailAddress\.address | string | `email` action\_result\.data\.\*\.sender\.emailAddress\.name | string | action\_result\.data\.\*\.sentDateTime | string | +action\_result\.data\.\*\.startDateTime\.dateTime | string | +action\_result\.data\.\*\.startDateTime\.timeZone | string | action\_result\.data\.\*\.subject | string | `msgoffice365 subject` action\_result\.data\.\*\.toRecipients\.\*\.emailAddress\.address | string | `email` action\_result\.data\.\*\.toRecipients\.\*\.emailAddress\.name | string | +action\_result\.data\.\*\.type | string | action\_result\.data\.\*\.webLink | string | `url` -action\_result\.summary\.emails\_matched | numeric | +action\_result\.status | string | action\_result\.message | string | +action\_result\.summary\.emails\_matched | numeric | summary\.total\_objects | numeric | -summary\.total\_objects\_successful | numeric | -action\_result\.parameter\.search\_well\_known\_folders | boolean | -action\_result\.data\.\*\.conversationIndex | string | -action\_result\.data\.\*\.ccRecipients\.\*\.emailAddress\.name | string | -action\_result\.data\.\*\.ccRecipients\.\*\.emailAddress\.address | string | -action\_result\.data\.\*\.replyTo\.\*\.emailAddress\.name | string | -action\_result\.data\.\*\.replyTo\.\*\.emailAddress\.address | string | -action\_result\.data\.\*\.bccRecipients\.\*\.emailAddress\.name | string | -action\_result\.data\.\*\.bccRecipients\.\*\.emailAddress\.address | string | -action\_result\.data\.\*\.type | string | -action\_result\.data\.\*\.isAllDay | boolean | -action\_result\.data\.\*\.recurrence | string | -action\_result\.data\.\*\.\@odata\.type | string | -action\_result\.data\.\*\.endDateTime\.dateTime | string | -action\_result\.data\.\*\.endDateTime\.timeZone | string | -action\_result\.data\.\*\.isDelegated | boolean | -action\_result\.data\.\*\.isOutOfDate | boolean | -action\_result\.data\.\*\.startDateTime\.dateTime | string | -action\_result\.data\.\*\.startDateTime\.timeZone | string | -action\_result\.data\.\*\.previousLocation | string | -action\_result\.data\.\*\.responseRequested | boolean | -action\_result\.data\.\*\.meetingMessageType | string | -action\_result\.data\.\*\.meetingRequestType | string | -action\_result\.data\.\*\.previousEndDateTime\.dateTime | string | -action\_result\.data\.\*\.previousEndDateTime\.timeZone | string | -action\_result\.data\.\*\.allowNewTimeProposals | string | -action\_result\.data\.\*\.previousStartDateTime\.dateTime | string | -action\_result\.data\.\*\.previousStartDateTime\.timeZone | string | -action\_result\.data\.\*\.previousEndDateTime | string | -action\_result\.data\.\*\.previousStartDateTime | string | +summary\.total\_objects\_successful | numeric | ## action: 'create folder' Create a new folder @@ -956,19 +1124,23 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS #### Action Output DATA PATH | TYPE | CONTAINS --------- | ---- | -------- -action\_result\.status | string | action\_result\.parameter\.all\_subdirs | boolean | action\_result\.parameter\.email\_address | string | `email` action\_result\.parameter\.folder | string | `msgoffice365 mail folder` `msgoffice365 mail folder path` +action\_result\.data\.\*\.\@odata\.context | string | `url` action\_result\.data\.\*\.\@odata\.etag | string | action\_result\.data\.\*\.childFolderCount | numeric | action\_result\.data\.\*\.displayName | string | action\_result\.data\.\*\.id | string | `msgoffice365 folder id` +action\_result\.data\.\*\.isHidden | boolean | action\_result\.data\.\*\.parentFolderId | string | `msgoffice365 folder id` +action\_result\.data\.\*\.sizeInBytes | numeric | action\_result\.data\.\*\.totalItemCount | numeric | action\_result\.data\.\*\.unreadItemCount | numeric | -action\_result\.summary | string | +action\_result\.status | string | action\_result\.message | string | +action\_result\.summary\.folder | string | +action\_result\.summary\.folders created | numeric | summary\.total\_objects | numeric | summary\.total\_objects\_successful | numeric | @@ -989,15 +1161,14 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS #### Action Output DATA PATH | TYPE | CONTAINS --------- | ---- | -------- -action\_result\.status | string | action\_result\.parameter\.email\_address | string | `email` action\_result\.parameter\.folder | string | `msgoffice365 mail folder` `msgoffice365 mail folder path` action\_result\.data\.\*\.folder | string | `msgoffice365 mail folder` `msgoffice365 mail folder path` action\_result\.data\.\*\.folder\_id | string | `msgoffice365 folder id` action\_result\.data\.\*\.path | string | `msgoffice365 mail folder` `msgoffice365 mail folder path` -action\_result\.summary | string | -action\_result\.summary\.folder\_id | string | `msgoffice365 folder id` +action\_result\.status | string | action\_result\.message | string | +action\_result\.summary\.folder\_id | string | `msgoffice365 folder id` summary\.total\_objects | numeric | summary\.total\_objects\_successful | numeric | @@ -1014,7 +1185,7 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS **end\_time** | optional | Parameter Ignored in this app | numeric | **container\_id** | optional | Parameter Ignored in this app | string | **container\_count** | required | Maximum number of emails to ingest | numeric | -**artifact\_count** | required | Maximum number of artifact to ingest | numeric | +**artifact\_count** | optional | Parameter Ignored in this app | numeric | #### Action Output -No Output +No Output \ No newline at end of file diff --git a/exclude_files.txt b/exclude_files.txt deleted file mode 100644 index 1dd604a..0000000 --- a/exclude_files.txt +++ /dev/null @@ -1,6 +0,0 @@ -docker-compose.yml -.gitlab-ci.yml -Makefile -.git* -whitesource* -gl-*.csv diff --git a/office365.json b/office365.json index 03f3aa1..14ec341 100644 --- a/office365.json +++ b/office365.json @@ -10,11 +10,11 @@ "product_version_regex": ".*", "publisher": "Splunk", "license": "Copyright (c) 2017-2022 Splunk Inc.", - "app_version": "2.4.14", + "app_version": "2.5.0", "utctime_updated": "2022-02-04T01:20:46.000000Z", "package_name": "phantom_msgraphoffice365", "main_module": "office365_connector.py", - "min_phantom_version": "5.1.0", + "min_phantom_version": "5.2.0", "latest_tested_versions": [ "Cloud 2021-09-28" ], @@ -73,51 +73,76 @@ "order": 8 }, "folder": { - "description": "Mailbox folder to ingest (On Poll)", + "description": "Mailbox folder name/folder path or the internal o365 folder ID to ingest (On Poll)", "data_type": "string", "order": 9 }, + "get_folder_id": { + "description": "Retrieve the folder ID for the provided folder name/folder path automatically and replace the folder parameter value (On Poll)", + "data_type": "boolean", + "default": true, + "order": 10 + }, + "ph_3": { + "data_type": "ph", + "order": 11 + }, "first_run_max_emails": { "description": "Maximum Containers for scheduled polling first time", "data_type": "numeric", "default": 1000, - "order": 10 + "order": 12 }, "max_containers": { "description": "Maximum Containers for scheduled polling", "data_type": "numeric", "default": 100, - "order": 11 + "order": 13 }, "extract_attachments": { "description": "Extract Attachments", "data_type": "boolean", "default": false, - "order": 12 + "order": 14 }, "extract_urls": { "description": "Extract URLs", "data_type": "boolean", "default": false, - "order": 13 + "order": 15 }, "extract_ips": { "description": "Extract IPs", "data_type": "boolean", "default": false, - "order": 14 + "order": 16 }, "extract_domains": { "description": "Extract Domain Names", "data_type": "boolean", "default": false, - "order": 15 + "order": 17 }, "extract_hashes": { "description": "Extract Hashes", "data_type": "boolean", "default": false, - "order": 16 + "order": 18 + }, + "ph_4": { + "data_type": "ph", + "order": 19 + }, + "ingest_manner": { + "data_type": "string", + "description": "How to Ingest (during ingestion, should the app get the latest emails or the oldest)", + "required": true, + "order": 20, + "value_list": [ + "oldest first", + "latest first" + ], + "default": "oldest first" } }, "actions": [ @@ -139,6 +164,10 @@ "read_only": false, "parameters": {}, "output": [ + { + "data_path": "action_result.data", + "data_type": "string" + }, { "data_path": "action_result.status", "data_type": "string", @@ -149,14 +178,6 @@ "column_name": "Status", "column_order": 0 }, - { - "data_path": "action_result.data", - "data_type": "string" - }, - { - "data_path": "action_result.summary", - "data_type": "string" - }, { "data_path": "action_result.message", "data_type": "string", @@ -166,6 +187,10 @@ "column_name": "Message", "column_order": 1 }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, { "data_path": "summary.total_objects", "data_type": "numeric", @@ -207,14 +232,6 @@ } }, "output": [ - { - "data_path": "action_result.status", - "data_type": "string", - "example_values": [ - "success", - "failed" - ] - }, { "data_path": "action_result.parameter.user_id", "data_type": "string", @@ -224,12 +241,68 @@ "email" ], "column_name": "User ID/Principle Name", - "column_order": 0 + "column_order": 0, + "example_values": [ + "eeb3645f-df19-58a1-0e9c-ghi234cb5f6f" + ] + }, + { + "data_path": "action_result.data.*.@odata.context", + "data_type": "string", + "example_values": [ + "https://graph.microsoft.com/v1.0/$metadata#users('eeb3645f-df19-47a1-8e8c-fcd234cb5f6f')/mailboxSettings/automaticRepliesSetting" + ], + "contains": [ + "url" + ] }, { "data_path": "action_result.data.*.@odata.etag", "data_type": "string" }, + { + "data_path": "action_result.data.*.externalAudience", + "data_type": "string", + "example_values": [ + "all" + ] + }, + { + "data_path": "action_result.data.*.externalReplyMessage", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.internalReplyMessage", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.scheduledEndDateTime.dateTime", + "data_type": "string", + "example_values": [ + "2022-03-15T12:00:00.0000000" + ] + }, + { + "data_path": "action_result.data.*.scheduledEndDateTime.timeZone", + "data_type": "string", + "example_values": [ + "UTC" + ] + }, + { + "data_path": "action_result.data.*.scheduledStartDateTime.dateTime", + "data_type": "string", + "example_values": [ + "2022-03-14T12:00:00.0000000" + ] + }, + { + "data_path": "action_result.data.*.scheduledStartDateTime.timeZone", + "data_type": "string", + "example_values": [ + "UTC" + ] + }, { "data_path": "action_result.data.*.status", "data_type": "string", @@ -240,10 +313,11 @@ ] }, { - "data_path": "action_result.summary.events_matched", - "data_type": "numeric", + "data_path": "action_result.status", + "data_type": "string", "example_values": [ - 1 + "success", + "failed" ] }, { @@ -253,6 +327,13 @@ "Successfully retrieved out of office status" ] }, + { + "data_path": "action_result.summary.events_matched", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, { "data_path": "summary.total_objects", "data_type": "numeric", @@ -286,7 +367,6 @@ "user_id": { "description": "User ID/Principal name", "data_type": "string", - "required": false, "primary": true, "contains": [ "msgoffice365 user id", @@ -298,7 +378,6 @@ "group_id": { "description": "Group ID", "data_type": "string", - "required": false, "primary": true, "contains": [ "msgoffice365 group id" @@ -308,25 +387,15 @@ "filter": { "description": "OData query to filter/search for specific results", "data_type": "string", - "required": false, "order": 2 }, "limit": { "description": "Maximum number of events to return", "data_type": "numeric", - "required": false, "order": 3 } }, "output": [ - { - "data_path": "action_result.status", - "data_type": "string", - "example_values": [ - "success", - "failed" - ] - }, { "data_path": "action_result.parameter.filter", "data_type": "string", @@ -340,6 +409,9 @@ "data_type": "string", "contains": [ "msgoffice365 group id" + ], + "example_values": [ + "3d9c58f8-9f38-4016-93ac-b61095f31c48" ] }, { @@ -368,6 +440,14 @@ "W/\"b1MzKFCcdkuJ24Mc2VsdjwABAdhQhg==\"" ] }, + { + "data_path": "action_result.data.*.allowNewTimeProposals", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, { "data_path": "action_result.data.*.attendee_list", "data_type": "string", @@ -433,6 +513,26 @@ "data_path": "action_result.data.*.bodyPreview", "data_type": "string" }, + { + "data_path": "action_result.data.*.calendar@odata.associationLink", + "data_type": "string", + "example_values": [ + "https://graph.microsoft.com/v1.0/users('ggfe645f-df19-47a1-8e8c-fcd234cb5f6f')/calendars('AQMkAGYxNGJmOWQyLTlhMjctNGRiOS1iODU0LTA1ZWE3ZmQ3NDU3MQBGAAADeDDJKaEf4EihMWU6SZgKbAcA07XhOkNngkCkqoNfY_k-jQAAAgEGAAAA07XhOkNngkCkqoNfY_k-jQAAAhTzBBAA')/$ref" + ], + "contains": [ + "url" + ] + }, + { + "data_path": "action_result.data.*.calendar@odata.navigationLink", + "data_type": "string", + "example_values": [ + "https://graph.microsoft.com/v1.0/users('ffb3645f-df20-47a1-8e9c-fcd234cb5f6f')/calendars('AQMkAGYxNGJmOWQyLTlhMjctNGRiOS1iODU0LTA1ZWE3ZmQ3NDU3MQBGAAADeDDJKaEf4EihMWU6SZgKbAcA07XhOkNngkCkqoNfY_k-jQAAAgEGAAAA07XhOkNngkCkqoNfY_k-jQAAAhTzABBB')" + ], + "contains": [ + "url" + ] + }, { "data_path": "action_result.data.*.categories.*.name", "data_type": "string" @@ -475,6 +575,14 @@ false ] }, + { + "data_path": "action_result.data.*.hideAttendees", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, { "data_path": "action_result.data.*.iCalUId", "data_type": "string", @@ -512,6 +620,22 @@ false ] }, + { + "data_path": "action_result.data.*.isDraft", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.isOnlineMeeting", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, { "data_path": "action_result.data.*.isOrganizer", "data_type": "boolean", @@ -709,6 +833,21 @@ "locationStore" ] }, + { + "data_path": "action_result.data.*.occurrenceId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onlineMeeting", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onlineMeetingProvider", + "data_type": "string", + "example_values": [ + "unknown" + ] + }, { "data_path": "action_result.data.*.onlineMeetingUrl", "data_type": "string", @@ -823,6 +962,13 @@ "New event - 1" ] }, + { + "data_path": "action_result.data.*.transactionId", + "data_type": "string", + "example_values": [ + "b2e47e5d-8f87-9845-c507-7be56490c432" + ] + }, { "data_path": "action_result.data.*.type", "data_type": "string", @@ -845,10 +991,11 @@ "data_type": "string" }, { - "data_path": "action_result.summary.events_matched", - "data_type": "numeric", + "data_path": "action_result.status", + "data_type": "string", "example_values": [ - 8 + "success", + "failed" ] }, { @@ -858,6 +1005,13 @@ "Successfully retrieved 8 events" ] }, + { + "data_path": "action_result.summary.events_matched", + "data_type": "numeric", + "example_values": [ + 8 + ] + }, { "data_path": "summary.total_objects", "data_type": "numeric", @@ -892,25 +1046,15 @@ "filter": { "description": "Search for specific results", "data_type": "string", - "required": false, "order": 0 }, "limit": { "description": "Maximum number of users to return", "data_type": "numeric", - "required": false, "order": 1 } }, "output": [ - { - "data_path": "action_result.status", - "data_type": "string", - "example_values": [ - "success", - "failed" - ] - }, { "data_path": "action_result.parameter.filter", "data_type": "string", @@ -1011,10 +1155,11 @@ "column_order": 1 }, { - "data_path": "action_result.summary.total_users_returned", - "data_type": "numeric", + "data_path": "action_result.status", + "data_type": "string", "example_values": [ - 11 + "success", + "failed" ] }, { @@ -1024,6 +1169,13 @@ "Successfully retrieved 11 users" ] }, + { + "data_path": "action_result.summary.total_users_returned", + "data_type": "numeric", + "example_values": [ + 11 + ] + }, { "data_path": "summary.total_objects", "data_type": "numeric", @@ -1057,25 +1209,15 @@ "filter": { "description": "Search for specific results", "data_type": "string", - "required": false, "order": 0 }, "limit": { "description": "Maximum number of groups to return", "data_type": "numeric", - "required": false, "order": 1 } }, "output": [ - { - "data_path": "action_result.status", - "data_type": "string", - "example_values": [ - "success", - "failed" - ] - }, { "data_path": "action_result.parameter.filter", "data_type": "string", @@ -1130,6 +1272,10 @@ "column_name": "Display Name", "column_order": 2 }, + { + "data_path": "action_result.data.*.expirationDateTime", + "data_type": "string" + }, { "data_path": "action_result.data.*.groupTypes", "data_type": "string", @@ -1182,10 +1328,30 @@ "Test-test-site" ] }, + { + "data_path": "action_result.data.*.membershipRule", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.membershipRuleProcessingState", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesDomainName", + "data_type": "string" + }, { "data_path": "action_result.data.*.onPremisesLastSyncDateTime", "data_type": "string" }, + { + "data_path": "action_result.data.*.onPremisesNetBiosName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesSamAccountName", + "data_type": "string" + }, { "data_path": "action_result.data.*.onPremisesSecurityIdentifier", "data_type": "string" @@ -1198,6 +1364,10 @@ "data_path": "action_result.data.*.preferredDataLocation", "data_type": "string" }, + { + "data_path": "action_result.data.*.preferredLanguage", + "data_type": "string" + }, { "data_path": "action_result.data.*.proxyAddresses", "data_type": "string", @@ -1234,6 +1404,17 @@ false ] }, + { + "data_path": "action_result.data.*.securityIdentifier", + "data_type": "string", + "example_values": [ + "S-1-12-1-294681889-1319597617-672379543-28952022" + ] + }, + { + "data_path": "action_result.data.*.theme", + "data_type": "string" + }, { "data_path": "action_result.data.*.visibility", "data_type": "string", @@ -1244,10 +1425,11 @@ "column_order": 5 }, { - "data_path": "action_result.summary.total_groups_returned", - "data_type": "numeric", + "data_path": "action_result.status", + "data_type": "string", "example_values": [ - 9 + "success", + "failed" ] }, { @@ -1257,6 +1439,13 @@ "Successfully retrieved 9 groups" ] }, + { + "data_path": "action_result.summary.total_groups_returned", + "data_type": "numeric", + "example_values": [ + 9 + ] + }, { "data_path": "summary.total_objects", "data_type": "numeric", @@ -1303,7 +1492,6 @@ "folder_id": { "description": "Parent mail folder ID", "data_type": "string", - "required": false, "primary": true, "order": 1, "contains": [ @@ -1312,14 +1500,6 @@ } }, "output": [ - { - "data_path": "action_result.status", - "data_type": "string", - "example_values": [ - "success", - "failed" - ] - }, { "data_path": "action_result.parameter.folder_id", "data_type": "string", @@ -1372,6 +1552,14 @@ "msgoffice365 folder id" ] }, + { + "data_path": "action_result.data.*.isHidden", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, { "data_path": "action_result.data.*.parentFolderId", "data_type": "string", @@ -1384,6 +1572,13 @@ "msgoffice365 folder id" ] }, + { + "data_path": "action_result.data.*.sizeInBytes", + "data_type": "numeric", + "example_values": [ + 7920 + ] + }, { "data_path": "action_result.data.*.totalItemCount", "data_type": "numeric", @@ -1403,10 +1598,11 @@ "column_order": 4 }, { - "data_path": "action_result.summary.total_folders_returned", - "data_type": "numeric", + "data_path": "action_result.status", + "data_type": "string", "example_values": [ - 14 + "success", + "failed" ] }, { @@ -1416,6 +1612,13 @@ "Successfully retrieved 14 mail folders" ] }, + { + "data_path": "action_result.summary.total_folders_returned", + "data_type": "numeric", + "example_values": [ + 14 + ] + }, { "data_path": "summary.total_objects", "data_type": "numeric", @@ -1464,7 +1667,8 @@ "contains": [ "email" ], - "order": 1 + "order": 1, + "primary": true }, "folder": { "description": "Destination folder; this must be either a (case-sensitive) well-known name or the internal o365 folder ID", @@ -1486,14 +1690,6 @@ } }, "output": [ - { - "data_path": "action_result.status", - "data_type": "string", - "example_values": [ - "success", - "failed" - ] - }, { "data_path": "action_result.parameter.email_address", "data_type": "string", @@ -1635,6 +1831,13 @@ "AAQkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQAQANDpL7xEHORGgd1idbVXqcg=" ] }, + { + "data_path": "action_result.data.*.conversationIndex", + "data_type": "string", + "example_values": [ + "AQHW+IHb9hH4JnJtjUmniPjyy9YF2Y==" + ] + }, { "data_path": "action_result.data.*.createdDateTime", "data_type": "string", @@ -1642,6 +1845,13 @@ "2017-10-25T22:29:01Z" ] }, + { + "data_path": "action_result.data.*.flag.flagStatus", + "data_type": "string", + "example_values": [ + "notFlagged" + ] + }, { "data_path": "action_result.data.*.from.emailAddress.address", "data_type": "string", @@ -1707,7 +1917,11 @@ }, { "data_path": "action_result.data.*.isDeliveryReceiptRequested", - "data_type": "string" + "data_type": "boolean", + "example_values": [ + true, + false + ] }, { "data_path": "action_result.data.*.isDraft", @@ -1823,8 +2037,12 @@ ] }, { - "data_path": "action_result.summary", - "data_type": "string" + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] }, { "data_path": "action_result.message", @@ -1833,6 +2051,10 @@ "Successfully copied email" ] }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, { "data_path": "summary.total_objects", "data_type": "numeric", @@ -1904,14 +2126,6 @@ } }, "output": [ - { - "data_path": "action_result.status", - "data_type": "string", - "example_values": [ - "success", - "failed" - ] - }, { "data_path": "action_result.parameter.email_address", "data_type": "string", @@ -2053,6 +2267,13 @@ "AAQkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQAQANDpL7xEHORGgd1idbVXqcg=" ] }, + { + "data_path": "action_result.data.*.conversationIndex", + "data_type": "string", + "example_values": [ + "AQHW+IHb9hH4JnJtjUmniPjyy9YF1Y==" + ] + }, { "data_path": "action_result.data.*.createdDateTime", "data_type": "string", @@ -2060,6 +2281,13 @@ "2017-10-25T22:29:01Z" ] }, + { + "data_path": "action_result.data.*.flag.flagStatus", + "data_type": "string", + "example_values": [ + "notFlagged" + ] + }, { "data_path": "action_result.data.*.from.emailAddress.address", "data_type": "string", @@ -2125,7 +2353,11 @@ }, { "data_path": "action_result.data.*.isDeliveryReceiptRequested", - "data_type": "string" + "data_type": "boolean", + "example_values": [ + true, + false + ] }, { "data_path": "action_result.data.*.isDraft", @@ -2241,8 +2473,12 @@ ] }, { - "data_path": "action_result.summary", - "data_type": "string" + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] }, { "data_path": "action_result.message", @@ -2251,6 +2487,10 @@ "Successfully moved email" ] }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, { "data_path": "summary.total_objects", "data_type": "numeric", @@ -2303,16 +2543,6 @@ } }, "output": [ - { - "data_path": "action_result.status", - "data_type": "string", - "column_name": "Status", - "column_order": 2, - "example_values": [ - "success", - "failed" - ] - }, { "data_path": "action_result.parameter.email_address", "data_type": "string", @@ -2342,8 +2572,14 @@ "data_type": "string" }, { - "data_path": "action_result.summary", - "data_type": "string" + "data_path": "action_result.status", + "data_type": "string", + "column_name": "Status", + "column_order": 2, + "example_values": [ + "success", + "failed" + ] }, { "data_path": "action_result.message", @@ -2352,6 +2588,10 @@ "Successfully deleted email" ] }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, { "data_path": "summary.total_objects", "data_type": "numeric", @@ -2414,14 +2654,6 @@ } }, "output": [ - { - "data_path": "action_result.status", - "data_type": "string", - "example_values": [ - "success", - "failed" - ] - }, { "data_path": "action_result.parameter.download_attachments", "data_type": "boolean", @@ -2440,6 +2672,14 @@ "test@onmicrosoft.com" ] }, + { + "data_path": "action_result.parameter.extract_headers", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, { "data_path": "action_result.parameter.id", "data_type": "string", @@ -2469,24 +2709,24 @@ ] }, { - "data_path": "action_result.data.*.attachments.*.@odata.type", + "data_path": "action_result.data.*.attachments.*.@odata.mediaContentType", "data_type": "string", "example_values": [ - "#microsoft.graph.fileAttachment" + "application/octet-stream" ] }, { - "data_path": "action_result.data.*.attachments.*.attachmentType", + "data_path": "action_result.data.*.attachments.*.@odata.type", "data_type": "string", "example_values": [ "#microsoft.graph.fileAttachment" ] }, { - "data_path": "action_result.data.*.attachments.*.itemType", + "data_path": "action_result.data.*.attachments.*.attachmentType", "data_type": "string", "example_values": [ - "#microsoft.graph.message" + "#microsoft.graph.fileAttachment" ] }, { @@ -2525,6 +2765,13 @@ false ] }, + { + "data_path": "action_result.data.*.attachments.*.itemType", + "data_type": "string", + "example_values": [ + "#microsoft.graph.message" + ] + }, { "data_path": "action_result.data.*.attachments.*.lastModifiedDateTime", "data_type": "string", @@ -2634,6 +2881,13 @@ "AAQkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQAQAE0u8cumTkhHhJdGoa0RzX0=" ] }, + { + "data_path": "action_result.data.*.conversationIndex", + "data_type": "string", + "example_values": [ + "AQHWRVB0TS7xy6ZOSEeEl0ahrRHNfQ==" + ] + }, { "data_path": "action_result.data.*.createdDateTime", "data_type": "string", @@ -2642,6 +2896,13 @@ "2020-06-18T09:11:31Z" ] }, + { + "data_path": "action_result.data.*.flag.flagStatus", + "data_type": "string", + "example_values": [ + "notFlagged" + ] + }, { "data_path": "action_result.data.*.from.emailAddress.address", "data_type": "string", @@ -2696,265 +2957,244 @@ ] }, { - "data_path": "action_result.data.*.internetMessageId", + "data_path": "action_result.data.*.internetMessageHeaders.Accept-Language", "data_type": "string", "example_values": [ - "", - "<5eeb2fbe.1c69fb81.22b4b.676a@mx.google.com>" - ], - "contains": [ - "msgoffice365 internet message id" + "en-US" ] }, { - "data_path": "action_result.data.*.isDeliveryReceiptRequested", + "data_path": "action_result.data.*.internetMessageHeaders.Authentication-Results", "data_type": "string", - "example_values": [] - }, - { - "data_path": "action_result.data.*.isDraft", - "data_type": "boolean", "example_values": [ - true, - false + "spf=pass (sender IP is 209.85.210.171) smtp.mailfrom=testdomain.com; .onmicrosoft.com; dkim=pass (signature was verified) header.d=testdomain.com.20150623.gappssmtp.com;.onmicrosoft.com; dmarc=pass action=none header.from=testdomain.com;compauth=pass reason=100" ] }, { - "data_path": "action_result.data.*.isRead", - "data_type": "boolean", + "data_path": "action_result.data.*.internetMessageHeaders.Content-Language", + "data_type": "string", "example_values": [ - true, - false + "en-US" ] }, { - "data_path": "action_result.data.*.isReadReceiptRequested", - "data_type": "boolean", + "data_path": "action_result.data.*.internetMessageHeaders.Content-Transfer-Encoding", + "data_type": "string", "example_values": [ - true, - false + "binary" ] }, { - "data_path": "action_result.data.*.lastModifiedDateTime", + "data_path": "action_result.data.*.internetMessageHeaders.Content-Type", "data_type": "string", "example_values": [ - "2017-10-26T01:31:43Z", - "2020-06-18T09:11:32Z" + "multipart/related" ] }, { - "data_path": "action_result.data.*.parentFolderId", + "data_path": "action_result.data.*.internetMessageHeaders.DKIM-Signature", "data_type": "string", - "contains": [ - "msgoffice365 folder id" - ], "example_values": [ - "AQMkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQAuAAADyW3X5P7Hb0_MMHKonvdoWQEAQSl1b8BFiEmbqZql_JiUtwAAAgEMAAAA" + "v=1; a=rsa-sha256; c=relaxed/relaxed; d=testdomain.com.20150623.gappssmtp.com; s=20150623; h=message-id:date:mime-version:from:to:subject; bh=tlTaRbacq4aWozhUPvcWg8i8flbpYQGZNs27nncn83I=; b=avAAeJ8jF08K4oIBhxTirRmyB+SXHwdU0zdxv7eqs/zWaWWcgmT0007KP560TTgo5u oD4nb6TvKxpRyWW4QwmkbuMIwHsMvehd2l1gispV3AawyGJjpmN7ErVYfLtIkz2Tap3V YxmluV+SqeyyxTU8pFAEZ7+2C2lOb1DO5TC7xCMv+dyzevSscJdbeN0dFkG+C93zCqkg w2fxubx2HDD7b/U6m2wXllYhH608wKJ/qYzyvQyqxYqNiQOtPRg2gw4sZ2UgN3+UQyVq 8ubO39ZuqakJpzEzYMw10d6E7SQhvHDJH7mFwhBlzhvOpb2gLJDN8n8dJaZo05BozQqq MsvA==" ] }, { - "data_path": "action_result.data.*.receivedDateTime", + "data_path": "action_result.data.*.internetMessageHeaders.Date", "data_type": "string", "example_values": [ - "2017-10-26T01:31:43Z", - "2020-06-18T09:11:31Z" + "Thu, 18 Jun 2020 02:11:26 -0700" ] }, { - "data_path": "action_result.data.*.replyTo", - "data_type": "string" - }, - { - "data_path": "action_result.data.*.sender.emailAddress.address", + "data_path": "action_result.data.*.internetMessageHeaders.From", "data_type": "string", "example_values": [ - "test@testdomain.onmicrosoft.com" - ], - "contains": [ - "email" + "\"Test\" " ] }, { - "data_path": "action_result.data.*.sender.emailAddress.name", + "data_path": "action_result.data.*.internetMessageHeaders.In-Reply-To", "data_type": "string", "example_values": [ - "Test Name" - ], - "contains": [ - "email" + "" ] }, { - "data_path": "action_result.data.*.sentDateTime", + "data_path": "action_result.data.*.internetMessageHeaders.MIME-Version", "data_type": "string", "example_values": [ - "2017-10-26T01:31:35Z", - "2020-06-18T09:11:26Z" + "1.0" ] }, { - "data_path": "action_result.data.*.subject", + "data_path": "action_result.data.*.internetMessageHeaders.Message-ID", "data_type": "string", "example_values": [ - "more attachments", - "test html" - ], - "contains": [ - "msgoffice365 subject" + "<5eeb2fbe.1c69fb81.22b4b.676a@mx.google.com>" ] }, { - "data_path": "action_result.data.*.toRecipients.*.emailAddress.address", + "data_path": "action_result.data.*.internetMessageHeaders.Received", "data_type": "string", "example_values": [ - "Test@testdomain.onmicrosoft.com" - ], - "contains": [ - "email" + "from localhost.localdomain (host-240.splunk.com. [204.107.141.240]) by smtp.gmail.com with UTF8SMTPSA id ng12sm1923252pjb.15.2020.06.18.02.11.26 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 18 Jun 2020 02:11:26 -0700 (PDT)" ] }, { - "data_path": "action_result.data.*.toRecipients.*.emailAddress.name", + "data_path": "action_result.data.*.internetMessageHeaders.Received-SPF", "data_type": "string", "example_values": [ - "Test Name" + "Pass (protection.outlook.com: domain of testdomain.com designates 209.85.210.171 as permitted sender) receiver=protection.outlook.com; client-ip=209.85.210.171; helo=mail-pf1-f171.google.com;" ] }, { - "data_path": "action_result.data.*.webLink", + "data_path": "action_result.data.*.internetMessageHeaders.References", "data_type": "string", "example_values": [ - "https://outlook.office365.com/owa/?ItemID=AQMkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQBGAAADyW3X5P7Hb0%2BMMHKonvdoWQcAQSl1b8BFiEmbqZql%2BJiUtwAAAgEMAAAAQSl1b8BFiEmbqZql%2BJiUtwABS2DpfAAAAA%3D%3D&exvsurl=1&viewmodel=ReadMessageItem" + "" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.Return-Path", + "data_type": "string", + "example_values": [ + "notifications@testdomain.com" ], "contains": [ - "url" + "email" ] }, { - "data_path": "action_result.summary", - "data_type": "string" + "data_path": "action_result.data.*.internetMessageHeaders.Subject", + "data_type": "string", + "example_values": [ + "Fw: Email having different attachments" + ] }, { - "data_path": "action_result.message", + "data_path": "action_result.data.*.internetMessageHeaders.Thread-Index", "data_type": "string", "example_values": [ - "Successfully fetched email" + "AQDEZLqyXR4k4Sc6skyFCMPITcMsbKpGS7At" ] }, { - "data_path": "summary.total_objects", - "data_type": "numeric", + "data_path": "action_result.data.*.internetMessageHeaders.Thread-Topic", + "data_type": "string", "example_values": [ - 1 + "Email having different attachments" ] }, { - "data_path": "summary.total_objects_successful", - "data_type": "numeric", + "data_path": "action_result.data.*.internetMessageHeaders.To", + "data_type": "string", "example_values": [ - 1 + "\"Test\" " ] }, { - "data_path": "action_result.data.*.flag.flagStatus", + "data_path": "action_result.data.*.internetMessageHeaders.X-EOPAttributedMessage", "data_type": "string", "example_values": [ - "notFlagged" + "0" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.Return-Path", + "data_path": "action_result.data.*.internetMessageHeaders.X-EOPTenantAttributedMessage", "data_type": "string", "example_values": [ - "notifications@testdomain.com" - ], - "contains": [ - "email" + "a417c578-c7ee-480d-a225-d48057e74df5:0" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-ExpirationInterval", + "data_path": "action_result.data.*.internetMessageHeaders.X-Forefront-Antispam-Report", "data_type": "string", "example_values": [ - "1:00:00:00.0000000" + "CIP:209.85.210.171;CTRY:US;LANG:en;SCL:-1;SRV:;IPV:NLI;SFV:SFE;H:mail-pf1-f171.google.com;PTR:mail-pf1-f171.google.com;CAT:NONE;SFTY:;SFS:;DIR:INB;SFP:;" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Transport-EndToEndLatency", + "data_path": "action_result.data.*.internetMessageHeaders.X-Gm-Message-State", "data_type": "string", "example_values": [ - "00:00:02.7417647" + "AOAM533ynFERIhSIewEEkj4b8B1rPNOEeie1IxBdrd55treEMtBa1jkL\tcO5ee4Ff6p0FYedfFtVtHKiCglGTpFTOSw==" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.Received-SPF", + "data_path": "action_result.data.*.internetMessageHeaders.X-Google-DKIM-Signature", "data_type": "string", "example_values": [ - "Pass (protection.outlook.com: domain of testdomain.com designates 209.85.210.171 as permitted sender) receiver=protection.outlook.com; client-ip=209.85.210.171; helo=mail-pf1-f171.google.com;" + "v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:date:mime-version:from:to:subject; bh=tlTaRbacq4aWozhUPvcWg8i8flbpYQGZNs27nncn83I=; b=fPT47NIiheeY6GM0bxUOlsmnOgN4WuiOlalFvZqrAiFiOoYk6zrznvgIcAtiHZ4nxE naQAa+mZs5svqRjib3YI52OvR5U8MitIYaa0Rt3LyYSUO1s3iKTUs4nHyRnqPt1skNl7 2OUwsZPXo3ShJDw/uxZRu/cuN1iIfeuE02PrbR04p4D8+1XRslqt/Xqm/bOWKUauqZWe dH1E7meFY01hXxODreO4nWHIhsZgr49TpP/OqRyFcyKHHFFg2sPGXz+QNah6jP4YQUYd Tty2wzOX3nc/YS7TkVo3ORmbzh9o+UZaqH8wHbQlyTdklYxoMPvJwZTo72rTxZeqiJ9E J7PQ==" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.Authentication-Results", + "data_path": "action_result.data.*.internetMessageHeaders.X-Google-Smtp-Source", "data_type": "string", "example_values": [ - "spf=pass (sender IP is 209.85.210.171) smtp.mailfrom=testdomain.com; .onmicrosoft.com; dkim=pass (signature was verified) header.d=testdomain.com.20150623.gappssmtp.com;.onmicrosoft.com; dmarc=pass action=none header.from=testdomain.com;compauth=pass reason=100" + "ABdhPJxrYC7raBubCCIOmauxmxryzS9KsihTN6XCRgaNp2rDrG71TVxryzYCtelFOZ2Xj1LzcYIiMA==" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-Microsoft-Antispam", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-AntiSpam-MessageData", "data_type": "string", "example_values": [ - "BCL:0;" + "VSM9HTzub/OH3NCwWNKQqkkzjnhdw5kXsgd9WM0SRgZ0qRdPg5D9/o3LA7lf8ziXc5k0mm9M5mHvFoYePXNXs/MGhGdBGxa/qUQ+FVHA2mDgfPkamJCEZxz//OX/uruTDo+zF4p9D1dQJpnIpx1M75OhuvrHX/BxWWzyAh78DXfF214YHdyFBCYepwl56CS7+fSGQL/r3p+OvWIBnIkISC+HJljSro2k47pPPAkspMhoUkb+zklyENFjez+JcEHYlih2FiNeUO8kb9b7qvlm3zPK98HLspzDh4BojpQ6Ff330iy7nfIK726tCMByxjOdnEQSB9Ua2sbE5gxSeeWL8MB5DHcQSSsXg+sR8w4gXrXLO3meE0lNQKRoAv2b1U0Q+yM0QBqeQWlymZG21bKeuH4gtAFQvfXNjoCtIbBQK1n7ZnL7fI21FJZRcMcKEneus6gLYUqD4PdLEq9FEGbfgiLmVYeUAL2A0Q/gectvL1OVudtHVR5gFMJKt65F1OtS04CPulfLLFSl1F4AzpjjtBSyQcK9R7bOsjoHxQXPMd9fMCzMSIq5f551pO0klKqWY7l11Un2Noj6CA7EtXiD1bTv8JmYQEKR+0HTZagNd+79GeTvKjxTvt9MkyO8k3aqWyNqT331ITnVICtksN1TVMCp8GVeDudNMr2PLSW0alOduR5unuEgTWrqHoaTGOovQx0PVjudNlpZ80ANK9hqaC/ZhLLOtNpJ3fZnjs06PzrPLGhE/IeccY1n8sYDvGm1QA9TN6JaaGPl1Pj6ecy16k0XuF/PKGHTL0M4LCpxSS6T87oFFH1zHkKtmbJp3aAI4bt3ihbQmwFb29JyMgL7ZOy+zrIwXGILh1KQGWQQv1uXXnAuqQy29HeFXs6D2hDHxHlBk5ZQ+vgRtsvRvGnq58vJ3CapjntfL3pOINUj1avLyAZxjasBWMTwaZs9JQ4ZIMekzkIk05lh9XfDSeULk2yKaH8YSCC6ENUHxSWa6pPHJfOdp9kXwOtlp09/VTTAikKy862k9ybN4bRWZB45B9Pv5scna8IX3rthIXUih8c=" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Processed-By-BccFoldering", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-AuthAs", "data_type": "string", "example_values": [ - "15.20.3109.017" + "Internal" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.Message-ID", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-AuthSource", "data_type": "string", "example_values": [ - "<5eeb2fbe.1c69fb81.22b4b.676a@mx.google.com>" + "SJ0PR22MB4941.namprd11.prod.outlook.com" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.subject", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-FromEntityHeader", "data_type": "string", "example_values": [ - "test html" + "Internet" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-ExpirationStartTime", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-Id", "data_type": "string", "example_values": [ - "18 Jun 2020 09:11:28.2531 (UTC)" + "a417c578-c7ee-480d-a225-d48057e74df5" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Oob-TLC-OOBClassifiers", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-MailboxType", "data_type": "string", "example_values": [ - "OLM:1728;" + "HOSTED" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-EOPTenantAttributedMessage", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-Network-Message-Id", "data_type": "string", "example_values": [ - "a417c578-c7ee-480d-a225-d48057e74df5:0" + "4b1ef179-4fe7-4248-7ec0-08d81367956e" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-EOPAttributedMessage", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-OriginalArrivalTime", "data_type": "string", "example_values": [ - "0" + "18 Jun 2020 09:11:28.2511 (UTC)" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-UserPrincipalName", + "data_type": "string", + "example_values": [ + "bs91VnpEPjrqCnvlIeymwO6ye5P9rggHggVNUPUbV/tC9uuFPVFOYg7e/Cd0MeGmSqT4AlLW0Nn4ZeEqNieSf/D1gp5iLz/YkwjXhYUSJnLRb/csQN4sRMMZsX3LUkKkwVpifaeJzoukLu8qSWn7og==" ] }, { @@ -2965,17 +3205,24 @@ ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-Microsoft-Antispam-Mailbox-Delivery", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-AuthMechanism", "data_type": "string", "example_values": [ - "wl:1;pcwl:1;ucf:0;jmr:0;auth:0;dest:I;ENG:(750128)(520011016)(520004050)(702028)(944506458)(944626604);" + "04" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-Google-DKIM-Signature", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-AuthSource", "data_type": "string", "example_values": [ - "v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:date:mime-version:from:to:subject; bh=tlTaRbacq4aWozhUPvcWg8i8flbpYQGZNs27nncn83I=; b=fPT47NIiheeY6GM0bxUOlsmnOgN4WuiOlalFvZqrAiFiOoYk6zrznvgIcAtiHZ4nxE naQAa+mZs5svqRjib3YI52OvR5U8MitIYaa0Rt3LyYSUO1s3iKTUs4nHyRnqPt1skNl7 2OUwsZPXo3ShJDw/uxZRu/cuN1iIfeuE02PrbR04p4D8+1XRslqt/Xqm/bOWKUauqZWe dH1E7meFY01hXxODreO4nWHIhsZgr49TpP/OqRyFcyKHHFFg2sPGXz+QNah6jP4YQUYd Tty2wzOX3nc/YS7TkVo3ORmbzh9o+UZaqH8wHbQlyTdklYxoMPvJwZTo72rTxZeqiJ9E J7PQ==" + "DM6NAM11FT055.eop-nam11.prod.protection.outlook.com" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-ExpirationInterval", + "data_type": "string", + "example_values": [ + "1:00:00:00.0000000" ] }, { @@ -2986,52 +3233,66 @@ ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.Date", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-ExpirationStartTime", "data_type": "string", "example_values": [ - "Thu, 18 Jun 2020 02:11:26 -0700" + "18 Jun 2020 09:11:28.2531 (UTC)" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-AuthSource", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-ExpirationStartTimeReason", "data_type": "string", "example_values": [ - "DM6NAM11FT055.eop-nam11.prod.protection.outlook.com" + "OriginalSubmit" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.Received", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-MessageDirectionality", "data_type": "string", "example_values": [ - "from localhost.localdomain (host-240.splunk.com. [204.107.141.240]) by smtp.gmail.com with UTF8SMTPSA id ng12sm1923252pjb.15.2020.06.18.02.11.26 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 18 Jun 2020 02:11:26 -0700 (PDT)" + "Incoming" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Transport-CrossTenantHeadersStamped", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-Network-Message-Id", "data_type": "string", "example_values": [ - "BN6PR18MB1492" + "4b1ef179-4fe7-4248-7ec0-08d81367956e" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-Received", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-SCL", "data_type": "string", "example_values": [ - "by 2002:aa7:84d9:: with SMTP id x25mr2807688pfn.300.1592471487394; Thu, 18 Jun 2020 02:11:27 -0700 (PDT)" + "-1" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-Microsoft-Antispam-Message-Info", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Processed-By-BccFoldering", "data_type": "string", "example_values": [ - "La+CSxAnpzVJOXq7njrFPhIbsh0khleSwldy+W8NYDRsoyyPruPIiId4Avama7JyfzrxoExzhLk5pDn2lGPAJIpdcguiDSsDQg5T+iBCJgFeaEJXjhstECMi842/JGawB9WsiGw9Q/PpvjO5H/2fNLlQZVZW3AAQVZSsX3az4iOsv1Ggj4aYZRMKHmPAtniWOEtQD7zAEWC0jIZf613lWy3vxHfb/3+pV9X8zqPqazbyGy5Q14PICSNkKnvIw8rmeqJV8eSHhvR51Lchib6OIN4xOpLWxkSkBTt5B95RUPnpgPvgp2yLo0Q+EYRIabLDQ0kMsv+24+RnFmr9vo2gRNuFusw8iEPsVEQyhfgIWtBtsBpyvyykxcfa6lIdzQhixZH3Tlkdh1kb15wFS3Ooz3CjaWbY8jcUot5l1p08Ypsj6r7CpIo3xE6jE0x/EeUkDK3Fu/Ol0pOsJ1N5W4iJLdjqSQM3l/t9QWlcPhD8s6D7D7JM5OUHCeFEPr7sSL+P/5zTgBaeUvwtZrlQSH2GHc+5gPW8rkwlwJLJftVEid0gO2PUOrzItzME5PXYAcdx++sF3XC1YMPLet/jMpX8T7/z7+hxFxNyifgmGJ+DkNOec7yGkkcLBz6iCaHx7OrRGwDHIcdAtV85wCk3NEDDiKyHivQpwp/gY55W+wkLe7aqSHmFzm1rUSslx+DWz8w2EgSjJxOmf0JkoNKbTFl3FObkocR0lUUQUnETuoAXUqvpWGD5B69W9XXUM8c43ozz2oBZseheSAtkLil3tMIr/CMCMILPX/LdoErNtkmiFXCPqaLFSSeyO61oCMl6Ezndtwp22nwMPUg5ofG0kdqFuTW122umhy9C6h5BcREaLhWclSyqDoZPB9RvkRlI2kTRwuwbuFW3iOMzmVwxLIQH9K5JkxdMvC3hvNpjVgz7Q2ZnEF3xSNqeoWVQvkaIe8rQLUc8s+HMRUmSERGdfSuQJAx47g8PDs9s3rS/ThUSzIaljJPbUgXEnFg/G6h3I/yXLj2Nj2OG50snoI5jJmE4+69YmNwasdDZuYpnuQeFgu11HtsLniDthJdjEJyYC1utZNt9hgA+6JlLnm7Dxb43cSIiW8ev+3X+b2kREj2k/m8fSz7YgtoCB8AkuiVXRaH3EUiq8XCExbbWeynKRgwCZ6bzvfSiT3+cg+QQKPHFc/cgot56ta6X80tjhFodpTQNTE6V6C9QFHJ3JCVhsSzVifJAc8crI5hAcPbKFEIjinENcfpF/8reo2Yr1xFElhoX" + "15.20.3109.017" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-Id", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Transport-CrossTenantHeadersStamped", "data_type": "string", "example_values": [ - "a417c578-c7ee-480d-a225-d48057e74df5" + "BN6PR18MB1492" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Transport-EndToEndLatency", + "data_type": "string", + "example_values": [ + "00:00:02.7417647" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Has-Attach", + "data_type": "string", + "example_values": [ + "yes" ] }, { @@ -3042,10 +3303,24 @@ ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-Network-Message-Id", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Oob-TLC-OOBClassifiers", "data_type": "string", "example_values": [ - "4b1ef179-4fe7-4248-7ec0-08d81367956e" + "OLM:1728;" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-PublicTrafficType", + "data_type": "string", + "example_values": [ + "Email" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-TNEF-Correlator", + "data_type": "string", + "example_values": [ + "" ] }, { @@ -3056,109 +3331,217 @@ ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-FromEntityHeader", + "data_path": "action_result.data.*.internetMessageHeaders.X-Microsoft-Antispam", "data_type": "string", "example_values": [ - "Internet" + "BCL:0;" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-Network-Message-Id", + "data_path": "action_result.data.*.internetMessageHeaders.X-Microsoft-Antispam-Mailbox-Delivery", "data_type": "string", "example_values": [ - "4b1ef179-4fe7-4248-7ec0-08d81367956e" + "wl:1;pcwl:1;ucf:0;jmr:0;auth:0;dest:I;ENG:(750128)(520011016)(520004050)(702028)(944506458)(944626604);" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-PublicTrafficType", + "data_path": "action_result.data.*.internetMessageHeaders.X-Microsoft-Antispam-Message-Info", "data_type": "string", "example_values": [ - "Email" + "La+CSxAnpzVJOXq7njrFPhIbsh0khleSwldy+W8NYDRsoyyPruPIiId4Avama7JyfzrxoExzhLk5pDn2lGPAJIpdcguiDSsDQg5T+iBCJgFeaEJXjhstECMi842/JGawB9WsiGw9Q/PpvjO5H/2fNLlQZVZW3AAQVZSsX3az4iOsv1Ggj4aYZRMKHmPAtniWOEtQD7zAEWC0jIZf613lWy3vxHfb/3+pV9X8zqPqazbyGy5Q14PICSNkKnvIw8rmeqJV8eSHhvR51Lchib6OIN4xOpLWxkSkBTt5B95RUPnpgPvgp2yLo0Q+EYRIabLDQ0kMsv+24+RnFmr9vo2gRNuFusw8iEPsVEQyhfgIWtBtsBpyvyykxcfa6lIdzQhixZH3Tlkdh1kb15wFS3Ooz3CjaWbY8jcUot5l1p08Ypsj6r7CpIo3xE6jE0x/EeUkDK3Fu/Ol0pOsJ1N5W4iJLdjqSQM3l/t9QWlcPhD8s6D7D7JM5OUHCeFEPr7sSL+P/5zTgBaeUvwtZrlQSH2GHc+5gPW8rkwlwJLJftVEid0gO2PUOrzItzME5PXYAcdx++sF3XC1YMPLet/jMpX8T7/z7+hxFxNyifgmGJ+DkNOec7yGkkcLBz6iCaHx7OrRGwDHIcdAtV85wCk3NEDDiKyHivQpwp/gY55W+wkLe7aqSHmFzm1rUSslx+DWz8w2EgSjJxOmf0JkoNKbTFl3FObkocR0lUUQUnETuoAXUqvpWGD5B69W9XXUM8c43ozz2oBZseheSAtkLil3tMIr/CMCMILPX/LdoErNtkmiFXCPqaLFSSeyO61oCMl6Ezndtwp22nwMPUg5ofG0kdqFuTW122umhy9C6h5BcREaLhWclSyqDoZPB9RvkRlI2kTRwuwbuFW3iOMzmVwxLIQH9K5JkxdMvC3hvNpjVgz7Q2ZnEF3xSNqeoWVQvkaIe8rQLUc8s+HMRUmSERGdfSuQJAx47g8PDs9s3rS/ThUSzIaljJPbUgXEnFg/G6h3I/yXLj2Nj2OG50snoI5jJmE4+69YmNwasdDZuYpnuQeFgu11HtsLniDthJdjEJyYC1utZNt9hgA+6JlLnm7Dxb43cSIiW8ev+3X+b2kREj2k/m8fSz7YgtoCB8AkuiVXRaH3EUiq8XCExbbWeynKRgwCZ6bzvfSiT3+cg+QQKPHFc/cgot56ta6X80tjhFodpTQNTE6V6C9QFHJ3JCVhsSzVifJAc8crI5hAcPbKFEIjinENcfpF/8reo2Yr1xFElhoX" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-OriginalArrivalTime", + "data_path": "action_result.data.*.internetMessageHeaders.X-Originating-IP", "data_type": "string", "example_values": [ - "18 Jun 2020 09:11:28.2511 (UTC)" + "[5.38.181.162]" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.MIME-Version", + "data_path": "action_result.data.*.internetMessageHeaders.X-Received", "data_type": "string", "example_values": [ - "1.0" + "by 2002:aa7:84d9:: with SMTP id x25mr2807688pfn.300.1592471487394; Thu, 18 Jun 2020 02:11:27 -0700 (PDT)" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-SCL", + "data_path": "action_result.data.*.internetMessageHeaders.subject", "data_type": "string", "example_values": [ - "-1" + "test html" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-Gm-Message-State", + "data_path": "action_result.data.*.internetMessageId", "data_type": "string", "example_values": [ - "AOAM533ynFERIhSIewEEkj4b8B1rPNOEeie1IxBdrd55treEMtBa1jkL\tcO5ee4Ff6p0FYedfFtVtHKiCglGTpFTOSw==" + "", + "<5eeb2fbe.1c69fb81.22b4b.676a@mx.google.com>" + ], + "contains": [ + "msgoffice365 internet message id" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-MessageDirectionality", + "data_path": "action_result.data.*.isDeliveryReceiptRequested", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.isDraft", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.isRead", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.isReadReceiptRequested", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.lastModifiedDateTime", "data_type": "string", "example_values": [ - "Incoming" + "2017-10-26T01:31:43Z", + "2020-06-18T09:11:32Z" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.DKIM-Signature", + "data_path": "action_result.data.*.parentFolderId", "data_type": "string", + "contains": [ + "msgoffice365 folder id" + ], "example_values": [ - "v=1; a=rsa-sha256; c=relaxed/relaxed; d=testdomain.com.20150623.gappssmtp.com; s=20150623; h=message-id:date:mime-version:from:to:subject; bh=tlTaRbacq4aWozhUPvcWg8i8flbpYQGZNs27nncn83I=; b=avAAeJ8jF08K4oIBhxTirRmyB+SXHwdU0zdxv7eqs/zWaWWcgmT0007KP560TTgo5u oD4nb6TvKxpRyWW4QwmkbuMIwHsMvehd2l1gispV3AawyGJjpmN7ErVYfLtIkz2Tap3V YxmluV+SqeyyxTU8pFAEZ7+2C2lOb1DO5TC7xCMv+dyzevSscJdbeN0dFkG+C93zCqkg w2fxubx2HDD7b/U6m2wXllYhH608wKJ/qYzyvQyqxYqNiQOtPRg2gw4sZ2UgN3+UQyVq 8ubO39ZuqakJpzEzYMw10d6E7SQhvHDJH7mFwhBlzhvOpb2gLJDN8n8dJaZo05BozQqq MsvA==" + "AQMkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQAuAAADyW3X5P7Hb0_MMHKonvdoWQEAQSl1b8BFiEmbqZql_JiUtwAAAgEMAAAA" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-Forefront-Antispam-Report", + "data_path": "action_result.data.*.receivedDateTime", "data_type": "string", "example_values": [ - "CIP:209.85.210.171;CTRY:US;LANG:en;SCL:-1;SRV:;IPV:NLI;SFV:SFE;H:mail-pf1-f171.google.com;PTR:mail-pf1-f171.google.com;CAT:NONE;SFTY:;SFS:;DIR:INB;SFP:;" + "2017-10-26T01:31:43Z", + "2020-06-18T09:11:31Z" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.Content-Type", + "data_path": "action_result.data.*.replyTo", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.sender.emailAddress.address", "data_type": "string", "example_values": [ - "multipart/related" + "test@testdomain.onmicrosoft.com" + ], + "contains": [ + "email" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-Google-Smtp-Source", + "data_path": "action_result.data.*.sender.emailAddress.name", "data_type": "string", "example_values": [ - "ABdhPJxrYC7raBubCCIOmauxmxryzS9KsihTN6XCRgaNp2rDrG71TVxryzYCtelFOZ2Xj1LzcYIiMA==" + "Test Name" + ], + "contains": [ + "email" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-ExpirationStartTimeReason", + "data_path": "action_result.data.*.sentDateTime", "data_type": "string", "example_values": [ - "OriginalSubmit" + "2017-10-26T01:31:35Z", + "2020-06-18T09:11:26Z" ] }, { - "data_path": "action_result.data.*.conversationIndex", + "data_path": "action_result.data.*.subject", "data_type": "string", "example_values": [ - "AQHWRVB0TS7xy6ZOSEeEl0ahrRHNfQ==" + "more attachments", + "test html" + ], + "contains": [ + "msgoffice365 subject" ] }, { - "data_path": "action_result.parameter.extract_headers", - "data_type": "boolean", + "data_path": "action_result.data.*.toRecipients.*.emailAddress.address", + "data_type": "string", "example_values": [ - true, - false + "Test@testdomain.onmicrosoft.com" + ], + "contains": [ + "email" + ] + }, + { + "data_path": "action_result.data.*.toRecipients.*.emailAddress.name", + "data_type": "string", + "example_values": [ + "Test Name" + ] + }, + { + "data_path": "action_result.data.*.webLink", + "data_type": "string", + "example_values": [ + "https://outlook.office365.com/owa/?ItemID=AQMkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQBGAAADyW3X5P7Hb0%2BMMHKonvdoWQcAQSl1b8BFiEmbqZql%2BJiUtwAAAgEMAAAAQSl1b8BFiEmbqZql%2BJiUtwABS2DpfAAAAA%3D%3D&exvsurl=1&viewmodel=ReadMessageItem" + ], + "contains": [ + "url" + ] + }, + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Successfully fetched email" + ] + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 ] } ], @@ -3227,10 +3610,81 @@ }, "output": [ { - "data_path": "action_result.status", + "data_path": "action_result.parameter.email_address", + "data_type": "string", + "example_values": [ + "user@onmicrosoft.com" + ], + "contains": [ + "email" + ] + }, + { + "data_path": "action_result.parameter.get_body", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.parameter.get_headers", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.parameter.get_sender", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.parameter.get_unique_body", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.parameter.id", + "data_type": "string", + "example_values": [ + "AQMkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQBGAAADyW3X5P7Hb0_MMHKonvdoWQcAQSl1b8BFiEmbqZql_JiUtwAAAgEMAAAAQSl1b8BFiEmbqZql_JiUtwADu9Tv8QAAAA==" + ], + "contains": [ + "msgoffice365 message id" + ] + }, + { + "data_path": "action_result.parameter.properties_list", + "data_type": "string", + "example_values": [ + "subject", + "subject,receivedDateTime" + ] + }, + { + "data_path": "action_result.data.*.@odata.context", + "data_type": "string", + "example_values": [ + "https://graph.microsoft.com/v1.0/$metadata#users('user%40.onmicrosoft.com')/messages(internetMessageHeaders,body,uniqueBody,sender,subject)/$entity", + "https://graph.microsoft.com/v1.0/$metadata#users('user%40.onmicrosoft.com')/messages(internetMessageHeaders,body,uniqueBody,sender,subject,receivedDateTime)/$entity" + ], + "contains": [ + "url" + ] + }, + { + "data_path": "action_result.data.*.@odata.etag", "data_type": "string", "example_values": [ - "success" + "W/\"CQAAABYAAABBKXVvwEWISZupmqX4mJS3AAO8DBJl\"" ] }, { @@ -3248,248 +3702,251 @@ ] }, { - "data_path": "action_result.data.*.sender.emailAddress.name", + "data_path": "action_result.data.*.id", "data_type": "string", "example_values": [ - "notifications@testdomain.com" - ], - "contains": [ - "email" + "AQMkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQBGAAADyW3X5P7Hb0_MMHKonvdoWQcAQSl1b8BFiEmbqZql_JiUtwAAAgEMAAAAQSl1b8BFiEmbqZql_JiUtwADu9Tv8QAAAA==" ] }, { - "data_path": "action_result.data.*.sender.emailAddress.address", + "data_path": "action_result.data.*.internetMessageHeaders.Accept-Language", "data_type": "string", "example_values": [ - "notifications@testdomain.com" - ], - "contains": [ - "email" + "en-US" ] }, { - "data_path": "action_result.data.*.@odata.context", + "data_path": "action_result.data.*.internetMessageHeaders.Authentication-Results", "data_type": "string", "example_values": [ - "https://graph.microsoft.com/v1.0/$metadata#users('user%40.onmicrosoft.com')/messages(internetMessageHeaders,body,uniqueBody,sender,subject)/$entity", - "https://graph.microsoft.com/v1.0/$metadata#users('user%40.onmicrosoft.com')/messages(internetMessageHeaders,body,uniqueBody,sender,subject,receivedDateTime)/$entity" - ], - "contains": [ - "url" + "spf=pass (sender IP is 209.85.210.171) smtp.mailfrom=testdomain.com; .onmicrosoft.com; dkim=pass (signature was verified) header.d=testdomain.com.20150623.gappssmtp.com;.onmicrosoft.com; dmarc=pass action=none header.from=testdomain.com;compauth=pass reason=100" ] }, { - "data_path": "action_result.data.*.uniqueBody.content", + "data_path": "action_result.data.*.internetMessageHeaders.Content-Language", "data_type": "string", "example_values": [ - "
\r\n
\r\n

HTML heading

\r\nHTML body.
\r\n
\r\n" + "en-US" ] }, { - "data_path": "action_result.data.*.uniqueBody.contentType", + "data_path": "action_result.data.*.internetMessageHeaders.Content-Transfer-Encoding", "data_type": "string", "example_values": [ - "html" + "binary" ] }, { - "data_path": "action_result.data.*.subject", + "data_path": "action_result.data.*.internetMessageHeaders.Content-Type", "data_type": "string", "example_values": [ - "test html" + "multipart/related" ] }, { - "data_path": "action_result.data.*.id", + "data_path": "action_result.data.*.internetMessageHeaders.DKIM-Signature", "data_type": "string", "example_values": [ - "AQMkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQBGAAADyW3X5P7Hb0_MMHKonvdoWQcAQSl1b8BFiEmbqZql_JiUtwAAAgEMAAAAQSl1b8BFiEmbqZql_JiUtwADu9Tv8QAAAA==" + "v=1; a=rsa-sha256; c=relaxed/relaxed; d=testdomain.com.20150623.gappssmtp.com; s=20150623; h=message-id:date:mime-version:from:to:subject; bh=tlTaRbacq4aWozhUPvcWg8i8flbpYQGZNs27nncn83I=; b=avAAeJ8jF08K4oIBhxTirRmyB+SXHwdU0zdxv7eqs/zWaWWcgmT0007KP560TTgo5u oD4nb6TvKxpRyWW4QwmkbuMIwHsMvehd2l1gispV3AawyGJjpmN7ErVYfLtIkz2Tap3V YxmluV+SqeyyxTU8pFAEZ7+2C2lOb1DO5TC7xCMv+dyzevSscJdbeN0dFkG+C93zCqkg w2fxubx2HDD7b/U6m2wXllYhH608wKJ/qYzyvQyqxYqNiQOtPRg2gw4sZ2UgN3+UQyVq 8ubO39ZuqakJpzEzYMw10d6E7SQhvHDJH7mFwhBlzhvOpb2gLJDN8n8dJaZo05BozQqq MsvA==" ] }, { - "data_path": "action_result.data.*.@odata.etag", + "data_path": "action_result.data.*.internetMessageHeaders.Date", "data_type": "string", "example_values": [ - "W/\"CQAAABYAAABBKXVvwEWISZupmqX4mJS3AAO8DBJl\"" + "Thu, 18 Jun 2020 02:11:26 -0700" ] }, { - "data_path": "action_result.message", + "data_path": "action_result.data.*.internetMessageHeaders.From", "data_type": "string", "example_values": [ - "Successfully fetched email" + "\"Test\" " ] }, { - "data_path": "action_result.parameter.properties_list", + "data_path": "action_result.data.*.internetMessageHeaders.In-Reply-To", "data_type": "string", "example_values": [ - "subject", - "subject,receivedDateTime" + "" ] }, { - "data_path": "action_result.parameter.get_unique_body", - "data_type": "boolean", + "data_path": "action_result.data.*.internetMessageHeaders.MIME-Version", + "data_type": "string", "example_values": [ - true, - false + "1.0" ] }, { - "data_path": "action_result.parameter.get_headers", - "data_type": "boolean", + "data_path": "action_result.data.*.internetMessageHeaders.Message-ID", + "data_type": "string", "example_values": [ - true, - false + "<5eeb2fbe.1c69fb81.22b4b.676a@mx.google.com>" ] }, { - "data_path": "action_result.parameter.get_body", - "data_type": "boolean", + "data_path": "action_result.data.*.internetMessageHeaders.Received", + "data_type": "string", "example_values": [ - true, - false + "from localhost.localdomain (host-240.splunk.com. [204.107.141.240]) by smtp.gmail.com with UTF8SMTPSA id ng12sm1923252pjb.15.2020.06.18.02.11.26 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 18 Jun 2020 02:11:26 -0700 (PDT)" ] }, { - "data_path": "action_result.parameter.get_sender", - "data_type": "boolean", + "data_path": "action_result.data.*.internetMessageHeaders.Received-SPF", + "data_type": "string", "example_values": [ - true, - false + "Pass (protection.outlook.com: domain of testdomain.com designates 209.85.210.171 as permitted sender) receiver=protection.outlook.com; client-ip=209.85.210.171; helo=mail-pf1-f171.google.com;" ] }, { - "data_path": "action_result.parameter.email_address", + "data_path": "action_result.data.*.internetMessageHeaders.References", "data_type": "string", "example_values": [ - "user@onmicrosoft.com" + "" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.Return-Path", + "data_type": "string", + "example_values": [ + "notifications@testdomain.com" ], "contains": [ "email" ] }, { - "data_path": "action_result.parameter.id", + "data_path": "action_result.data.*.internetMessageHeaders.Subject", "data_type": "string", "example_values": [ - "AQMkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQBGAAADyW3X5P7Hb0_MMHKonvdoWQcAQSl1b8BFiEmbqZql_JiUtwAAAgEMAAAAQSl1b8BFiEmbqZql_JiUtwADu9Tv8QAAAA==" - ], - "contains": [ - "msgoffice365 message id" + "Fw: Email having different attachments" ] }, { - "data_path": "action_result.summary", - "data_type": "string" + "data_path": "action_result.data.*.internetMessageHeaders.Thread-Index", + "data_type": "string", + "example_values": [ + "AQHWZLqyXR4k4Sc6skyFCMPITcMsbKpGS7Bm" + ] }, { - "data_path": "summary.total_objects", - "data_type": "numeric", + "data_path": "action_result.data.*.internetMessageHeaders.Thread-Topic", + "data_type": "string", "example_values": [ - 1 + "Email having different attachments" ] }, { - "data_path": "summary.total_objects_successful", - "data_type": "numeric", + "data_path": "action_result.data.*.internetMessageHeaders.To", + "data_type": "string", "example_values": [ - 1 + "\"Test\" " ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.Return-Path", + "data_path": "action_result.data.*.internetMessageHeaders.X-EOPAttributedMessage", "data_type": "string", "example_values": [ - "notifications@testdomain.com" - ], - "contains": [ - "email" + "0" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-ExpirationInterval", + "data_path": "action_result.data.*.internetMessageHeaders.X-EOPTenantAttributedMessage", "data_type": "string", "example_values": [ - "1:00:00:00.0000000" + "a417c578-c7ee-480d-a225-d48057e74df5:0" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Transport-EndToEndLatency", + "data_path": "action_result.data.*.internetMessageHeaders.X-Forefront-Antispam-Report", "data_type": "string", "example_values": [ - "00:00:02.7417647" + "CIP:209.85.210.171;CTRY:US;LANG:en;SCL:-1;SRV:;IPV:NLI;SFV:SFE;H:mail-pf1-f171.google.com;PTR:mail-pf1-f171.google.com;CAT:NONE;SFTY:;SFS:;DIR:INB;SFP:;" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.Received-SPF", + "data_path": "action_result.data.*.internetMessageHeaders.X-Gm-Message-State", "data_type": "string", "example_values": [ - "Pass (protection.outlook.com: domain of testdomain.com designates 209.85.210.171 as permitted sender) receiver=protection.outlook.com; client-ip=209.85.210.171; helo=mail-pf1-f171.google.com;" + "AOAM533ynFERIhSIewEEkj4b8B1rPNOEeie1IxBdrd55treEMtBa1jkL\tcO5ee4Ff6p0FYedfFtVtHKiCglGTpFTOSw==" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.Authentication-Results", + "data_path": "action_result.data.*.internetMessageHeaders.X-Google-DKIM-Signature", "data_type": "string", "example_values": [ - "spf=pass (sender IP is 209.85.210.171) smtp.mailfrom=testdomain.com; .onmicrosoft.com; dkim=pass (signature was verified) header.d=testdomain.com.20150623.gappssmtp.com;.onmicrosoft.com; dmarc=pass action=none header.from=testdomain.com;compauth=pass reason=100" + "v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:date:mime-version:from:to:subject; bh=tlTaRbacq4aWozhUPvcWg8i8flbpYQGZNs27nncn83I=; b=fPT47NIiheeY6GM0bxUOlsmnOgN4WuiOlalFvZqrAiFiOoYk6zrznvgIcAtiHZ4nxE naQAa+mZs5svqRjib3YI52OvR5U8MitIYaa0Rt3LyYSUO1s3iKTUs4nHyRnqPt1skNl7 2OUwsZPXo3ShJDw/uxZRu/cuN1iIfeuE02PrbR04p4D8+1XRslqt/Xqm/bOWKUauqZWe dH1E7meFY01hXxODreO4nWHIhsZgr49TpP/OqRyFcyKHHFFg2sPGXz+QNah6jP4YQUYd Tty2wzOX3nc/YS7TkVo3ORmbzh9o+UZaqH8wHbQlyTdklYxoMPvJwZTo72rTxZeqiJ9E J7PQ==" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-Microsoft-Antispam", + "data_path": "action_result.data.*.internetMessageHeaders.X-Google-Smtp-Source", "data_type": "string", "example_values": [ - "BCL:0;" + "ABdhPJxrYC7raBubCCIOmauxmxryzS9KsihTN6XCRgaNp2rDrG71TVxryzYCtelFOZ2Xj1LzcYIiMA==" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Processed-By-BccFoldering", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-AntiSpam-MessageData", "data_type": "string", "example_values": [ - "15.20.3109.017" + "VSM9HTzub/OH3NCwKXEQqkkzjnhdw5kXsgd9WM0SRgZ0qRdPg5D9/o3LA7lf8ziXc5k0mm9M5mHvFoYePXNXs/MGhGdBGxa/qUQ+FVHA2mDgfPkamJCEZxz//OX/uruTDo+zF4p9D1dQJpnIpx1M75OhuvrHX/BxWWzyAh78DXfF214YHdyFBCYepwl56CS7+fSGQL/r3p+OvWIBnIkISC+HJljSro2k47pPPAkspMhoUkb+zklyENFjez+JcEHYlih2FiNeUO8kb9b7qvlm3zPK98HLspzDh4BojpQ6Ff330iy7nfIK726tCMByxjOdnEQSB9Ua2sbE5gxSeeWL8MB5DHcQSSsXg+sR8w4gXrXLO3meE0lNQKRoAv2b1U0Q+yM0QBqeQWlymZG21bKeuH4gtAFQvfXNjoCtIbBQK1n7ZnL7fI21FJZRcMcKEneus6gLYUqD4PdLEq9FEGbfgiLmVYeUAL2A0Q/gectvL1OVudtHVR5gFMJKt65F1OtS04CPulfLLFSl1F4AzpjjtBSyQcK9R7bOsjoHxQXPMd9fMCzMSIq5f551pO0klKqWY7l11Un2Noj6CA7EtXiD1bTv8JmYQEKR+0HTZagNd+79GeTvKjxTvt9MkyO8k3aqWyNqT331ITnVICtksN1TVMCp8GVeDudNMr2PLSW0alOduR5unuEgTWrqHoaTGOovQx0PVjudNlpZ80ANK9hqaC/ZhLLOtNpJ3fZnjs06PzrPLGhE/IeccY1n8sYDvGm1QA9TN6JaaGPl1Pj6ecy16k0XuF/PKGHTL0M4LCpxSS6T87oFFH1zHkKtmbJp3aAI4bt3ihbQmwFb29JyMgL7ZOy+zrIwXGILh1KQGWQQv1uXXnAuqQy29HeFXs6D2hDHxHlBk5ZQ+vgRtsvRvGnq58vJ3CapjntfL3pOINUj1avLyAZxjasBWMTwaZs9JQ4ZIMekzkIk05lh9XfDSeULk2yKaH8YSCC6ENUHxSWa6pPHJfOdp9kXwOtlp09/VTTAikKy862k9ybN4bRWZB45B9Pv5scna8IX3rthIXUih8c=" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.Message-ID", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-AuthAs", "data_type": "string", "example_values": [ - "<5eeb2fbe.1c69fb81.22b4b.676a@mx.google.com>" + "Internal" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.subject", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-AuthSource", "data_type": "string", "example_values": [ - "test html" + "SJ0QA11MB4941.namprd11.prod.outlook.com" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-ExpirationStartTime", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-FromEntityHeader", "data_type": "string", "example_values": [ - "18 Jun 2020 09:11:28.2531 (UTC)" + "Internet" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Oob-TLC-OOBClassifiers", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-Id", "data_type": "string", "example_values": [ - "OLM:1728;" + "a417c578-c7ee-480d-a225-d48057e74df5" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-EOPTenantAttributedMessage", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-MailboxType", "data_type": "string", "example_values": [ - "a417c578-c7ee-480d-a225-d48057e74df5:0" + "HOSTED" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-EOPAttributedMessage", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-Network-Message-Id", "data_type": "string", "example_values": [ - "0" + "4b1ef179-4fe7-4248-7ec0-08d81367956e" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-OriginalArrivalTime", + "data_type": "string", + "example_values": [ + "18 Jun 2020 09:11:28.2511 (UTC)" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-UserPrincipalName", + "data_type": "string", + "example_values": [ + "bs91VnpEPjrqCnvlIeymwO6ye4Q8rggHggVNUPUbV/tC9uuFPVFOYg7e/Cd0MeGmSqT4AlLW0Nn4ZeEqNieSf/D1gp5iLz/YkwjXhYUSJnLRb/csQN4sRMMZsX3LUkKkwVpifaeJzoukLu8qSWn7og==" ] }, { @@ -3500,17 +3957,24 @@ ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-Microsoft-Antispam-Mailbox-Delivery", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-AuthMechanism", "data_type": "string", "example_values": [ - "wl:1;pcwl:1;ucf:0;jmr:0;auth:0;dest:I;ENG:(750128)(520011016)(520004050)(702028)(944506458)(944626604);" + "04" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-Google-DKIM-Signature", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-AuthSource", "data_type": "string", "example_values": [ - "v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:date:mime-version:from:to:subject; bh=tlTaRbacq4aWozhUPvcWg8i8flbpYQGZNs27nncn83I=; b=fPT47NIiheeY6GM0bxUOlsmnOgN4WuiOlalFvZqrAiFiOoYk6zrznvgIcAtiHZ4nxE naQAa+mZs5svqRjib3YI52OvR5U8MitIYaa0Rt3LyYSUO1s3iKTUs4nHyRnqPt1skNl7 2OUwsZPXo3ShJDw/uxZRu/cuN1iIfeuE02PrbR04p4D8+1XRslqt/Xqm/bOWKUauqZWe dH1E7meFY01hXxODreO4nWHIhsZgr49TpP/OqRyFcyKHHFFg2sPGXz+QNah6jP4YQUYd Tty2wzOX3nc/YS7TkVo3ORmbzh9o+UZaqH8wHbQlyTdklYxoMPvJwZTo72rTxZeqiJ9E J7PQ==" + "DM6NAM11FT055.eop-nam11.prod.protection.outlook.com" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-ExpirationInterval", + "data_type": "string", + "example_values": [ + "1:00:00:00.0000000" ] }, { @@ -3521,52 +3985,66 @@ ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.Date", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-ExpirationStartTime", "data_type": "string", "example_values": [ - "Thu, 18 Jun 2020 02:11:26 -0700" + "18 Jun 2020 09:11:28.2531 (UTC)" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-AuthSource", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-ExpirationStartTimeReason", "data_type": "string", "example_values": [ - "DM6NAM11FT055.eop-nam11.prod.protection.outlook.com" + "OriginalSubmit" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.Received", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-MessageDirectionality", "data_type": "string", "example_values": [ - "from localhost.localdomain (host-240.splunk.com. [204.107.141.240]) by smtp.gmail.com with UTF8SMTPSA id ng12sm1923252pjb.15.2020.06.18.02.11.26 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 18 Jun 2020 02:11:26 -0700 (PDT)" + "Incoming" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Transport-CrossTenantHeadersStamped", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-Network-Message-Id", "data_type": "string", "example_values": [ - "BN6PR18MB1492" + "4b1ef179-4fe7-4248-7ec0-08d81367956e" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-Received", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-SCL", "data_type": "string", "example_values": [ - "by 2002:aa7:84d9:: with SMTP id x25mr2807688pfn.300.1592471487394; Thu, 18 Jun 2020 02:11:27 -0700 (PDT)" + "-1" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-Microsoft-Antispam-Message-Info", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Processed-By-BccFoldering", "data_type": "string", "example_values": [ - "La+CSxAnpzVJOXq7njrFPhIbsh0khleSwldy+W8NYDRsoyyPruPIiId4Avama7JyfzrxoExzhLk5pDn2lGPAJIpdcguiDSsDQg5T+iBCJgFeaEJXjhstECMi842/JGawB9WsiGw9Q/PpvjO5H/2fNLlQZVZW3AAQVZSsX3az4iOsv1Ggj4aYZRMKHmPAtniWOEtQD7zAEWC0jIZf613lWy3vxHfb/3+pV9X8zqPqazbyGy5Q14PICSNkKnvIw8rmeqJV8eSHhvR51Lchib6OIN4xOpLWxkSkBTt5B95RUPnpgPvgp2yLo0Q+EYRIabLDQ0kMsv+24+RnFmr9vo2gRNuFusw8iEPsVEQyhfgIWtBtsBpyvyykxcfa6lIdzQhixZH3Tlkdh1kb15wFS3Ooz3CjaWbY8jcUot5l1p08Ypsj6r7CpIo3xE6jE0x/EeUkDK3Fu/Ol0pOsJ1N5W4iJLdjqSQM3l/t9QWlcPhD8s6D7D7JM5OUHCeFEPr7sSL+P/5zTgBaeUvwtZrlQSH2GHc+5gPW8rkwlwJLJftVEid0gO2PUOrzItzME5PXYAcdx++sF3XC1YMPLet/jMpX8T7/z7+hxFxNyifgmGJ+DkNOec7yGkkcLBz6iCaHx7OrRGwDHIcdAtV85wCk3NEDDiKyHivQpwp/gY55W+wkLe7aqSHmFzm1rUSslx+DWz8w2EgSjJxOmf0JkoNKbTFl3FObkocR0lUUQUnETuoAXUqvpWGD5B69W9XXUM8c43ozz2oBZseheSAtkLil3tMIr/CMCMILPX/LdoErNtkmiFXCPqaLFSSeyO61oCMl6Ezndtwp22nwMPUg5ofG0kdqFuTW122umhy9C6h5BcREaLhWclSyqDoZPB9RvkRlI2kTRwuwbuFW3iOMzmVwxLIQH9K5JkxdMvC3hvNpjVgz7Q2ZnEF3xSNqeoWVQvkaIe8rQLUc8s+HMRUmSERGdfSuQJAx47g8PDs9s3rS/ThUSzIaljJPbUgXEnFg/G6h3I/yXLj2Nj2OG50snoI5jJmE4+69YmNwasdDZuYpnuQeFgu11HtsLniDthJdjEJyYC1utZNt9hgA+6JlLnm7Dxb43cSIiW8ev+3X+b2kREj2k/m8fSz7YgtoCB8AkuiVXRaH3EUiq8XCExbbWeynKRgwCZ6bzvfSiT3+cg+QQKPHFc/cgot56ta6X80tjhFodpTQNTE6V6C9QFHJ3JCVhsSzVifJAc8crI5hAcPbKFEIjinENcfpF/8reo2Yr1xFElhoX" + "15.20.3109.017" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-Id", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Transport-CrossTenantHeadersStamped", "data_type": "string", "example_values": [ - "a417c578-c7ee-480d-a225-d48057e74df5" + "BN6PR18MB1492" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Transport-EndToEndLatency", + "data_type": "string", + "example_values": [ + "00:00:02.7417647" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Has-Attach", + "data_type": "string", + "example_values": [ + "yes" ] }, { @@ -3577,10 +4055,24 @@ ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-Network-Message-Id", + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Oob-TLC-OOBClassifiers", "data_type": "string", "example_values": [ - "4b1ef179-4fe7-4248-7ec0-08d81367956e" + "OLM:1728;" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-PublicTrafficType", + "data_type": "string", + "example_values": [ + "Email" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.X-MS-TNEF-Correlator", + "data_type": "string", + "example_values": [ + "" ] }, { @@ -3591,101 +4083,126 @@ ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-FromEntityHeader", + "data_path": "action_result.data.*.internetMessageHeaders.X-Microsoft-Antispam", "data_type": "string", "example_values": [ - "Internet" + "BCL:0;" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-Network-Message-Id", + "data_path": "action_result.data.*.internetMessageHeaders.X-Microsoft-Antispam-Mailbox-Delivery", "data_type": "string", "example_values": [ - "4b1ef179-4fe7-4248-7ec0-08d81367956e" + "wl:1;pcwl:1;ucf:0;jmr:0;auth:0;dest:I;ENG:(750128)(520011016)(520004050)(702028)(944506458)(944626604);" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-PublicTrafficType", + "data_path": "action_result.data.*.internetMessageHeaders.X-Microsoft-Antispam-Message-Info", "data_type": "string", "example_values": [ - "Email" + "La+CSxAnpzVJOXq7njrFPhIbsh0khleSwldy+W8NYDRsoyyPruPIiId4Avama7JyfzrxoExzhLk5pDn2lGPAJIpdcguiDSsDQg5T+iBCJgFeaEJXjhstECMi842/JGawB9WsiGw9Q/PpvjO5H/2fNLlQZVZW3AAQVZSsX3az4iOsv1Ggj4aYZRMKHmPAtniWOEtQD7zAEWC0jIZf613lWy3vxHfb/3+pV9X8zqPqazbyGy5Q14PICSNkKnvIw8rmeqJV8eSHhvR51Lchib6OIN4xOpLWxkSkBTt5B95RUPnpgPvgp2yLo0Q+EYRIabLDQ0kMsv+24+RnFmr9vo2gRNuFusw8iEPsVEQyhfgIWtBtsBpyvyykxcfa6lIdzQhixZH3Tlkdh1kb15wFS3Ooz3CjaWbY8jcUot5l1p08Ypsj6r7CpIo3xE6jE0x/EeUkDK3Fu/Ol0pOsJ1N5W4iJLdjqSQM3l/t9QWlcPhD8s6D7D7JM5OUHCeFEPr7sSL+P/5zTgBaeUvwtZrlQSH2GHc+5gPW8rkwlwJLJftVEid0gO2PUOrzItzME5PXYAcdx++sF3XC1YMPLet/jMpX8T7/z7+hxFxNyifgmGJ+DkNOec7yGkkcLBz6iCaHx7OrRGwDHIcdAtV85wCk3NEDDiKyHivQpwp/gY55W+wkLe7aqSHmFzm1rUSslx+DWz8w2EgSjJxOmf0JkoNKbTFl3FObkocR0lUUQUnETuoAXUqvpWGD5B69W9XXUM8c43ozz2oBZseheSAtkLil3tMIr/CMCMILPX/LdoErNtkmiFXCPqaLFSSeyO61oCMl6Ezndtwp22nwMPUg5ofG0kdqFuTW122umhy9C6h5BcREaLhWclSyqDoZPB9RvkRlI2kTRwuwbuFW3iOMzmVwxLIQH9K5JkxdMvC3hvNpjVgz7Q2ZnEF3xSNqeoWVQvkaIe8rQLUc8s+HMRUmSERGdfSuQJAx47g8PDs9s3rS/ThUSzIaljJPbUgXEnFg/G6h3I/yXLj2Nj2OG50snoI5jJmE4+69YmNwasdDZuYpnuQeFgu11HtsLniDthJdjEJyYC1utZNt9hgA+6JlLnm7Dxb43cSIiW8ev+3X+b2kREj2k/m8fSz7YgtoCB8AkuiVXRaH3EUiq8XCExbbWeynKRgwCZ6bzvfSiT3+cg+QQKPHFc/cgot56ta6X80tjhFodpTQNTE6V6C9QFHJ3JCVhsSzVifJAc8crI5hAcPbKFEIjinENcfpF/8reo2Yr1xFElhoX" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-CrossTenant-OriginalArrivalTime", + "data_path": "action_result.data.*.internetMessageHeaders.X-Originating-IP", "data_type": "string", "example_values": [ - "18 Jun 2020 09:11:28.2511 (UTC)" + "[2.39.180.162]" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.X-Received", + "data_type": "string", + "example_values": [ + "by 2002:aa7:84d9:: with SMTP id x25mr2807688pfn.300.1592471487394; Thu, 18 Jun 2020 02:11:27 -0700 (PDT)" + ] + }, + { + "data_path": "action_result.data.*.internetMessageHeaders.subject", + "data_type": "string", + "example_values": [ + "test html" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.MIME-Version", + "data_path": "action_result.data.*.receivedDateTime", "data_type": "string", "example_values": [ - "1.0" + "2020-06-18T09:11:31Z" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-SCL", + "data_path": "action_result.data.*.sender.emailAddress.address", "data_type": "string", "example_values": [ - "-1" + "notifications@testdomain.com" + ], + "contains": [ + "email" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-Gm-Message-State", + "data_path": "action_result.data.*.sender.emailAddress.name", "data_type": "string", "example_values": [ - "AOAM533ynFERIhSIewEEkj4b8B1rPNOEeie1IxBdrd55treEMtBa1jkL\tcO5ee4Ff6p0FYedfFtVtHKiCglGTpFTOSw==" + "notifications@testdomain.com" + ], + "contains": [ + "email" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-MessageDirectionality", + "data_path": "action_result.data.*.subject", "data_type": "string", "example_values": [ - "Incoming" + "test html" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.DKIM-Signature", + "data_path": "action_result.data.*.uniqueBody.content", "data_type": "string", "example_values": [ - "v=1; a=rsa-sha256; c=relaxed/relaxed; d=testdomain.com.20150623.gappssmtp.com; s=20150623; h=message-id:date:mime-version:from:to:subject; bh=tlTaRbacq4aWozhUPvcWg8i8flbpYQGZNs27nncn83I=; b=avAAeJ8jF08K4oIBhxTirRmyB+SXHwdU0zdxv7eqs/zWaWWcgmT0007KP560TTgo5u oD4nb6TvKxpRyWW4QwmkbuMIwHsMvehd2l1gispV3AawyGJjpmN7ErVYfLtIkz2Tap3V YxmluV+SqeyyxTU8pFAEZ7+2C2lOb1DO5TC7xCMv+dyzevSscJdbeN0dFkG+C93zCqkg w2fxubx2HDD7b/U6m2wXllYhH608wKJ/qYzyvQyqxYqNiQOtPRg2gw4sZ2UgN3+UQyVq 8ubO39ZuqakJpzEzYMw10d6E7SQhvHDJH7mFwhBlzhvOpb2gLJDN8n8dJaZo05BozQqq MsvA==" + "
\r\n
\r\n

HTML heading

\r\nHTML body.
\r\n
\r\n" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-Forefront-Antispam-Report", + "data_path": "action_result.data.*.uniqueBody.contentType", "data_type": "string", "example_values": [ - "CIP:209.85.210.171;CTRY:US;LANG:en;SCL:-1;SRV:;IPV:NLI;SFV:SFE;H:mail-pf1-f171.google.com;PTR:mail-pf1-f171.google.com;CAT:NONE;SFTY:;SFS:;DIR:INB;SFP:;" + "html" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.Content-Type", + "data_path": "action_result.status", "data_type": "string", "example_values": [ - "multipart/related" + "success", + "failed" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-Google-Smtp-Source", + "data_path": "action_result.message", "data_type": "string", "example_values": [ - "ABdhPJxrYC7raBubCCIOmauxmxryzS9KsihTN6XCRgaNp2rDrG71TVxryzYCtelFOZ2Xj1LzcYIiMA==" + "Successfully fetched email" ] }, { - "data_path": "action_result.data.*.internetMessageHeaders.X-MS-Exchange-Organization-ExpirationStartTimeReason", - "data_type": "string", + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", "example_values": [ - "OriginalSubmit" + 1 ] }, { - "data_path": "action_result.data.*.receivedDateTime", - "data_type": "string", + "data_path": "summary.total_objects_successful", + "data_type": "numeric", "example_values": [ - "2020-06-18T09:11:31Z" + 1 ] } ], @@ -3715,7 +4232,6 @@ "folder": { "description": "Destination folder; this must be either a (case-sensitive) well-known name or the internal o365 folder ID", "data_type": "string", - "required": false, "primary": true, "contains": [ "msgoffice365 mail folder", @@ -3739,7 +4255,6 @@ "subject": { "description": "Substring to search in subject", "data_type": "string", - "required": false, "primary": true, "contains": [ "msgoffice365 subject" @@ -3749,13 +4264,11 @@ "body": { "description": "Substring to search in body", "data_type": "string", - "order": 5, - "required": false + "order": 5 }, "sender": { "description": "Sender email address to match", "data_type": "string", - "required": false, "primary": true, "contains": [ "email" @@ -3765,19 +4278,16 @@ "limit": { "description": "Maximum emails to return", "data_type": "numeric", - "required": false, "order": 7 }, "query": { "description": "MS Graph query string", "data_type": "string", - "required": false, "order": 8 }, "internet_message_id": { "description": "Internet message ID", "data_type": "string", - "required": false, "primary": true, "contains": [ "msgoffice365 internet message id" @@ -3786,14 +4296,6 @@ } }, "output": [ - { - "data_path": "action_result.status", - "data_type": "string", - "example_values": [ - "success", - "failed" - ] - }, { "data_path": "action_result.parameter.body", "data_type": "string", @@ -3856,6 +4358,14 @@ "$orderby=propertyName desc" ] }, + { + "data_path": "action_result.parameter.search_well_known_folders", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, { "data_path": "action_result.parameter.sender", "data_type": "string", @@ -3883,6 +4393,31 @@ "W/\"CQAAABYAAABBKXVvwEWISZupmqX4mJS3AAFOpxtE\"" ] }, + { + "data_path": "action_result.data.*.@odata.type", + "data_type": "string", + "example_values": [ + "#microsoft.graph.eventMessageRequests" + ] + }, + { + "data_path": "action_result.data.*.allowNewTimeProposals", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.bccRecipients.*.emailAddress.address", + "data_type": "string", + "example_values": [ + "test3.test@gmail.com" + ] + }, + { + "data_path": "action_result.data.*.bccRecipients.*.emailAddress.name", + "data_type": "string", + "example_values": [ + "test3.test@gmail.com" + ] + }, { "data_path": "action_result.data.*.bccRecipients.email", "data_type": "string", @@ -3925,6 +4460,20 @@ "data_path": "action_result.data.*.categories", "data_type": "string" }, + { + "data_path": "action_result.data.*.ccRecipients.*.emailAddress.address", + "data_type": "string", + "example_values": [ + "test3.test@gmail.com" + ] + }, + { + "data_path": "action_result.data.*.ccRecipients.*.emailAddress.name", + "data_type": "string", + "example_values": [ + "test3.test@gmail.com" + ] + }, { "data_path": "action_result.data.*.ccRecipients.email", "data_type": "string", @@ -3956,6 +4505,13 @@ "AAQkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQAQAGqbDRkVLxZMtetM-dKqAPo=" ] }, + { + "data_path": "action_result.data.*.conversationIndex", + "data_type": "string", + "example_values": [ + "AQHXHRZ01/QE6F/kQkdaSwXyspIYQagZQ==" + ] + }, { "data_path": "action_result.data.*.createdDateTime", "data_type": "string", @@ -3963,6 +4519,20 @@ "2017-10-30T22:32:42Z" ] }, + { + "data_path": "action_result.data.*.endDateTime.dateTime", + "data_type": "string", + "example_values": [ + "2020-08-15T12:30:00.0000000" + ] + }, + { + "data_path": "action_result.data.*.endDateTime.timeZone", + "data_type": "string", + "example_values": [ + "UTC" + ] + }, { "data_path": "action_result.data.*.flag.flagStatus", "data_type": "string", @@ -4031,11 +4601,7 @@ ] }, { - "data_path": "action_result.data.*.isDeliveryReceiptRequested", - "data_type": "string" - }, - { - "data_path": "action_result.data.*.isDraft", + "data_path": "action_result.data.*.isAllDay", "data_type": "boolean", "example_values": [ true, @@ -4043,7 +4609,7 @@ ] }, { - "data_path": "action_result.data.*.isRead", + "data_path": "action_result.data.*.isDelegated", "data_type": "boolean", "example_values": [ true, @@ -4051,7 +4617,7 @@ ] }, { - "data_path": "action_result.data.*.isReadReceiptRequested", + "data_path": "action_result.data.*.isDeliveryReceiptRequested", "data_type": "boolean", "example_values": [ true, @@ -4059,124 +4625,31 @@ ] }, { - "data_path": "action_result.data.*.lastModifiedDateTime", - "data_type": "string", - "example_values": [ - "2017-10-30T22:32:53Z" - ] - }, - { - "data_path": "action_result.data.*.parentFolderId", - "data_type": "string", - "contains": [ - "msgoffice365 folder id" - ], - "example_values": [ - "AAMkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQAuAAAAAADJbdfk-sdvT4wwcqie92hZAQBBKXVvwEWISZupmqX4mJS3AACEV3zJAAA=" - ] - }, - { - "data_path": "action_result.data.*.receivedDateTime", - "data_type": "string", - "example_values": [ - "2017-10-30T22:32:42Z" - ] - }, - { - "data_path": "action_result.data.*.replyTo", - "data_type": "string" - }, - { - "data_path": "action_result.data.*.sender.emailAddress.address", - "data_type": "string", - "example_values": [ - "test@testdomain.onmicrosoft.com" - ], - "contains": [ - "email" - ] - }, - { - "data_path": "action_result.data.*.sender.emailAddress.name", - "data_type": "string", - "example_values": [ - "Test Name" - ] - }, - { - "data_path": "action_result.data.*.sentDateTime", - "data_type": "string", - "example_values": [ - "2017-10-30T22:32:37Z" - ] - }, - { - "data_path": "action_result.data.*.subject", - "data_type": "string", - "example_values": [ - "Just wanted to say hello" - ], - "contains": [ - "msgoffice365 subject" - ] - }, - { - "data_path": "action_result.data.*.toRecipients.*.emailAddress.address", - "data_type": "string", - "example_values": [ - "Test@testdomain.onmicrosoft.com" - ], - "contains": [ - "email" - ] - }, - { - "data_path": "action_result.data.*.toRecipients.*.emailAddress.name", - "data_type": "string", - "example_values": [ - "Test Name" - ] - }, - { - "data_path": "action_result.data.*.webLink", - "data_type": "string", - "example_values": [ - "https://outlook.office365.com/owa/?ItemID=AAMkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQBGAAAAAADJbdfk%2FsdvT4wwcqie92hZBwBBKXVvwEWISZupmqX4mJS3AACEV3zJAABBKXVvwEWISZupmqX4mJS3AAFOZwS4AAA%3D&exvsurl=1&viewmodel=ReadMessageItem" - ], - "contains": [ - "url" - ] - }, - { - "data_path": "action_result.summary.emails_matched", - "data_type": "numeric", - "example_values": [ - 1 - ] - }, - { - "data_path": "action_result.message", - "data_type": "string", + "data_path": "action_result.data.*.isDraft", + "data_type": "boolean", "example_values": [ - "Emails matched: 1" + true, + false ] }, { - "data_path": "summary.total_objects", - "data_type": "numeric", + "data_path": "action_result.data.*.isOutOfDate", + "data_type": "boolean", "example_values": [ - 1 + true, + false ] }, - { - "data_path": "summary.total_objects_successful", - "data_type": "numeric", + { + "data_path": "action_result.data.*.isRead", + "data_type": "boolean", "example_values": [ - 1 + true, + false ] }, { - "data_path": "action_result.parameter.search_well_known_folders", + "data_path": "action_result.data.*.isReadReceiptRequested", "data_type": "boolean", "example_values": [ true, @@ -4184,67 +4657,81 @@ ] }, { - "data_path": "action_result.data.*.conversationIndex", + "data_path": "action_result.data.*.lastModifiedDateTime", "data_type": "string", "example_values": [ - "AQHXHRZ01/QE6F/kQkdaSwXyspIYQagZQ==" + "2017-10-30T22:32:53Z" ] }, { - "data_path": "action_result.data.*.ccRecipients.*.emailAddress.name", + "data_path": "action_result.data.*.meetingMessageType", "data_type": "string", "example_values": [ - "test3.test@gmail.com" + "meetingRequest" ] }, { - "data_path": "action_result.data.*.ccRecipients.*.emailAddress.address", + "data_path": "action_result.data.*.meetingRequestType", "data_type": "string", "example_values": [ - "test3.test@gmail.com" + "informationalUpdate" ] }, { - "data_path": "action_result.data.*.replyTo.*.emailAddress.name", + "data_path": "action_result.data.*.parentFolderId", "data_type": "string", + "contains": [ + "msgoffice365 folder id" + ], "example_values": [ - "hellohi@okta.com" + "AAMkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQAuAAAAAADJbdfk-sdvT4wwcqie92hZAQBBKXVvwEWISZupmqX4mJS3AACEV3zJAAA=" ] }, { - "data_path": "action_result.data.*.replyTo.*.emailAddress.address", + "data_path": "action_result.data.*.previousEndDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.previousEndDateTime.dateTime", "data_type": "string", "example_values": [ - "hellohi@okta.com" + "2020-08-15T12:30:00.0000000" ] }, { - "data_path": "action_result.data.*.bccRecipients.*.emailAddress.name", + "data_path": "action_result.data.*.previousEndDateTime.timeZone", "data_type": "string", "example_values": [ - "test3.test@gmail.com" + "UTC" ] }, { - "data_path": "action_result.data.*.bccRecipients.*.emailAddress.address", + "data_path": "action_result.data.*.previousLocation", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.previousStartDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.previousStartDateTime.dateTime", "data_type": "string", "example_values": [ - "test3.test@gmail.com" + "2020-08-15T12:00:00.0000000" ] }, { - "data_path": "action_result.data.*.type", + "data_path": "action_result.data.*.previousStartDateTime.timeZone", "data_type": "string", "example_values": [ - "singleInstance" + "UTC" ] }, { - "data_path": "action_result.data.*.isAllDay", - "data_type": "boolean", + "data_path": "action_result.data.*.receivedDateTime", + "data_type": "string", "example_values": [ - true, - false + "2017-10-30T22:32:42Z" ] }, { @@ -4252,28 +4739,25 @@ "data_type": "string" }, { - "data_path": "action_result.data.*.@odata.type", - "data_type": "string", - "example_values": [ - "#microsoft.graph.eventMessageRequests" - ] + "data_path": "action_result.data.*.replyTo", + "data_type": "string" }, { - "data_path": "action_result.data.*.endDateTime.dateTime", + "data_path": "action_result.data.*.replyTo.*.emailAddress.address", "data_type": "string", "example_values": [ - "2020-08-15T12:30:00.0000000" + "hellohi@okta.com" ] }, { - "data_path": "action_result.data.*.endDateTime.timeZone", + "data_path": "action_result.data.*.replyTo.*.emailAddress.name", "data_type": "string", "example_values": [ - "UTC" + "hellohi@okta.com" ] }, { - "data_path": "action_result.data.*.isDelegated", + "data_path": "action_result.data.*.responseRequested", "data_type": "boolean", "example_values": [ true, @@ -4281,11 +4765,27 @@ ] }, { - "data_path": "action_result.data.*.isOutOfDate", - "data_type": "boolean", + "data_path": "action_result.data.*.sender.emailAddress.address", + "data_type": "string", "example_values": [ - true, - false + "test@testdomain.onmicrosoft.com" + ], + "contains": [ + "email" + ] + }, + { + "data_path": "action_result.data.*.sender.emailAddress.name", + "data_type": "string", + "example_values": [ + "Test Name" + ] + }, + { + "data_path": "action_result.data.*.sentDateTime", + "data_type": "string", + "example_values": [ + "2017-10-30T22:32:37Z" ] }, { @@ -4303,70 +4803,84 @@ ] }, { - "data_path": "action_result.data.*.previousLocation", - "data_type": "string" - }, - { - "data_path": "action_result.data.*.responseRequested", - "data_type": "boolean", + "data_path": "action_result.data.*.subject", + "data_type": "string", "example_values": [ - true, - false + "Just wanted to say hello" + ], + "contains": [ + "msgoffice365 subject" ] }, { - "data_path": "action_result.data.*.meetingMessageType", + "data_path": "action_result.data.*.toRecipients.*.emailAddress.address", "data_type": "string", "example_values": [ - "meetingRequest" + "Test@testdomain.onmicrosoft.com" + ], + "contains": [ + "email" ] }, { - "data_path": "action_result.data.*.meetingRequestType", + "data_path": "action_result.data.*.toRecipients.*.emailAddress.name", "data_type": "string", "example_values": [ - "informationalUpdate" + "Test Name" ] }, { - "data_path": "action_result.data.*.previousEndDateTime.dateTime", + "data_path": "action_result.data.*.type", "data_type": "string", "example_values": [ - "2020-08-15T12:30:00.0000000" + "singleInstance" ] }, { - "data_path": "action_result.data.*.previousEndDateTime.timeZone", + "data_path": "action_result.data.*.webLink", "data_type": "string", "example_values": [ - "UTC" + "https://outlook.office365.com/owa/?ItemID=AAMkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQBGAAAAAADJbdfk%2FsdvT4wwcqie92hZBwBBKXVvwEWISZupmqX4mJS3AACEV3zJAABBKXVvwEWISZupmqX4mJS3AAFOZwS4AAA%3D&exvsurl=1&viewmodel=ReadMessageItem" + ], + "contains": [ + "url" ] }, { - "data_path": "action_result.data.*.allowNewTimeProposals", - "data_type": "string" + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] }, { - "data_path": "action_result.data.*.previousStartDateTime.dateTime", + "data_path": "action_result.message", "data_type": "string", "example_values": [ - "2020-08-15T12:00:00.0000000" + "Emails matched: 1" ] }, { - "data_path": "action_result.data.*.previousStartDateTime.timeZone", - "data_type": "string", + "data_path": "action_result.summary.emails_matched", + "data_type": "numeric", "example_values": [ - "UTC" + 1 ] }, { - "data_path": "action_result.data.*.previousEndDateTime", - "data_type": "string" + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] }, { - "data_path": "action_result.data.*.previousStartDateTime", - "data_type": "string" + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] } ], "render": { @@ -4410,19 +4924,10 @@ "all_subdirs": { "description": "Make any missing directories in the path if they don't exist instead of failing", "data_type": "boolean", - "required": false, "order": 2 } }, "output": [ - { - "data_path": "action_result.status", - "data_type": "string", - "example_values": [ - "success", - "failed" - ] - }, { "data_path": "action_result.parameter.all_subdirs", "data_type": "boolean", @@ -4452,6 +4957,16 @@ "Archive" ] }, + { + "data_path": "action_result.data.*.@odata.context", + "data_type": "string", + "example_values": [ + "https://graph.microsoft.com/v1.0/$metadata#users('abc%def.onmicrosoft.com')/mailFolders/$entity" + ], + "contains": [ + "url" + ] + }, { "data_path": "action_result.data.*.@odata.etag", "data_type": "string", @@ -4484,6 +4999,14 @@ "AAMkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQBGAAAAAADJbdfk-sdvT4wwcqie92hZBwBBKXVvwEWISZupmqX4mJS3AACEV3zJAABBKXVvwEWISZupmqX4mJS3AAFOZwS4AAA=" ] }, + { + "data_path": "action_result.data.*.isHidden", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, { "data_path": "action_result.data.*.parentFolderId", "data_type": "string", @@ -4496,6 +5019,13 @@ "AAMkADU3NDk3MzJlLTY3MDQtNDE2Ny1iZDk1LTc4YjEwYzhmZDc5YQAuAAAAAADJbdfk-sdvT4wwcqie92hZAQBBKXVvwEWISZupmqX4mJS3AACEV3zJAAA=" ] }, + { + "data_path": "action_result.data.*.sizeInBytes", + "data_type": "numeric", + "example_values": [ + 0 + ] + }, { "data_path": "action_result.data.*.totalItemCount", "data_type": "numeric", @@ -4511,8 +5041,12 @@ ] }, { - "data_path": "action_result.summary", - "data_type": "string" + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] }, { "data_path": "action_result.message", @@ -4521,6 +5055,20 @@ "Emails matched: 1" ] }, + { + "data_path": "action_result.summary.folder", + "data_type": "string", + "example_values": [ + "AQMkAMExNGJmOWQyLTlhMjctNGRiOS1iODU0LTA1ZWE3ZmQ3NDU3MQAuAAADeDDJKaEf4EihMWU6SZgKbAEA07XhOkNngkCkqoNfY_k-jQAFA6de0wAAAA==" + ] + }, + { + "data_path": "action_result.summary.folders created", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, { "data_path": "summary.total_objects", "data_type": "numeric", @@ -4575,14 +5123,6 @@ } }, "output": [ - { - "data_path": "action_result.status", - "data_type": "string", - "example_values": [ - "success", - "failed" - ] - }, { "data_path": "action_result.parameter.email_address", "data_type": "string", @@ -4640,17 +5180,11 @@ ] }, { - "data_path": "action_result.summary", - "data_type": "string" - }, - { - "data_path": "action_result.summary.folder_id", + "data_path": "action_result.status", "data_type": "string", "example_values": [ - "AAMkAGFmNTRhODA4LWIxMjQtNDJjYy05NDM2LWQ5MzY1MGFhMTkzYwAuAAAAAADRlY7ewL4xToKRDciQog5UAQBvUzMoUJx2S4nbgxzZWx2PAAEApxCTAAA=" - ], - "contains": [ - "msgoffice365 folder id" + "success", + "failed" ] }, { @@ -4660,6 +5194,16 @@ "Folder id: AAMkAGFmNTRhODA4LWIxMjQtNDJjYy05NDM2LWQ5MzY1MGFhMTkzYwAuAAAAAADRlY7ewL4xToKRDciQog5UAQBvUzMoUJx2S4nbgxzZWx2PAAEApxCTAAA=" ] }, + { + "data_path": "action_result.summary.folder_id", + "data_type": "string", + "example_values": [ + "AAMkAGFmNTRhODA4LWIxMjQtNDJjYy05NDM2LWQ5MzY1MGFhMTkzYwAuAAAAAADRlY7ewL4xToKRDciQog5UAQBvUzMoUJx2S4nbgxzZWx2PAAEApxCTAAA=" + ], + "contains": [ + "msgoffice365 folder id" + ] + }, { "data_path": "summary.total_objects", "data_type": "numeric", @@ -4692,27 +5236,31 @@ "parameters": { "start_time": { "data_type": "numeric", - "description": "Parameter Ignored in this app" + "description": "Parameter Ignored in this app", + "order": 0 }, "end_time": { "data_type": "numeric", - "description": "Parameter Ignored in this app" + "description": "Parameter Ignored in this app", + "order": 1 }, "container_id": { "data_type": "string", - "description": "Parameter Ignored in this app" + "description": "Parameter Ignored in this app", + "order": 2 }, "container_count": { "data_type": "numeric", "description": "Maximum number of emails to ingest", "required": true, - "value": 100 + "value": 100, + "order": 3 }, "artifact_count": { "data_type": "numeric", - "description": "Maximum number of artifact to ingest", - "required": true, - "value": 1000 + "description": "Parameter Ignored in this app", + "value": 1000, + "order": 4 } }, "output": [], @@ -4723,7 +5271,7 @@ "wheel": [ { "module": "Django", - "input_file": "wheels/py3/Django-3.2.12-py3-none-any.whl" + "input_file": "wheels/py3/Django-3.2.13-py3-none-any.whl" }, { "module": "asgiref", @@ -4751,7 +5299,7 @@ }, { "module": "pytz", - "input_file": "wheels/shared/pytz-2021.3-py2.py3-none-any.whl" + "input_file": "wheels/shared/pytz-2022.1-py2.py3-none-any.whl" }, { "module": "requests", @@ -4759,7 +5307,7 @@ }, { "module": "soupsieve", - "input_file": "wheels/py3/soupsieve-2.3.1-py3-none-any.whl" + "input_file": "wheels/py3/soupsieve-2.3.2-py3-none-any.whl" }, { "module": "sqlparse", @@ -4767,11 +5315,11 @@ }, { "module": "typing_extensions", - "input_file": "wheels/py3/typing_extensions-4.0.1-py3-none-any.whl" + "input_file": "wheels/py3/typing_extensions-4.1.1-py3-none-any.whl" }, { "module": "urllib3", - "input_file": "wheels/shared/urllib3-1.26.8-py2.py3-none-any.whl" + "input_file": "wheels/shared/urllib3-1.26.9-py2.py3-none-any.whl" } ] }, @@ -4779,7 +5327,7 @@ "wheel": [ { "module": "Django", - "input_file": "wheels/py3/Django-3.2.12-py3-none-any.whl" + "input_file": "wheels/py3/Django-3.2.13-py3-none-any.whl" }, { "module": "asgiref", @@ -4807,7 +5355,7 @@ }, { "module": "pytz", - "input_file": "wheels/shared/pytz-2021.3-py2.py3-none-any.whl" + "input_file": "wheels/shared/pytz-2022.1-py2.py3-none-any.whl" }, { "module": "requests", @@ -4815,7 +5363,7 @@ }, { "module": "soupsieve", - "input_file": "wheels/py3/soupsieve-2.3.1-py3-none-any.whl" + "input_file": "wheels/py3/soupsieve-2.3.2-py3-none-any.whl" }, { "module": "sqlparse", @@ -4823,8 +5371,8 @@ }, { "module": "urllib3", - "input_file": "wheels/shared/urllib3-1.26.8-py2.py3-none-any.whl" + "input_file": "wheels/shared/urllib3-1.26.9-py2.py3-none-any.whl" } ] } -} \ No newline at end of file +} diff --git a/office365_connector.py b/office365_connector.py index ad50bce..af8c13e 100644 --- a/office365_connector.py +++ b/office365_connector.py @@ -23,12 +23,13 @@ import sys import time import uuid -from datetime import datetime, timedelta +from datetime import datetime import phantom.app as phantom import requests from bs4 import BeautifulSoup, UnicodeDammit from django.http import HttpResponse +from phantom import vault from phantom.action_result import ActionResult from phantom.base_connector import BaseConnector from phantom.vault import Vault @@ -80,15 +81,8 @@ def _load_app_state(asset_id, app_connector=None): state = json.loads(state_file_data) except Exception as e: if app_connector: - # Fetching the Python major version - try: - python_version = int(sys.version_info[0]) - except: - app_connector.debug_print("Error occurred while getting the Phantom server's Python major version.") - return state - - error_code, error_msg = _get_error_message_from_exception(python_version, e, app_connector) - app_connector.debug_print('In _load_app_state: Error Code: {0}. Error Message: {1}'.format(error_code, error_msg)) + error_msg = _get_error_message_from_exception(e) + app_connector.debug_print('In _load_app_state: {0}'.format(error_msg)) if app_connector: app_connector.debug_print('Loaded state: ', state) @@ -127,68 +121,67 @@ def _save_app_state(state, asset_id, app_connector): with open(real_state_file_path, 'w+') as state_file_obj: state_file_obj.write(json.dumps(state)) except Exception as e: - # Fetching the Python major version - try: - python_version = int(sys.version_info[0]) - except: - if app_connector: - app_connector.debug_print("Error occurred while getting the Phantom server's Python major version.") - return phantom.APP_ERROR - - error_code, error_msg = _get_error_message_from_exception(python_version, e, app_connector) + error_msg = _get_error_message_from_exception(e) if app_connector: - app_connector.debug_print('Unable to save state file: Error Code: {0}. Error Message: {1}'.format(error_code, error_msg)) - print('Unable to save state file: Error Code: {0}. Error Message: {1}'.format(error_code, error_msg)) + app_connector.debug_print('Unable to save state file: {0}'.format(error_msg)) + print('Unable to save state file: {0}'.format(error_msg)) return phantom.APP_ERROR return phantom.APP_SUCCESS -def _handle_py_ver_compat_for_input_str(python_version, input_str, app_connector=None): - """ - This method returns the encoded|original string based on the Python version. - :param input_str: Input string to be processed - :return: input_str (Processed input string based on following logic 'input_str - Python 3; encoded input_str - Python 2') +def _get_error_message_from_exception(e): """ - try: - if input_str and python_version < 3: - input_str = UnicodeDammit(input_str).unicode_markup.encode('utf-8') - except: - if app_connector: - app_connector.debug_print("Error occurred while handling python 2to3 compatibility for the input string") - - return input_str - - -def _get_error_message_from_exception(python_version, e, app_connector=None): - """ This function is used to get appropriate error message from the exception. + Get appropriate error message from the exception. :param e: Exception object :return: error message """ - error_msg = "Unknown error occurred. Please check the asset configuration and|or action parameters." + error_code = None + error_msg = ERR_MSG_UNAVAILABLE + try: - if e.args: + if hasattr(e, "args"): if len(e.args) > 1: error_code = e.args[0] error_msg = e.args[1] elif len(e.args) == 1: - error_code = "Error code unavailable" error_msg = e.args[0] - else: - error_code = "Error code unavailable" - error_msg = "Unknown error occurred. Please check the asset configuration and|or action parameters." - except: - error_code = "Error code unavailable" - error_msg = "Unknown error occurred. Please check the asset configuration and|or action parameters." + except Exception: + pass - try: - error_msg = _handle_py_ver_compat_for_input_str(python_version, error_msg, app_connector) - except TypeError: - error_msg = "Error occurred while handling python 2to3 compatibility for the input string" - except: - error_msg = "Unknown error occurred. Please check the asset configuration and|or action parameters." + if not error_code: + error_text = "Error Message: {}".format(error_msg) + else: + error_text = "Error Code: {}. Error Message: {}".format(error_code, error_msg) - return error_code, error_msg + return error_text + + +def _validate_integer(action_result, parameter, key, allow_zero=False): + """ + Validate an integer. + + :param action_result: Action result or BaseConnector object + :param parameter: input parameter + :param key: input parameter message key + :allow_zero: whether zero should be considered as valid value or not + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS, integer value of the parameter or None in case of failure + """ + if parameter is not None: + try: + if not float(parameter).is_integer(): + return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_VALID_INT_MSG.format(param=key)), None + + parameter = int(parameter) + except Exception: + return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_VALID_INT_MSG.format(param=key)), None + + if parameter < 0: + return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_NON_NEG_INT_MSG.format(param=key)), None + if not allow_zero and parameter == 0: + return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_NON_NEG_NON_ZERO_INT_MSG.format(param=key)), None + + return phantom.APP_SUCCESS, parameter def _handle_oauth_result(request, path_parts): @@ -299,16 +292,11 @@ def handle_request(request, path_parts): gid = grp.getgrnam("phantom").gr_gid os.chown(auth_status_file_path, uid, gid) os.chmod(auth_status_file_path, "0664") - except: + except Exception: pass return ret_val - """ - if call_type == 'refresh_token': - return _handle_oauth_refresh_token(request, path_parts) - """ - return HttpResponse('error: Invalid endpoint', content_type="text/plain", status=404) @@ -345,8 +333,9 @@ def __init__(self): self._access_token = None self._refresh_token = None self._REPLACE_CONST = "C53CEA8298BD401BA695F247633D0542" # pragma: allowlist secret + self._duplicate_count = 0 - def _process_empty_reponse(self, response, action_result): + def _process_empty_response(self, response, action_result): if response.status_code == 200: return RetVal(phantom.APP_SUCCESS, {}) @@ -367,16 +356,9 @@ def _process_html_response(self, response, action_result): split_lines = error_text.split('\n') split_lines = [x.strip() for x in split_lines if x.strip()] error_text = '\n'.join(split_lines) - except: + except Exception: error_text = "Cannot parse error details" - try: - error_text = _handle_py_ver_compat_for_input_str(self._python_version, error_text, self) - except TypeError: - error_text = "Error occurred while handling python 2to3 compatibility for the error string" - except: - error_text = "Unknown error occurred. Please check the asset configuration and|or action parameters." - message = "Status Code: {0}. Data from server:\n{1}\n".format(status_code, error_text) @@ -390,9 +372,8 @@ def _process_json_response(self, r, action_result): try: resp_json = r.json() except Exception as e: - error_code, error_msg = _get_error_message_from_exception(self._python_version, e, self) - error_txt = "Error Code: {0}. Error Message: {1}".format(error_code, error_msg) - return RetVal(action_result.set_status(phantom.APP_ERROR, "Unable to parse JSON response. {0}".format(error_txt)), None) + error_msg = _get_error_message_from_exception(e) + return RetVal(action_result.set_status(phantom.APP_ERROR, "Unable to parse JSON response. {0}".format(error_msg)), None) # Please specify the status codes here if 200 <= r.status_code < 399: @@ -420,41 +401,20 @@ def _process_json_response(self, r, action_result): error_text = '\n'.join(split_lines) if len(error_text) > 500: error_text = 'Error while connecting to a server (Please check input parameters or asset configuration parameters)' - except: + except Exception: error_text = "Cannot parse error details" - try: - error_text = _handle_py_ver_compat_for_input_str(self._python_version, error_text, self) - except TypeError: - error_text = "Error occurred while handling python 2to3 compatibility for the error message" - except: - error_text = "Unknown error occurred while parsing the error message" - if error_code: error_text = "{}. {}".format(error_code, error_text) if error_desc: - try: - error_desc = _handle_py_ver_compat_for_input_str(self._python_version, error_desc, self) - except TypeError: - error_desc = "Error occurred while handling python 2to3 compatibility for the error_description" - except: - error_desc = "Unknown error occurred while parsing the error_description" - error_text = "{}. {}".format(error_desc, error_text) if not error_text: error_text = r.text.replace('{', '{{').replace('}', '}}') - except: + except Exception: error_text = r.text.replace('{', '{{').replace('}', '}}') - try: - error_text = _handle_py_ver_compat_for_input_str(self._python_version, error_text, self) - except TypeError: - error_text = "Error occurred while handling python 2to3 compatibility for the error string" - except: - error_text = "Unknown error occurred. Please check the asset configuration and|or action parameters." - # You should process the error returned in the json message = "Error from server. Status Code: {0} Data from server: {1}".format( r.status_code, error_text) @@ -491,7 +451,7 @@ def _process_response(self, r, action_result): # it's not content-type that is to be parsed, handle an empty response if not r.text: - return self._process_empty_reponse(r, action_result) + return self._process_empty_response(r, action_result) # everything else is actually an error at this point message = "Can't process response from server. Status Code: {0} Data from server: {1}".format( @@ -516,9 +476,8 @@ def _make_rest_call(self, action_result, url, verify=True, headers={}, params=No verify=verify, params=params) except Exception as e: - error_code, error_msg = _get_error_message_from_exception(self._python_version, e, self) - return RetVal(action_result.set_status(phantom.APP_ERROR, "Error connecting to server. Error Code: {0}. Error Message: {1}".format( - error_code, error_msg)), resp_json) + error_msg = _get_error_message_from_exception(e) + return RetVal(action_result.set_status(phantom.APP_ERROR, "Error connecting to server. {0}".format(error_msg)), resp_json) return self._process_response(r, action_result) @@ -540,6 +499,34 @@ def _get_asset_name(self, action_result): return (phantom.APP_SUCCESS, asset_name) + def _update_container(self, action_result, container_id, container): + """ + Update container. + + :param action_result: Action result or BaseConnector object + :param container_id: container ID + :param container: container's payload to update + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS with status message + """ + rest_endpoint = PHANTOM_CONTAINER_INFO_URL.format(url=self.get_phantom_base_url(), container_id=container_id) + + try: + data = json.dumps(container) + except Exception as e: + error_msg = _get_error_message_from_exception(e) + message = ( + "json.dumps failed while updating the container: {}. " + "Possibly a value in the container dictionary is not encoded properly. " + "Exception: {}" + ).format(container_id, error_msg) + return action_result.set_status(phantom.APP_ERROR, message) + + ret_val, _ = self._make_rest_call(action_result, rest_endpoint, False, data=data, method="post") + if phantom.is_fail(ret_val): + return action_result.get_status() + + return phantom.APP_SUCCESS + def _get_phantom_base_url(self, action_result): ret_val, resp_json = self._make_rest_call(action_result, PHANTOM_SYS_INFO_URL.format(url=self.get_phantom_base_url()), False) @@ -606,7 +593,11 @@ def _make_rest_call_helper(self, action_result, endpoint, verify=True, headers=N if msg and 'token is invalid' in msg or ('Access token has expired' in msg) or ('ExpiredAuthenticationToken' in msg) or ('AuthenticationFailed' in msg): + + self.debug_print("Token is invalid/expired. Hence, generating a new token.") ret_val = self._get_token(action_result) + if phantom.is_fail(ret_val): + return action_result.get_status(), None headers.update({ 'Authorization': 'Bearer {0}'.format(self._access_token)}) @@ -619,38 +610,50 @@ def _make_rest_call_helper(self, action_result, endpoint, verify=True, headers=N def _handle_attachment(self, attachment, container_id, artifact_json=None): - try: - - if hasattr(Vault, "create_attachment"): - vault_ret = Vault.create_attachment(base64.b64decode(attachment.pop('contentBytes')), container_id, file_name=attachment['name']) + vault_id = None - else: - if hasattr(Vault, 'get_vault_tmp_dir'): - temp_dir = Vault.get_vault_tmp_dir() + try: + if 'contentBytes' in attachment: # Check whether the attachment contains the data + if hasattr(Vault, "create_attachment"): + vault_ret = Vault.create_attachment( + base64.b64decode(attachment.pop('contentBytes')), + container_id, + file_name=attachment['name'] + ) + if not vault_ret.get('succeeded'): + self.debug_print("Error saving file to vault: ", vault_ret.get('message', "Could not save file to vault")) + return phantom.APP_ERROR + vault_id = vault_ret[phantom.APP_JSON_HASH] else: - temp_dir = '/opt/phantom/vault/tmp' - - temp_dir = temp_dir + '/{}'.format(uuid.uuid4()) - os.makedirs(temp_dir) - file_path = os.path.join(temp_dir, attachment['name']) - - with open(file_path, 'w') as f: - f.write(base64.b64decode(attachment.pop('contentBytes'))) - - vault_ret = Vault.add_attachment(file_path, container_id, file_name=attachment['name']) - + if hasattr(Vault, 'get_vault_tmp_dir'): + temp_dir = Vault.get_vault_tmp_dir() + else: + temp_dir = '/opt/phantom/vault/tmp' + + temp_dir = temp_dir + '/{}'.format(uuid.uuid4()) + os.makedirs(temp_dir) + file_path = os.path.join(temp_dir, attachment['name']) + + with open(file_path, 'w') as f: + f.write(base64.b64decode(attachment.pop('contentBytes'))) + + success, message, vault_id = vault.vault_add( + container=container_id, + file_location=file_path, + file_name=attachment['name'] + ) + if not success: + self.debug_print("Error adding file to vault: {}".format(message)) + return phantom.APP_ERROR + else: + self.debug_print("No content found in the attachment. Hence, skipping the vault file creation.") except Exception as e: - error_code, error_msg = _get_error_message_from_exception(self._python_version, e, self) - error_txt = "Error Code: {0}. Error Message: {1}".format(error_code, error_msg) - self.debug_print("Error saving file to vault: {0}".format(error_txt)) - return phantom.APP_ERROR - - if not vault_ret.get('succeeded'): - self.debug_print("Error saving file to vault: ", vault_ret.get('message', "Could not save file to vault")) + error_msg = _get_error_message_from_exception(e) + self.debug_print("Error saving file to vault: {0}".format(error_msg)) return phantom.APP_ERROR if artifact_json is None: - attachment['vaultId'] = vault_ret[phantom.APP_JSON_HASH] + attachment['vaultId'] = vault_id return phantom.APP_SUCCESS artifact_json['name'] = 'Vault Artifact' @@ -664,35 +667,67 @@ def _handle_attachment(self, attachment, container_id, artifact_json=None): artifact_cef['lastModified'] = attachment['lastModifiedDateTime'] artifact_cef['filename'] = attachment['name'] artifact_cef['mimeType'] = attachment['contentType'] - artifact_cef['vault_id'] = vault_ret[phantom.APP_JSON_HASH] + if vault_id: + artifact_cef['vault_id'] = vault_id artifact_json['cef'] = artifact_cef return phantom.APP_SUCCESS - def _create_email_artifacts(self, container_id, email): + def _create_reference_attachment_artifact(self, container_id, attachment, artifact_json): + """ + Create reference attachment artifact. + + :param container_id: container ID + :param attachment: attachment dict + :param artifact_json: artifact dict to add the data + :return: phantom.APP_SUCCESS + """ + artifact_json['name'] = 'Reference Attachment Artifact' + artifact_json['container_id'] = container_id + artifact_json['source_data_identifier'] = attachment['id'] + + artifact_cef = {} + + artifact_cef['size'] = attachment.get('size') + artifact_cef['lastModified'] = attachment.get('lastModifiedDateTime') + artifact_cef['filename'] = attachment.get('name') + artifact_cef['mimeType'] = attachment.get('contentType') + + artifact_json['cef'] = artifact_cef + + return phantom.APP_SUCCESS + def _create_email_artifacts(self, container_id, email, artifact_id=None): + """ + Create email artifacts. + + :param container_id: container ID + :param email: email content + :param artifact_id: artifact ID + :return: extracted artifacts list + """ artifacts = [] email_artifact = {} - artifacts.append(email_artifact) email_artifact['label'] = 'email' email_artifact['name'] = 'Email Artifact' email_artifact['container_id'] = container_id - email_artifact['cef_types'] = {'id': ['email id']} - email_artifact['source_data_identifier'] = email['id'] + + if email.get('id'): + artifact_id = email['id'] + + # Set email ID contains + self._process_email._set_email_id_contains(email['id']) + email_artifact['cef_types'] = {'messageId': self._process_email._email_id_contains} + + email_artifact['source_data_identifier'] = artifact_id cef = {} email_artifact['cef'] = cef - try: - email_items = email.iteritems() - except: - email_items = email.items() - - for k, v in email_items: + for k, v in email.items(): if v is not None: - # self.save_progress("Key: {}\r\nValue: {}".format(k, v)) if k == 'from': from_obj = v.get('emailAddress', {}) cef[k] = from_obj @@ -703,9 +738,36 @@ def _create_email_artifacts(self, container_id, email): recipients = v if len(recipients): cef['toEmail'] = recipients[0].get('emailAddress', {}).get('address', '') + elif k == 'id': + cef['messageId'] = v + elif k == 'internetMessageHeaders': + cef['internetMessageHeaders'] = {} + if isinstance(v, list): + for header in v: + key_name = header.get('name') + key_value = header.get('value') + if key_name and key_value: + cef['internetMessageHeaders'][key_name] = key_value else: cef[k] = v + if cef.get('body', {}).get('content') and (cef.get('body', {}).get('contentType') == 'html'): + html_body = cef['body']['content'] + + try: + soup = BeautifulSoup(html_body, "html.parser") + # Remove the script, style, footer, title and navigation part from the HTML message + for element in soup(["script", "style", "footer", "title", "nav"]): + element.extract() + body_text = soup.get_text(separator=' ') + split_lines = body_text.split('\n') + split_lines = [x.strip() for x in split_lines if x.strip()] + body_text = '\n'.join(split_lines) + if body_text: + cef['bodyText'] = body_text + except Exception: + self.debug_print("Cannot parse email body text details") + body = email['body']['content'] ips = [] @@ -718,7 +780,7 @@ def _create_email_artifacts(self, container_id, email): ip_artifact['label'] = 'artifact' ip_artifact['cef'] = ip ip_artifact['container_id'] = container_id - ip_artifact['source_data_identifier'] = email['id'] + ip_artifact['source_data_identifier'] = artifact_id urls = [] domains = [] @@ -731,7 +793,7 @@ def _create_email_artifacts(self, container_id, email): url_artifact['label'] = 'artifact' url_artifact['cef'] = url url_artifact['container_id'] = container_id - url_artifact['source_data_identifier'] = email['id'] + url_artifact['source_data_identifier'] = artifact_id for domain in domains: domain_artifact = {} @@ -740,10 +802,168 @@ def _create_email_artifacts(self, container_id, email): domain_artifact['label'] = 'artifact' domain_artifact['cef'] = domain domain_artifact['container_id'] = container_id - domain_artifact['source_data_identifier'] = email['id'] + domain_artifact['source_data_identifier'] = artifact_id + + hashes = [] + self._process_email._extract_hashes(body, hashes) + + for hash in hashes: + hash_artifact = {} + artifacts.append(hash_artifact) + hash_artifact['name'] = 'Hash Artifact' + hash_artifact['label'] = 'artifact' + hash_artifact['cef'] = hash + hash_artifact['container_id'] = container_id + hash_artifact['source_data_identifier'] = artifact_id + + artifacts.append(email_artifact) return artifacts + def _extract_attachments(self, config, attach_endpoint, artifacts, action_result, attachments, container_id, first_time=False): + """ + Extract attachments. + + :param config: config dict + :param attach_endpoint: attachment endpoint + :param artifacts: artifacts list to append the attachment artifacts + :param action_result: Action result or BaseConnector object + :param attachments: attachments list to process + :param container_id: container ID + :param first_time: boolean flag to specify if we want to expand the item attachment + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS with status message + """ + for attachment in attachments: + + if attachment.get('@odata.type') == '#microsoft.graph.itemAttachment': + + # We need to expand the item attachment only once + if first_time: + sub_email_endpoint = attach_endpoint + '/{0}?$expand=microsoft.graph.itemattachment/item'.format(attachment['id']) + ret_val, sub_email_resp = self._make_rest_call_helper(action_result, sub_email_endpoint) + if phantom.is_fail(ret_val): + return action_result.get_status() + + sub_email = sub_email_resp.get('item', {}) + else: + sub_email = attachment.get('item', {}) + + if sub_email.get('@odata.type') != '#microsoft.graph.message': + continue + + item_attachments = sub_email.pop('attachments', []) + if sub_email: + sub_artifacts = self._create_email_artifacts(container_id, sub_email, attachment['id']) + artifacts += sub_artifacts + + if item_attachments: + ret_val = self._extract_attachments(config, attach_endpoint, artifacts, action_result, item_attachments, container_id) + if phantom.is_fail(ret_val): + return action_result.get_status() + + elif attachment.get('@odata.type') == "#microsoft.graph.referenceAttachment": + + attach_artifact = {} + artifacts.append(attach_artifact) + self._create_reference_attachment_artifact(container_id, attachment, attach_artifact) + + elif attachment.get('name', '').endswith('.eml'): + if 'contentBytes' in attachment: + try: + rfc822_email = base64.b64decode(attachment['contentBytes']) + rfc822_email = UnicodeDammit(rfc822_email).unicode_markup + except Exception as e: + error_msg = _get_error_message_from_exception(e) + self.debug_print("Unable to decode Email Mime Content. {0}".format(error_msg)) + return action_result.set_status(phantom.APP_ERROR, "Unable to decode Email Mime Content") + + # Create ProcessEmail Object for email file attachment + process_email_obj = ProcessEmail(self, config) + process_email_obj._trigger_automation = False + ret_val, message = process_email_obj.process_email(rfc822_email, attachment['id'], epoch=None, container_id=container_id) + if phantom.is_fail(ret_val): + return action_result.set_status(phantom.APP_ERROR, message) + else: + self.debug_print("No content found in the .eml file attachment. Hence, skipping the email file processing.") + + else: + attach_artifact = {} + artifacts.append(attach_artifact) + if not self._handle_attachment(attachment, container_id, artifact_json=attach_artifact): + return action_result.set_status(phantom.APP_ERROR, "Could not process attachment. See logs for details.") + + return phantom.APP_SUCCESS + + def _process_email_data(self, config, action_result, endpoint, email): + """ + Process email data. + + :param config: config dict + :param action_result: Action result or BaseConnector object + :param endpoint: endpoint for making REST calls + :param emails: Emails to process + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS with status message + """ + container = {} + + container['name'] = email['subject'] if email['subject'] else email['id'] + container_description = MSGOFFICE365_CONTAINER_DESCRIPTION.format(last_modified_time=email['lastModifiedDateTime']) + container['description'] = container_description + container['source_data_identifier'] = email['id'] + + ret_val, message, container_id = self.save_container(container) + + if phantom.is_fail(ret_val) or not container_id: + return action_result.set_status(phantom.APP_ERROR, message) + + if MSGOFFICE365_DUPLICATE_CONTAINER_FOUND_MSG in message.lower(): + self.debug_print("Duplicate container found") + self._duplicate_count += 1 + + # Prevent further processing if the email is not modified + ret_val, container_info, status_code = self.get_container_info(container_id=container_id) + if phantom.is_fail(ret_val): + return action_result.set_status( + phantom.APP_ERROR, + "Status Code: {}. Error occurred while fetching the container info for container ID: {}".format(status_code, container_id) + ) + + if container_info.get('description', '') == container_description: + msg = "Email ID: {} has not been modified. Hence, skipping the artifact ingestion.".format(email['id']) + self.debug_print(msg) + return action_result.set_status(phantom.APP_SUCCESS, msg) + else: + # Update the container's description and continue + self.debug_print("Updating container's description") + ret_val = self._update_container(action_result, container_id, container) + if phantom.is_fail(ret_val): + return action_result.get_status() + + self.debug_print("Creating email artifacts") + email_artifacts = self._create_email_artifacts(container_id, email) + attachment_artifacts = [] + + if email['hasAttachments'] and config.get('extract_attachments', False): + + attach_endpoint = endpoint + '/{0}/attachments'.format(email['id']) + ret_val, attach_resp = self._make_rest_call_helper(action_result, attach_endpoint) + if phantom.is_fail(ret_val): + return action_result.get_status() + + ret_val = self._extract_attachments( + config, attach_endpoint, attachment_artifacts, + action_result, attach_resp.get('value', []), container_id, first_time=True + ) + if phantom.is_fail(ret_val): + return action_result.get_status() + + artifacts = attachment_artifacts + email_artifacts + ret_val, message, container_id = self.save_artifacts(artifacts) + if phantom.is_fail(ret_val): + return action_result.set_status(phantom.APP_ERROR, message) + + return phantom.APP_SUCCESS + def _handle_test_connectivity(self, param): """ Function that handles the test connectivity action, it is much simpler than other action handlers.""" @@ -753,14 +973,14 @@ def _handle_test_connectivity(self, param): self.save_progress("Getting App REST endpoint URL") - # Get the URL to the app's REST Endpiont, this is the url that the TC dialog + # Get the URL to the app's REST Endpoint, this is the url that the TC dialog # box will ask the user to connect to ret_val, app_rest_url = self._get_url_to_app_rest(action_result) app_state = {} if phantom.is_fail(ret_val): self.save_progress("Unable to get the URL to the app's REST Endpoint. Error: {0}".format( action_result.get_message())) - return self.set_status(phantom.APP_ERROR) + return action_result.set_status(phantom.APP_ERROR) # create the url that the oauth server should re-direct to after the auth is completed # (success and failure), this is added to the state so that the request handler will access @@ -774,7 +994,7 @@ def _handle_test_connectivity(self, param): if phantom.is_fail(ret_val): self.save_progress("Unable to get the URL to the app's REST Endpoint. Error: {0}".format( action_result.get_message())) - return self.set_status(phantom.APP_ERROR) + return action_result.set_status(phantom.APP_ERROR) if self._admin_access: # Create the url for fetching administrator consent @@ -785,7 +1005,7 @@ def _handle_test_connectivity(self, param): else: # Scope is required for non-admin access if not self._scope: - return self.set_status(phantom.APP_ERROR, "Please provide scope for non-admin access in the asset configuration") + return action_result.set_status(phantom.APP_ERROR, "Please provide scope for non-admin access in the asset configuration") # Create the url authorization, this is the one pointing to the oauth server side admin_consent_url = "https://login.microsoftonline.com/{0}/oauth2/v2.0/authorize".format(self._tenant) admin_consent_url += "?client_id={0}".format(self._client_id) @@ -832,7 +1052,7 @@ def _handle_test_connectivity(self, param): if not completed: self.save_progress("Authentication process does not seem to be completed. Timing out") - return self.set_status(phantom.APP_ERROR) + return action_result.set_status(phantom.APP_ERROR) self.send_progress("") @@ -842,18 +1062,18 @@ def _handle_test_connectivity(self, param): if not self._state: self.save_progress("Authorization not received or not given") self.save_progress("Test Connectivity Failed") - return self.set_status(phantom.APP_ERROR) + return action_result.set_status(phantom.APP_ERROR) else: if self._admin_access: if not self._state.get('admin_consent'): self.save_progress("Admin Consent not received or not given") self.save_progress("Test Connectivity Failed") - return self.set_status(phantom.APP_ERROR) + return action_result.set_status(phantom.APP_ERROR) else: if not self._state.get('code'): self.save_progress("Authorization code not received or not given") self.save_progress("Test Connectivity Failed") - return self.set_status(phantom.APP_ERROR) + return action_result.set_status(phantom.APP_ERROR) self.save_progress("Getting the token") ret_val = self._get_token(action_result) @@ -875,7 +1095,7 @@ def _handle_test_connectivity(self, param): if phantom.is_fail(ret_val): self.save_progress(msg_failed) self.save_progress("Test Connectivity Failed") - return self.set_status(phantom.APP_ERROR) + return action_result.set_status(phantom.APP_ERROR) value = response.get('value') @@ -884,23 +1104,23 @@ def _handle_test_connectivity(self, param): self.save_progress("Test Connectivity Passed") - return self.set_status(phantom.APP_SUCCESS) + return action_result.set_status(phantom.APP_SUCCESS) def _handle_copy_email(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) - email_addr = _handle_py_ver_compat_for_input_str(self._python_version, param['email_address'], self) - folder = _handle_py_ver_compat_for_input_str(self._python_version, param["folder"], self) - message_id = _handle_py_ver_compat_for_input_str(self._python_version, param['id'], self) + email_addr = param['email_address'] + folder = param["folder"] + message_id = param['id'] endpoint = '/users/{0}'.format(email_addr) endpoint += '/messages/{0}/copy'.format(message_id) body = {'DestinationId': folder} - if param.get('get_folder_id', False): + if param.get('get_folder_id', True): try: dir_id, error, _ = self._get_folder_id(action_result, folder, email_addr) except ReturnException: @@ -925,15 +1145,15 @@ def _handle_move_email(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) - email_addr = _handle_py_ver_compat_for_input_str(self._python_version, param['email_address'], self) - folder = _handle_py_ver_compat_for_input_str(self._python_version, param["folder"], self) - message_id = _handle_py_ver_compat_for_input_str(self._python_version, param['id'], self) + email_addr = param['email_address'] + folder = param["folder"] + message_id = param['id'] endpoint = '/users/{0}'.format(email_addr) endpoint += '/messages/{0}/move'.format(message_id) body = {'DestinationId': folder} - if param.get('get_folder_id', False): + if param.get('get_folder_id', True): try: dir_id, error, _ = self._get_folder_id(action_result, folder, email_addr) @@ -960,8 +1180,8 @@ def _handle_delete_email(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) - email_addr = _handle_py_ver_compat_for_input_str(self._python_version, param['email_address'], self) - message_id = _handle_py_ver_compat_for_input_str(self._python_version, param['id'], self) + email_addr = param['email_address'] + message_id = param['id'] endpoint = "/users/{0}".format(email_addr) endpoint += '/messages/{0}'.format(message_id) @@ -976,7 +1196,7 @@ def _handle_oof_check(self, param): self.save_progress('In action handler for: {0}'.format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) - user_id = _handle_py_ver_compat_for_input_str(self._python_version, param['user_id'], self) + user_id = param['user_id'] endpoint = '/users/{0}/mailboxSettings/automaticRepliesSetting'.format(user_id) @@ -994,31 +1214,23 @@ def _handle_list_events(self, param): self.save_progress('In action handler for: {0}'.format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) - try: - user_id = _handle_py_ver_compat_for_input_str(self._python_version, param.get('user_id'), self) if param.get('user_id') else None - group_id = _handle_py_ver_compat_for_input_str(self._python_version, param.get('group_id'), self) if param.get('group_id') else None - query = _handle_py_ver_compat_for_input_str(self._python_version, param.get('filter'), self) if param.get('filter') else None - except: - return action_result.set_status(phantom.APP_ERROR, "Please check your input parameters") + user_id = param.get('user_id') if param.get('user_id') else None + group_id = param.get('group_id') if param.get('group_id') else None + query = param.get('filter') if param.get('filter') else None limit = param.get('limit') + # Integer validation for 'limit' action parameter + ret_val, limit = _validate_integer(action_result, limit, "'limit' action") + if phantom.is_fail(ret_val): + return action_result.get_status() + if user_id is None and group_id is None: - return action_result.set_status(phantom.APP_ERROR, 'Either a user_id or group_id must be supplied to the "list_events" action') + return action_result.set_status(phantom.APP_ERROR, 'Either a "user_id" or "group_id" must be supplied to the "list_events" action') if user_id and group_id and user_id != "" and group_id != "": return action_result.set_status(phantom.APP_ERROR, 'Either a user_id or group_id can be supplied to the "list_events" action - not both') - if limit is not None: - try: - if not float(limit).is_integer() or limit == 0: - return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_INVALID_LIMIT) - param['limit'] = limit = int(limit) - if limit < 0: - return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_INVALID_LIMIT) - except: - return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_INVALID_LIMIT) - endpoint = '' if user_id: @@ -1035,22 +1247,17 @@ def _handle_list_events(self, param): msg = action_result.get_message() if '$top' in msg or '$top/top' in msg: msg += "The '$top' parameter is already used internally to handle pagination logic. " - msg += "If you want to restirct results in terms of number of output results, you can use the 'limit' parameter." + msg += "If you want to restrict results in terms of number of output results, you can use the 'limit' parameter." return action_result.set_status(phantom.APP_ERROR, msg) return action_result.get_status() if not events: # No events found is a valid scenario that there can be 0 events returned # even if the API call is a success for the correct given inputs and hence, returning APP_SUCCESS. - return action_result.set_status(phantom.APP_SUCCESS, "No data found") + return action_result.set_status(phantom.APP_SUCCESS, MSGOFFICE365_NO_DATA_FOUND) for event in events: - categories = [] - attendees = [] - for category in event["categories"]: - categories.append({"name": category}) - for attendee in event["attendees"]: - attendees.append(attendee["emailAddress"]["name"]) + attendees = [attendee.get("emailAddress", {}).get("name") for attendee in event.get("attendees", [])] event["attendee_list"] = ", ".join(attendees) action_result.add_data(event) @@ -1066,17 +1273,13 @@ def _handle_list_groups(self, param): action_result = self.add_action_result(ActionResult(dict(param))) limit = param.get('limit') - query = _handle_py_ver_compat_for_input_str(self._python_version, param.get('filter'), self) if param.get('filter') else None - if limit is not None: - try: - if not float(limit).is_integer() or limit == 0: - return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_INVALID_LIMIT) - param['limit'] = limit = int(limit) - if limit < 0: - return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_INVALID_LIMIT) - except: - return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_INVALID_LIMIT) + # Integer validation for 'limit' action parameter + ret_val, limit = _validate_integer(action_result, limit, "'limit' action") + if phantom.is_fail(ret_val): + return action_result.get_status() + + query = param.get('filter') if param.get('filter') else None endpoint = '/groups' @@ -1086,7 +1289,7 @@ def _handle_list_groups(self, param): return action_result.get_status() if not groups: - return action_result.set_status(phantom.APP_SUCCESS, "No data found") + return action_result.set_status(phantom.APP_SUCCESS, MSGOFFICE365_NO_DATA_FOUND) for group in groups: action_result.add_data(group) @@ -1103,17 +1306,13 @@ def _handle_list_users(self, param): action_result = self.add_action_result(ActionResult(dict(param))) limit = param.get('limit') - query = _handle_py_ver_compat_for_input_str(self._python_version, param.get('filter'), self) if param.get('filter') else None - if limit is not None: - try: - if not float(limit).is_integer() or limit == 0: - return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_INVALID_LIMIT) - param['limit'] = limit = int(limit) - if limit < 0: - return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_INVALID_LIMIT) - except: - return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_INVALID_LIMIT) + # Integer validation for 'limit' action parameter + ret_val, limit = _validate_integer(action_result, limit, "'limit' action") + if phantom.is_fail(ret_val): + return action_result.get_status() + + query = param.get('filter') if param.get('filter') else None endpoint = '/users' @@ -1123,7 +1322,7 @@ def _handle_list_users(self, param): return action_result.get_status() if not users: - return action_result.set_status(phantom.APP_SUCCESS, "No data found") + return action_result.set_status(phantom.APP_SUCCESS, MSGOFFICE365_NO_DATA_FOUND) for user in users: action_result.add_data(user) @@ -1139,8 +1338,8 @@ def _handle_list_folders(self, param): action_result = self.add_action_result(ActionResult(dict(param))) list_folder = list() - user_id = _handle_py_ver_compat_for_input_str(self._python_version, param['user_id'], self) - folder_id = _handle_py_ver_compat_for_input_str(self._python_version, param.get('folder_id'), self) + user_id = param['user_id'] + folder_id = param.get('folder_id') if not folder_id: # fetching root level folders @@ -1155,7 +1354,7 @@ def _handle_list_folders(self, param): # checking for child folder if have, add it in list of folders for root_folder in root_folders: - if root_folder['childFolderCount'] == 0: + if root_folder.get('childFolderCount', 0) == 0: continue else: ret_val = self._list_child_folders(action_result, list_folder, user_id=user_id, parent_folder=root_folder) @@ -1187,7 +1386,7 @@ def _fetch_root_folders(self, action_result, user_id): return action_result.get_status(), None if not folders: - return action_result.set_status(phantom.APP_SUCCESS, "No data found"), None + return action_result.set_status(phantom.APP_SUCCESS, MSGOFFICE365_NO_DATA_FOUND), None return phantom.APP_SUCCESS, folders @@ -1205,9 +1404,8 @@ def _list_child_folders(self, action_result, list_folder, user_id, parent_folder # checking for child folder if have, add it in list of folders for child_folder in child_folders: - if child_folder['childFolderCount'] == 0: + if child_folder.get('childFolderCount', 0) == 0: list_folder.append(child_folder) - continue else: ret_val = self._list_child_folders(action_result, list_folder, user_id=user_id, parent_folder=child_folder) @@ -1252,8 +1450,8 @@ def _handle_get_email(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) - email_addr = _handle_py_ver_compat_for_input_str(self._python_version, param['email_address'], self) - message_id = _handle_py_ver_compat_for_input_str(self._python_version, param['id'], self) + email_addr = param['email_address'] + message_id = param['id'] endpoint = '/users/{0}'.format(email_addr) endpoint += '/messages/{0}'.format(message_id) @@ -1269,10 +1467,10 @@ def _handle_get_email(self, param): if phantom.is_fail(ret_val): return action_result.get_status() # For Drafts there might not be any internetMessageHeaders, - # so we have to use get() fetching insted of direct fetching from dictionary + # so we have to use get() fetching instead of directly fetching from dictionary response['internetMessageHeaders'] = header_response.get('internetMessageHeaders') - if param['download_attachments'] and response.get('hasAttachments'): + if param.get('download_attachments', False) and response.get('hasAttachments'): endpoint += '/attachments?$expand=microsoft.graph.itemattachment/item' ret_val, attach_resp = self._make_rest_call_helper(action_result, endpoint) @@ -1310,8 +1508,8 @@ def _handle_get_email_properties(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) - email_addr = _handle_py_ver_compat_for_input_str(self._python_version, param['email_address'], self) - message_id = _handle_py_ver_compat_for_input_str(self._python_version, param['id'], self) + email_addr = param['email_address'] + message_id = param['id'] endpoint = '/users/{0}'.format(email_addr) endpoint += '/messages/{0}'.format(message_id) @@ -1326,8 +1524,9 @@ def _handle_get_email_properties(self, param): if param.get('get_sender'): select_list.append('sender') if 'properties_list' in param: - properties_list = _handle_py_ver_compat_for_input_str(self._python_version, param['properties_list'], self) - select_list += properties_list.strip().split(',') + properties_list = param['properties_list'] + properties_list = [property.strip() for property in properties_list.strip().split(',') if property.strip()] + select_list += properties_list if select_list: endpoint += '?$select={0}'.format(','.join(select_list)) @@ -1343,6 +1542,35 @@ def _handle_get_email_properties(self, param): return action_result.set_status(phantom.APP_SUCCESS, "Successfully fetched email") + def _manage_data_duplication(self, emails, total_ingested, limit, max_emails): + """ + This function handles the duplicate emails we get during the ingestion process. + + :param emails: Processed emails + :param total_ingested: Total ingested emails till now + :param limit: Current pagination limit + :param max_emails: Max emails to ingest + :return: limit: next cycle pagination limit, total_ingested: Total ingested emails till now + """ + total_ingested_current_cycle = limit - self._duplicate_count + total_ingested += total_ingested_current_cycle + + remaining_count = max_emails - total_ingested + if remaining_count <= 0: + return 0, total_ingested + + expected_duplicate_count_in_next_cycle = 0 + last_modified_time = emails[-1]['lastModifiedDateTime'] + + # Calculate the duplicate emails count we can get in the next cycle + for email in reversed(emails): + if email["lastModifiedDateTime"] != last_modified_time: + break + expected_duplicate_count_in_next_cycle += 1 + + limit = expected_duplicate_count_in_next_cycle + remaining_count + return limit, total_ingested + def _handle_on_poll(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) @@ -1354,13 +1582,21 @@ def _handle_on_poll(self, param): if self.is_poll_now(): max_emails = param[phantom.APP_JSON_CONTAINER_COUNT] elif self._state.get('first_run', True): - self._state['first_run'] = False - max_emails = config.get('first_run_max_emails', 1000) - self._state['last_time'] = datetime.utcnow().strftime(O365_TIME_FORMAT) + # Integer validation for 'first_run_max_emails' config parameter + ret_val, max_emails = _validate_integer( + action_result, config.get('first_run_max_emails', 1000), "'Maximum Containers for scheduled polling first time' config" + ) + if phantom.is_fail(ret_val): + return action_result.get_status() else: - max_emails = config.get('max_containers', 100) + # Integer validation for 'max_containers' config parameter + ret_val, max_emails = _validate_integer( + action_result, config.get('max_containers', 100), "'Maximum Containers for scheduled polling' config" + ) + if phantom.is_fail(ret_val): + return action_result.get_status() + start_time = self._state['last_time'] - self._state['last_time'] = datetime.utcnow().strftime(O365_TIME_FORMAT) if not config.get('email_address'): return action_result.set_status(phantom.APP_ERROR, "Email Adress to ingest must be supplied in asset!") @@ -1371,96 +1607,88 @@ def _handle_on_poll(self, param): if 'folder' in config: folder = config.get('folder', '') - if '\\' in folder: - folder = folder.replace('\\', '/') + if config.get('get_folder_id', True): + try: + dir_id, error, _ = self._get_folder_id(action_result, folder, config.get('email_address')) + except ReturnException: + return action_result.get_status() + if dir_id: + folder = dir_id + else: + self.save_progress(error) + return action_result.set_status(phantom.APP_ERROR, error) endpoint += '/mailFolders/{0}'.format(folder) endpoint += '/messages' + order = 'asc' if config['ingest_manner'] == 'oldest first' else 'desc' + + params = { + '$orderBy': 'lastModifiedDateTime {}'.format(order) + } - params = {'$top': str(max_emails)} if start_time: params['$filter'] = "lastModifiedDateTime ge {0}".format(start_time) - ret_val, response = self._make_rest_call_helper(action_result, endpoint, params=params) - if phantom.is_fail(ret_val): - return action_result.get_status() - - emails = response.get('value') - - for email in emails: - self.save_progress('Processing email with ID ending in: {}'.format(email['id'][-10:])) - container = {} + cur_limit = max_emails + total_ingested = 0 - container['name'] = email['subject'] if email['subject'] else email['id'] - container['description'] = 'Email ingested using MS Graph API' - container['source_data_identifier'] = email['id'] - - ret_val, message, container_id = self.save_container(container) + # If the ingestion manner is set for the latest emails, then the 0th index email is the latest + # in the list returned, else the last email is the latest. This will be used to store the + # last modified time in the state file + email_index = 0 if config['ingest_manner'] == "latest first" else -1 + while True: + self._duplicate_count = 0 + ret_val, emails = self._paginator(action_result, endpoint, limit=cur_limit, params=params) if phantom.is_fail(ret_val): - return action_result.set_status(phantom.APP_ERROR, message), None - - artifacts = self._create_email_artifacts(container_id, email) - - if not container_id: - return phantom.APP_ERROR - - if email['hasAttachments'] and config.get('extract_attachments', False): - - attach_endpoint = endpoint + '/{0}/attachments'.format(email['id']) - ret_val, attach_resp = self._make_rest_call_helper(action_result, attach_endpoint) - if phantom.is_fail(ret_val): - return action_result.get_status() - - for attachment in attach_resp.get('value', []): - - if attachment.get('@odata.type') == '#microsoft.graph.itemAttachment': - - sub_email_endpoint = attach_endpoint + '/{0}?$expand=microsoft.graph.itemattachment/item'.format(attachment['id']) - ret_val, sub_email_resp = self._make_rest_call_helper(action_result, sub_email_endpoint) - if phantom.is_fail(ret_val): - return action_result.get_status() - - sub_email = sub_email_resp['item'] - if sub_email.get('@odata.type') != '#microsoft.graph.message': - continue - - container = {} - - container['name'] = email['subject'] if email['subject'] else email['id'] - container['description'] = 'Email ingested using MS Graph API' - container['source_data_identifier'] = email['id'] - - ret_val, message, sub_container_id = self.save_container(container) - - if phantom.is_fail(ret_val): - return action_result.set_status(phantom.APP_ERROR, message), None - - sub_artifacts = self._create_email_artifacts(sub_container_id, sub_email) - - if not sub_container_id: - return phantom.APP_ERROR - - ret_val, message, sub_container_id = self.save_artifacts(sub_artifacts) + return action_result.get_status() - elif attachment['name'].endswith('.eml'): - ret_val, message = self._process_email.process_email(self, base64.b64decode(attachment['contentBytes']), - attachment['id'], None) + if not emails: + return action_result.set_status(phantom.APP_SUCCESS, MSGOFFICE365_NO_DATA_FOUND) - else: - attach_artifact = {} - artifacts.append(attach_artifact) - if not self._handle_attachment(attachment, container_id, artifact_json=attach_artifact): - return action_result.set_status(phantom.APP_ERROR, "Could not process attachment. See logs for details.") + failed_email_ids = 0 + total_emails = len(emails) - ret_val, message, container_id = self.save_artifacts(artifacts) + self.save_progress(f"Total emails fetched: {total_emails}") + if self.is_poll_now(): + self.save_progress("Ingesting all possible artifacts (ignoring maximum artifacts value) for POLL NOW") - if phantom.is_fail(ret_val): - return action_result.set_status(phantom.APP_ERROR, message) + for index, email in enumerate(emails): + try: + self.send_progress('Processing email # {} with ID ending in: {}'.format(index + 1, email['id'][-10:])) + ret_val = self._process_email_data(config, action_result, endpoint, email) + if phantom.is_fail(ret_val): + failed_email_ids += 1 + self.debug_print(f"Error occurred while processing email ID: {email.get('id')}. {action_result.get_message()}") + except Exception as e: + failed_email_ids += 1 + error_msg = _get_error_message_from_exception(e) + self.debug_print(f"Exception occurred while processing email ID: {email.get('id')}. {error_msg}") + + if failed_email_ids == total_emails: + return action_result.set_status(phantom.APP_ERROR, "Error occurred while processing all the email IDs") + + if not self.is_poll_now(): + last_time = datetime.strptime(emails[email_index]['lastModifiedDateTime'], O365_TIME_FORMAT).strftime(O365_TIME_FORMAT) + self._state['last_time'] = last_time + self.save_state(self._state) + + # Setting filter for next cycle + params['$filter'] = "lastModifiedDateTime ge {0}".format(last_time) + + # Duplication logic should only work for the oldest first order and if we have more data on the server. + if total_emails >= cur_limit and email_index == -1: + cur_limit, total_ingested = self._manage_data_duplication(emails, total_ingested, cur_limit, max_emails) + if not cur_limit: + break + else: + break + else: + break - if not self.is_poll_now() and len(emails) == int(max_emails): - self._state['last_time'] = (datetime.strptime(emails[-1]['lastModifiedDateTime'], O365_TIME_FORMAT) + timedelta( - seconds=1)).strftime(O365_TIME_FORMAT) + # Update the 'first_run' value only if the ingestion gets successfully completed + if not self.is_poll_now() and self._state.get('first_run', True): + self._state['first_run'] = False return action_result.set_status(phantom.APP_SUCCESS) @@ -1468,7 +1696,7 @@ def _validate_range(self, email_range, action_result): try: mini, maxi = (int(x) for x in email_range.split('-')) - except: + except Exception: return action_result.set_status(phantom.APP_ERROR, "Unable to parse the range. Please specify the range as min_offset-max_offset") if mini < 0 or maxi < 0: @@ -1485,6 +1713,7 @@ def _validate_range(self, email_range, action_result): def _handle_generate_token(self, param): + self.save_progress('In action handler for: {0}'.format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) ret_val = self._get_token(action_result) if phantom.is_fail(ret_val): @@ -1500,43 +1729,36 @@ def _handle_run_query(self, param): action_result = self.add_action_result(ActionResult(dict(param))) limit = param.get('limit') - - if limit is not None: - try: - if not float(limit).is_integer() or limit == 0: - return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_INVALID_LIMIT) - param['limit'] = limit = int(limit) - if limit < 0: - return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_INVALID_LIMIT) - except: - return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_INVALID_LIMIT) + # Integer validation for 'limit' action parameter + ret_val, limit = _validate_integer(action_result, limit, "'limit' action") + if phantom.is_fail(ret_val): + return action_result.get_status() # user - email_addr = _handle_py_ver_compat_for_input_str(self._python_version, param['email_address'], self) + email_addr = param['email_address'] endpoint = "/users/{0}".format(email_addr) query = "" params = dict() if 'internet_message_id' in param: params = { - '$filter': "internetMessageId eq '{0}'".format(_handle_py_ver_compat_for_input_str( - self._python_version, param['internet_message_id'], self)) + '$filter': "internetMessageId eq '{0}'".format(param['internet_message_id']) } elif 'query' in param: - query = "?{0}".format(_handle_py_ver_compat_for_input_str(self._python_version, param['query'], self)) + query = "?{0}".format(param['query']) else: # search params search_query = '' if 'subject' in param: - search_query += "subject:{0} ".format(_handle_py_ver_compat_for_input_str(self._python_version, param['subject'], self)) + search_query += "subject:{0} ".format(param['subject']) if 'body' in param: - search_query += "body:{0} ".format(_handle_py_ver_compat_for_input_str(self._python_version, param['body'], self)) + search_query += "body:{0} ".format(param['body']) if 'sender' in param: - search_query += "from:{0} ".format(_handle_py_ver_compat_for_input_str(self._python_version, param['sender'], self)) + search_query += "from:{0} ".format(param['sender']) if search_query: params['$search'] = '"{0}"'.format(search_query[:-1]) @@ -1567,9 +1789,9 @@ def _handle_run_query(self, param): # folder elif 'folder' in param: - folder = _handle_py_ver_compat_for_input_str(self._python_version, param['folder'], self) + folder = param['folder'] - if param.get('get_folder_id', False): + if param.get('get_folder_id', True): try: dir_id, error, _ = self._get_folder_id(action_result, folder, email_addr) except ReturnException: @@ -1605,12 +1827,12 @@ def _handle_run_query(self, param): msg = action_result.get_message() if '$top' in msg or '$top/top' in msg: msg += "The '$top' parameter is already used internally to handle pagination logic. " - msg += "If you want to restirct results in terms of number of output results, you can use the 'limit' parameter." + msg += "If you want to restrict results in terms of number of output results, you can use the 'limit' parameter." return action_result.set_status(phantom.APP_ERROR, msg) return action_result.get_status() if not messages: - return action_result.set_status(phantom.APP_SUCCESS, "No data found") + return action_result.set_status(phantom.APP_SUCCESS, MSGOFFICE365_NO_DATA_FOUND) action_result.update_data(messages) action_result.update_summary({'emails_matched': action_result.get_data_size()}) @@ -1733,8 +1955,8 @@ def _handle_create_folder(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) - email = _handle_py_ver_compat_for_input_str(self._python_version, param["email_address"], self) - folder = _handle_py_ver_compat_for_input_str(self._python_version, param["folder"], self) + email = param["email_address"] + folder = param["folder"] minusp = param.get("all_subdirs", False) @@ -1830,8 +2052,8 @@ def _handle_get_folder_id(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) - email = _handle_py_ver_compat_for_input_str(self._python_version, param["email_address"], self) - folder = _handle_py_ver_compat_for_input_str(self._python_version, param["folder"], self) + email = param["email_address"] + folder = param["folder"] try: dir_id, error, ret = self._get_folder_id(action_result, folder, email) @@ -1892,22 +2114,11 @@ def _paginator(self, action_result, endpoint, limit=None, params=None, query=Non if limit and len(list_items) >= limit: return phantom.APP_SUCCESS, list_items[:limit] - next_link = response.get('@odata.nextLink', None) + next_link = response.get('@odata.nextLink') if not next_link: break - if params is not None: - if '$top' in params: - del(params['$top']) - - if '$search' in params: - del(params['$search']) - - if '$filter' in params: - del(params['$filter']) - - if params == {}: - params = None + params = None return phantom.APP_SUCCESS, list_items @@ -1999,6 +2210,7 @@ def _get_token(self, action_result): else: return action_result.set_status(phantom.APP_ERROR, "Unexpected details retrieved from the state file.") + self.debug_print("Generating token...") ret_val, resp_json = self._make_rest_call(action_result, req_url, headers=headers, data=data, method='post') if phantom.is_fail(ret_val): return action_result.get_status() @@ -2007,7 +2219,7 @@ def _get_token(self, action_result): self._state['admin_auth'] = resp_json else: self._state['non_admin_auth'] = resp_json - # Fetching the acces token and refresh token + # Fetching the access token and refresh token self._access_token = resp_json.get('access_token') self._refresh_token = resp_json.get('refresh_token') @@ -2031,7 +2243,8 @@ def _get_token(self, action_result): if self._access_token != self._state.get('non_admin_auth', {}).get('access_token'): return action_result.set_status(phantom.APP_ERROR, MSGOFFICE365_INVALID_PERMISSION_ERR) - return (phantom.APP_SUCCESS) + self.debug_print("Token generated successfully") + return action_result.set_status(phantom.APP_SUCCESS) def initialize(self): @@ -2040,12 +2253,6 @@ def initialize(self): self._currentdir = None - # Fetching the Python major version - try: - self._python_version = int(sys.version_info[0]) - except: - return self.set_status(phantom.APP_ERROR, "Error occurred while getting the Phantom server's Python major version.") - # Load the state in initialize config = self.get_config() @@ -2058,12 +2265,12 @@ def initialize(self): } return self.set_status(phantom.APP_ERROR, MSGOFFICE365_STATE_FILE_CORRUPT_ERROR) - self._tenant = _handle_py_ver_compat_for_input_str(self._python_version, config['tenant'], self) - self._client_id = _handle_py_ver_compat_for_input_str(self._python_version, config['client_id'], self) - self._client_secret = _handle_py_ver_compat_for_input_str(self._python_version, config['client_secret'], self) + self._tenant = config['tenant'] + self._client_id = config['client_id'] + self._client_secret = config['client_secret'] self._admin_access = config.get('admin_access') self._admin_consent = config.get('admin_consent') - self._scope = _handle_py_ver_compat_for_input_str(self._python_version, config.get('scope'), self) if config.get('scope') else None + self._scope = config.get('scope') if config.get('scope') else None if not self._admin_access: if not self._scope: @@ -2118,11 +2325,11 @@ def finalize(self): if __name__ == '__main__': - # import sys - # import pudb import argparse - # pudb.set_trace() + import pudb + + pudb.set_trace() argparser = argparse.ArgumentParser() diff --git a/office365_consts.py b/office365_consts.py index d1d3d70..250bfd3 100644 --- a/office365_consts.py +++ b/office365_consts.py @@ -16,6 +16,7 @@ MSGOFFICE365_PER_PAGE_COUNT = 999 PHANTOM_SYS_INFO_URL = "{url}rest/system_info" PHANTOM_ASSET_INFO_URL = "{url}rest/asset/{asset_id}" +PHANTOM_CONTAINER_INFO_URL = "{url}rest/container/{container_id}" O365_TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ" MSGOFFICE365_RUN_CONNECTIVITY_MSG = "Please run test connectivity first to complete authorization flow and "\ "generate a token that the app can use to make calls to the server " @@ -25,7 +26,6 @@ " displayName eq 'msg folder root' or displayName eq 'outbox' or displayName eq 'recoverable items deletions' or "\ "displayName eq 'scheduled' or displayName eq 'search folders' or displayName eq 'sent items' or displayName eq 'server failures' or "\ "displayName eq 'sync issues'" -MSGOFFICE365_INVALID_LIMIT = "Please provide non-zero positive integer value in the 'limit' parameter." MSGOFFICE365_STATE_FILE_CORRUPT_ERROR = "Error occurred while loading the state file due to its unexpected format. Resetting the state file with the default format. \ Please try again." MSGOFFICE365_AUTHORIZE_TROUBLESHOOT_MSG = 'If authorization URL fails to communicate with your Phantom instance, check whether you have: '\ @@ -36,5 +36,18 @@ MSGOFFICE365_INVALID_PERMISSION_ERR += " Please check the owner, owner group, and the permissions of the state file. The Phantom " MSGOFFICE365_INVALID_PERMISSION_ERR += "user should have the correct access rights and ownership for the corresponding state file "\ "(refer to readme file for more information)." +MSGOFFICE365_NO_DATA_FOUND = "No data found" +MSGOFFICE365_DUPLICATE_CONTAINER_FOUND_MSG = "duplicate container found" MSGOFFICE365_DEFAULT_REQUEST_TIMEOUT = 30 # in seconds +MSGOFFICE365_CONTAINER_DESCRIPTION = 'Email ingested using MS Graph API - {last_modified_time}' + +# Constants relating to '_get_error_message_from_exception' +ERR_MSG_UNAVAILABLE = "Error message unavailable. Please check the asset configuration and|or action parameters" + +# Constants relating to 'validate_integer' +MSGOFFICE365_VALID_INT_MSG = "Please provide a valid integer value in the {param} parameter" +MSGOFFICE365_NON_NEG_NON_ZERO_INT_MSG = ( + "Please provide a valid non-zero positive integer value in the {param} parameter" +) +MSGOFFICE365_NON_NEG_INT_MSG = "Please provide a valid non-negative integer value in the {param} parameter" diff --git a/office365_get_email.html b/office365_get_email.html index 4957d6f..0684f0e 100644 --- a/office365_get_email.html +++ b/office365_get_email.html @@ -73,6 +73,11 @@ .office365 .dataTable .glyphicon.glyphicon-dot:before { content: "\25cf"; font-size: 10px; } + + .office365 .no-word-wrap { + white-space: nowrap; + } +
@@ -148,10 +153,12 @@

Data

+ {{ data.bodyPreview }} - {% if data.from %} + + {% if data.from is not None %} - {{ data.from.emailAddress.address }}   @@ -159,15 +166,16 @@

Data

{% else %} - + None {% endif %} + {% if data.toRecipients %} {% for to in data.toRecipients %}
- {{ to.emailAddress.address }}   @@ -179,11 +187,12 @@

Data

{% else %} - + None {% endif %} + {{ data.hasAttachments }} - {{ data.internetMessageId }}   @@ -212,7 +221,7 @@

Attachments

{{ file.name }} -
{{ file.vaultId }}   diff --git a/office365_run_query.html b/office365_run_query.html index 9c1bc1c..e14db19 100644 --- a/office365_run_query.html +++ b/office365_run_query.html @@ -73,6 +73,11 @@ .office365 .dataTable .glyphicon.glyphicon-dot:before { content: "\25cf"; font-size: 10px; } + + .office365 .no-word-wrap { + white-space: nowrap; + } +
@@ -180,24 +185,36 @@

Data

{% for data in result.data %} - -
- {{ data.sender.emailAddress.address }} -   - - - + {% if data.sender.emailAddress.address is not None %} + + + {{ data.sender.emailAddress.address }} +   + + + + {% else %} + None + {% endif %} + {{ data.receivedDateTime }} - - - {{ data.subject }} -   - - - + + {% if data.subject is not None %} + + + {{ data.subject }} +   + + + + {% else %} + None + {% endif %} + {{ data.bodyPreview }} + @@ -206,8 +223,9 @@

Data

+ - {{ data.internetMessageId }}   diff --git a/process_email.py b/process_email.py index c9283f6..5f3cc7c 100644 --- a/process_email.py +++ b/process_email.py @@ -27,14 +27,18 @@ from collections import OrderedDict from copy import deepcopy from email.header import decode_header, make_header +from html import unescape import magic import phantom.app as phantom import phantom.rules as phantom_rules import phantom.utils as ph_utils from bs4 import BeautifulSoup, UnicodeDammit +from django.core.validators import URLValidator from requests.structures import CaseInsensitiveDict +from office365_consts import ERR_MSG_UNAVAILABLE + _container_common = { "run_automation": False # Don't run any playbooks, when this artifact is added } @@ -115,6 +119,34 @@ ipv6_regexc = re.compile(IPV6_REGEX) +def _get_error_message_from_exception(e): + """ + Get appropriate error message from the exception. + :param e: Exception object + :return: error message + """ + + error_code = None + error_msg = ERR_MSG_UNAVAILABLE + + try: + if hasattr(e, "args"): + if len(e.args) > 1: + error_code = e.args[0] + error_msg = e.args[1] + elif len(e.args) == 1: + error_msg = e.args[0] + except Exception: + pass + + if not error_code: + error_text = "Error Message: {}".format(error_msg) + else: + error_text = "Error Code: {}. Error Message: {}".format(error_code, error_msg) + + return error_text + + class ProcessEmail(object): def __init__(self, base_connector, config): @@ -130,6 +162,7 @@ def __init__(self, base_connector, config): self._parsed_mail = None self._guid_to_hash = dict() self._tmp_dirs = list() + self._trigger_automation = True def _get_file_contains(self, file_path): @@ -183,28 +216,6 @@ def _get_string(self, input_str, charset): ) return input_str - def _get_error_message_from_exception(self, e): - """ - This method is used to get appropriate error message from the exception. - :param e: Exception object - :return: error message - """ - try: - if e.args: - if len(e.args) > 1: - error_code = e.args[0] - error_msg = e.args[1] - elif len(e.args) == 1: - error_code = "Error code unavailable" - error_msg = e.args[0] - else: - error_code = "Error code unavailable" - error_msg = "Error message unavailable. Please check the asset configuration and|or action parameters." - except Exception: - error_code = "Error code unavailable" - error_msg = "Error message unavailable. Please check the asset configuration and|or action parameters." - return error_code, error_msg - def _clean_url(self, url): url = url.strip('>),.]\r\n') @@ -226,46 +237,83 @@ def _extract_urls_domains(self, file_data, urls, domains, parent_id=None): if not self._config[PROC_EMAIL_JSON_EXTRACT_DOMAINS] and not self._config[PROC_EMAIL_JSON_EXTRACT_URLS]: return + # Get domains from email + extracted_domains = set() + emails = [] + emails.extend(re.findall(email_regexc, file_data)) + emails.extend(re.findall(email_regexc2, file_data)) + + for curr_email in emails: + domain = curr_email[curr_email.rfind('@') + 1:] + if domain and (not ph_utils.is_ip(domain)): + extracted_domains.add(domain) + # try to load the email try: + file_data = unescape(file_data) soup = BeautifulSoup(file_data, "html.parser") except Exception as e: - self._debug_print("Handled exception", e) + error_msg = _get_error_message_from_exception(e) + self._debug_print("Error occurred while parsing email data. {0}".format(error_msg)) return uris = [] - # get all tags that have hrefs + # get all tags that have hrefs and srcs links = soup.find_all(href=True) - if links: - # it's html, so get all the urls - uris = [x['href'] for x in links if (not x['href'].startswith('mailto:'))] + srcs = soup.find_all(src=True) + + uri_text = [] + + for link in links: # work on the text part of the link, they might be http links different from the href # and were either missed by the uri_regexc while parsing text or there was no text counterpart # in the email - uri_text = [self._clean_url(x.get_text()) for x in links] - if uri_text: - uri_text = [x for x in uri_text if x.startswith('http')] - if uri_text: - uris.extend(uri_text) - else: - # Parse it as a text file - uris = re.findall(uri_regexc, file_data) - if uris: - uris = [self._clean_url(x) for x in uris] + uri_text.append(self._clean_url(link.get_text())) + # it's html, so get all the urls + if not link['href'].startswith('mailto:'): + uris.append(link['href']) + + for src in srcs: + uri_text.append(self._clean_url(src.get_text())) + # it's html, so get all the urls + uris.append(src['src']) + + uri_text = [uri for uri in uri_text if uri.startswith('http')] + uris.extend(uri_text) + + # Parse it as a text file + uris_from_text = re.findall(uri_regexc, file_data) + if uris_from_text: + uris_from_text = [self._clean_url(uri) for uri in uris_from_text] + uris.extend(uris_from_text) + + # Get unique uris + unique_uris = set(uris) + + # Validate the uris + validate_uri = URLValidator(schemes=['http', 'https']) + validated_uris = list() + for uri in unique_uris: + try: + validate_uri(uri) + validated_uris.append(uri) + except Exception: + pass if self._config[PROC_EMAIL_JSON_EXTRACT_URLS]: # add the uris to the urls - unique_uris = set(uris) - unique_uris = list(unique_uris) - for uri in unique_uris: - uri_dict = {'requestURL': uri, 'parentInternetMessageId': parent_id} + for uri in validated_uris: + if parent_id: + uri_dict = {'requestURL': uri, 'parentInternetMessageId': parent_id} + else: + uri_dict = {'requestURL': uri} urls.append(uri_dict) if self._config[PROC_EMAIL_JSON_EXTRACT_DOMAINS]: - for uri in uris: + for uri in validated_uris: domain = phantom.get_host_from_url(uri) if domain and not self._is_ip(domain): - domains.append({'destinationDnsDomain': domain, 'parentInternetMessageId': parent_id}) + extracted_domains.add(domain) # work on any mailto urls if present if links: mailtos = [x['href'] for x in links if (x['href'].startswith('mailto:'))] @@ -274,12 +322,21 @@ def _extract_urls_domains(self, file_data, urls, domains, parent_id=None): if domain and (not self._is_ip(domain)): if '?' in domain: domain = domain[:domain.find('?')] - domains.append({'destinationDnsDomain': domain, 'parentInternetMessageId': parent_id}) + extracted_domains.add(domain) + + for domain in extracted_domains: + if parent_id: + domains.append({'destinationDnsDomain': domain, 'parentInternetMessageId': parent_id}) + else: + domains.append({'destinationDnsDomain': domain}) return def _get_ips(self, file_data, ips, parent_id=None): + if not self._config[PROC_EMAIL_JSON_EXTRACT_IPS]: + return None + # First extract what looks like an IP from the file, this is a faster operation ips_in_mail = re.findall(ip_regexc, file_data) ip6_in_mail = re.findall(ipv6_regexc, file_data) @@ -298,7 +355,24 @@ def _get_ips(self, file_data, ips, parent_id=None): if ips_in_mail: unique_ips = set(ips_in_mail) for ip in unique_ips: - ips.append({'sourceAddress': ip, 'parentInternetMessageId': parent_id}) + if parent_id: + ips.append({'sourceAddress': ip, 'parentInternetMessageId': parent_id}) + else: + ips.append({'sourceAddress': ip}) + + def _extract_hashes(self, file_data, hashes, parent_id=None): + + if not self._config[PROC_EMAIL_JSON_EXTRACT_HASHES]: + return None + + hashs_in_mail = re.findall(hash_regexc, file_data) + if hashs_in_mail: + unique_hashes = set(hashs_in_mail) + for hash in unique_hashes: + if parent_id: + hashes.append({'fileHash': hash, 'parentInternetMessageId': parent_id}) + else: + hashes.append({'fileHash': hash}) def _handle_body(self, body, parsed_mail, body_index, email_id): @@ -326,33 +400,18 @@ def _handle_body(self, body, parsed_mail, body_index, email_id): with open(local_file_path, 'rb') as f: # noqa file_data = f.read() self._base_connector.debug_print("Reading file data using binary mode") + file_data = self._get_string(file_data, 'utf-8') if file_data is None or len(file_data) == 0: return phantom.APP_ERROR self._parse_email_headers_as_inline(file_data, parsed_mail, charset, email_id) - if self._config[PROC_EMAIL_JSON_EXTRACT_DOMAINS]: - emails = [] - emails.extend(re.findall(email_regexc, file_data)) - emails.extend(re.findall(email_regexc2, file_data)) - - for curr_email in emails: - domain = curr_email[curr_email.rfind('@') + 1:] - if domain and (not ph_utils.is_ip(domain)): - domains.append({'destinationDnsDomain': domain, 'parentInternetMessageId': parent_id}) - self._extract_urls_domains(file_data, urls, domains, parent_id) - if self._config[PROC_EMAIL_JSON_EXTRACT_IPS]: - self._get_ips(file_data, ips, parent_id) + self._get_ips(file_data, ips, parent_id) - if self._config[PROC_EMAIL_JSON_EXTRACT_HASHES]: - hashs_in_mail = re.findall(hash_regexc, file_data) - if hashs_in_mail: - unique_hashes = set(hashs_in_mail) - for hash in unique_hashes: - hashes.append({'fileHash': hash, 'parentInternetMessageId': parent_id}) + self._extract_hashes(file_data, hashes, parent_id) return phantom.APP_SUCCESS @@ -444,8 +503,8 @@ def _decode_uni_string(self, input_str, def_name): decoded_strings = [decode_header(x)[0] for x in encoded_strings] decoded_strings = [{'value': x[0], 'encoding': x[1]} for x in decoded_strings] except Exception as e: - error_code, error_msg = self._get_error_message_from_exception(e) - self._debug_print("Decoding: {0}. Error code: {1}. Error message: {2}".format(encoded_strings, error_code, error_msg)) + error_msg = _get_error_message_from_exception(e) + self._debug_print("Decoding: {0}. {1}".format(encoded_strings, error_msg)) return def_name # convert to dict for safe access, if it's an empty list, the dict will be empty @@ -497,7 +556,7 @@ def _decode_uni_string(self, input_str, def_name): # replace input string with new string because issue find in PAPP-9531 if new_str and new_str_create_count == len(encoded_strings): - self.debug_print("Creating a new string entirely from the encoded_strings and assigning into input_str") + self._debug_print("Creating a new string entirely from the encoded_strings and assigning into input_str") input_str = new_str return input_str @@ -518,6 +577,7 @@ def _get_container_name(self, parsed_mail, email_id): def _handle_if_body(self, content_disp, content_id, content_type, part, bodies, file_path): + content_charset = part.get_content_charset() process_as_body = False # if content disposition is None then assume that it is @@ -536,6 +596,27 @@ def _handle_if_body(self, content_disp, content_id, content_type, part, bodies, if not part_payload: return (phantom.APP_SUCCESS, False) + if 'text/html' in content_type and self._parsed_mail[PROC_EMAIL_JSON_EMAIL_HEADERS]: + # Get Email Header Artifact + email_header_artifact = self._parsed_mail[PROC_EMAIL_JSON_EMAIL_HEADERS][0] + artifact_cef = email_header_artifact['cef'] + html_body = self._get_string(part_payload, charset=content_charset) + artifact_cef['bodyHtml'] = html_body + + try: + soup = BeautifulSoup(html_body, "html.parser") + # Remove the script, style, footer, title and navigation part from the HTML message + for element in soup(["script", "style", "footer", "title", "nav"]): + element.extract() + body_text = soup.get_text(separator=' ') + split_lines = body_text.split('\n') + split_lines = [x.strip() for x in split_lines if x.strip()] + body_text = '\n'.join(split_lines) + if body_text: + artifact_cef["bodyText"] = body_text + except Exception: + self._debug_print("Cannot parse email body text details") + with open(file_path, 'wb') as f: # noqa f.write(part_payload) @@ -583,7 +664,7 @@ def _handle_attachment(self, part, tmp_dir, file_name, file_path): f.write(part_payload) files.append({'file_name': file_name, 'file_path': file_path, 'meta_info': attach_meta_info}) except IOError as ioerr: - error_msg = self._get_error_message_from_exception(ioerr) + error_msg = _get_error_message_from_exception(ioerr) if "File name too long" in error_msg: self.write_with_new_filename(tmp_dir, part_payload, files, file_name, as_byte=False) else: @@ -633,8 +714,7 @@ def _handle_part(self, part, part_index, tmp_dir, extract_attach, parsed_mail, c file_name = self._decode_uni_string(file_name, file_name) # Remove any chars that we don't want in the name - file_path = "{0}/{1}_{2}_{3}".format(tmp_dir, part_index, - file_name.translate(None, ''.join(['<', '>', ' '])), child) + file_path = "{0}/{1}_{2}_{3}".format(tmp_dir, part_index, file_name.replace('<', '').replace('>', '').replace(' ', ''), child) self._debug_print("file_path: {0}".format(file_path)) @@ -688,10 +768,21 @@ def _get_email_headers_from_part(self, part, charset=None): # Convert the header tuple into a dictionary headers = CaseInsensitiveDict() - [headers.update({x[0]: str(x[1], charset)}) for x in email_headers] + try: + [headers.update({x[0]: self._get_string(x[1], charset)}) for x in email_headers] + except Exception as e: + error_msg = _get_error_message_from_exception(e) + err = "Error occurred while converting the header tuple into a dictionary" + self._debug_print("{}. {}".format(err, error_msg)) # Handle received seperately - received_headers = [str(x[1], charset) for x in email_headers if x[0].lower() == 'received'] + received_headers = list() + try: + received_headers = [self._get_string(x[1], charset) for x in email_headers if x[0].lower() == 'received'] + except Exception as e: + error_msg = _get_error_message_from_exception(e) + err = "Error occurred while handling the received header tuple separately" + self._debug_print("{}. {}".format(err, error_msg)) if received_headers: headers['Received'] = received_headers @@ -700,7 +791,7 @@ def _get_email_headers_from_part(self, part, charset=None): subject = headers.get('Subject') if subject: if type(subject) == str: - headers['decodedSubject'] = self._decode_uni_string(subject.encode('utf8'), subject) + headers['decodedSubject'] = self._decode_uni_string(subject, subject) return headers @@ -765,6 +856,7 @@ def _parse_email_headers(self, parsed_mail, part, charset=None, add_email_id=Non artifact = {} artifact.update(_artifact_common) artifact['name'] = 'Email Artifact' + artifact['label'] = 'email' artifact['severity'] = self._base_connector.get_config().get('container_severity', 'medium') artifact['cef'] = cef_artifact artifact['cef_types'] = cef_types @@ -829,7 +921,6 @@ def _handle_mail_object(self, mail, email_id, rfc822_email, tmp_dir, start_time_ continue else: - print('else') self._parse_email_headers(self._parsed_mail, mail, add_email_id=email_id) # parsed_mail[PROC_EMAIL_JSON_EMAIL_HEADERS].append(mail.items()) file_path = "{0}/part_1.text".format(tmp_dir) @@ -940,9 +1031,11 @@ def process_email(self, rfc822_email, email_id, epoch, container_id=None, email_ try: self._parse_results(results, container_id) - except Exception: + except Exception as e: + # delete any temp directories that were created by the email parsing function self._del_tmp_dirs() - raise + self._base_connector.debug_print(_get_error_message_from_exception(e)) + return phantom.APP_ERROR, "Error occurred while parsing the results" return (phantom.APP_SUCCESS, "Email Processed") @@ -1016,9 +1109,9 @@ def _handle_save_ingested(self, artifacts, container, container_id, files): last_file = len(files) - 1 for i, curr_file in enumerate(files): - run_automation = True if i == last_file else False + run_automation = self._trigger_automation if i == last_file else False ret_val, added_to_vault = self._handle_file( - curr_file, container_id, vault_artifacts_added, run_automation + curr_file, container_id, run_automation ) if added_to_vault: @@ -1074,8 +1167,8 @@ def _parse_results(self, results, container_id=None): # if it is the last artifact of the last container if (j + 1) == len_artifacts: - # mark it such that active playbooks get executed - artifact['run_automation'] = True + # mark it such that active playbooks get executed if trigger automation is set to True + artifact['run_automation'] = self._trigger_automation cef_artifact = artifact.get('cef') if 'parentGuid' in cef_artifact: @@ -1125,7 +1218,7 @@ def _add_vault_hashes_to_dictionary(self, cef_artifact, vault_id): return (phantom.APP_SUCCESS, "Mapped hash values") - def _handle_file(self, curr_file, container_id): + def _handle_file(self, curr_file, container_id, run_automation=False): file_name = curr_file.get('file_name') @@ -1186,6 +1279,7 @@ def _handle_file(self, curr_file, container_id): artifact['container_id'] = container_id artifact['name'] = 'Vault Artifact' artifact['cef'] = cef_artifact + artifact['run_automation'] = run_automation if contains: artifact['cef_types'] = {'vaultId': contains, 'cs6': contains} self._set_sdi(artifact) @@ -1243,9 +1337,9 @@ def _create_dict_hash(self, input_dict): fips_enabled = self._base_connector._get_fips_enabled() if not fips_enabled: - return hashlib.md5(input_dict_str).hexdigest() + return hashlib.md5(UnicodeDammit(input_dict_str).unicode_markup.encode('utf-8')).hexdigest() - return hashlib.sha256(input_dict_str).hexdigest() + return hashlib.sha256(UnicodeDammit(input_dict_str).unicode_markup.encode('utf-8')).hexdigest() def _del_tmp_dirs(self): """Remove any tmp_dirs that were created.""" diff --git a/readme.html b/readme.html index 504ddb2..903c506 100644 --- a/readme.html +++ b/readme.html @@ -13,48 +13,91 @@ and limitations under the License. --> +

Playbook Backward Compatibility

+

+

    +
  • The 'id' field of email artifact has been renamed to 'messageId'. Hence, it is requested to the end-user to please update their existing + playbooks by re-inserting | modifying | deleting the corresponding action blocks to ensure the correct functioning of the playbooks created + on the earlier versions of the app.
  • +
+

+

Authentication

This app requires registration of a Microsoft Graph Application. To do so, navigate to the URL
https://portal.azure.com in a browser and log in with the Microsoft account, then, click App registrations.

On the next page, select New registration and give your app a name.

-Once the app is created, follow the below three steps: +Once the app is created, follow the below-mentioned steps:
  • Under Certificates & secrets select New client secret. Note down this key somewhere secure, as it cannot be retrieved after closing the window.
  • -
  • Under Overview select Add a redirect URI. In the Add Platform window, select Web. The Redirect URLs field will be filled in the later steps.
  • -
  • Under API Permissions the following Application Permissions need to be added: +
  • Under Authentication, select Add a platform. In the Add a platform window, select Web. The Redirect URLs should be filled right here. We will get Redirect URLs from the Phantom asset we create below in the section titled Phantom Graph Asset.
  • +
  • Under API Permissions Click on Add a permission.
  • +
  • Under the Microsoft API section, select Microsoft Graph.
  • +
  • Provide the following Application permissions to the app:
    • Mail.Read (https://graph.microsoft.com/Mail.Read)
    • Mail.ReadWrite (https://graph.microsoft.com/Mail.ReadWrite)
    • User.Read.All (https://graph.microsoft.com/User.Read.All)
      • For non-admin access, use User.Read (Delegated permission) instead (https://graph.microsoft.com/User.Read)
      -
    • Group.Read.All (https://graph.microsoft.com/Group.Read.All)- It is required only if you want to run the list events action for the group's calendar and for the list groups action
    • -
    • Calendar.Read (https://graph.microsoft.com/Calendars.Read)- It is required only if you want to run the list events action for the user's calendar
    • -
    • MailboxSettings.Read (https://graph.microsoft.com/MailboxSettings.Read)- It is required only if you want to run the oof status action
    • +
    • Group.Read.All (https://graph.microsoft.com/Group.Read.All) - It is required only if you want to run the list events action for the group's calendar and for the list groups action.
    • +
    • Calendar.Read (https://graph.microsoft.com/Calendars.Read) - It is required only if you want to run the list events action for the user's calendar.
    • +
    • MailboxSettings.Read (https://graph.microsoft.com/MailboxSettings.Read) - It is required only if you want to run the oof status action.
After making these changes, click Add permissions, then select Grant admin consent for Test Phantom at the bottom of the screen.

Phantom Graph Asset

-When creating an asset for the MS Graph for Office 365 app, place Application ID of the app created during the app registration on the Azure Portal in the Application ID field and place the client secret generated during the app registration process in the Client Secret field. Then, after filling out the Tenant field, click SAVE. Both the Application/Client ID and the Tenant ID can be found in the Overview tab on your app's Azure page. +When creating an asset for the MS Graph for Office 365 app, place Application ID of the app created during the app registration on the Azure Portal in the Application ID field and place the client secret generated during the app registration process in the Application Secret field. Then, after filling out the Tenant field, click SAVE. Both the Application/Client ID and the Tenant ID can be found in the Overview tab on your app's Azure page.

-After saving, a new field will appear in the Asset Settings tab. Take the URL found in the POST incoming for MS Graph for Office 365 to this location field and place it in the Redirect URLs field mentioned in a previous step. To this URL, add /result. After doing so the URL should look something like: +After saving, a new field will appear in the Asset Settings tab. Take the URL found in the POST incoming for MS Graph for Office 365 to this location field and place it in the Redirect URLs field mentioned in the previous step. To this URL, add /result. After doing so the URL should look something like:

-
+

https://<phantom_host>/rest/handler/msgraphforoffice365_0a0a4087-10e8-4c96-9872-b740ff26d8bb/<asset_name>/result -

-
-Once again, click save at the bottom of the screen. +


+Once again, click SAVE at the bottom of the screen. +

+Additionally, updating the Base URL in the Company Settings is also required. Navigate to Administration > Company Settings > Info to configure the Base URL For Splunk SOAR. Then, select Save Changes. +

+

User Permissions

-To complete the authorization process, this app needs permission to view assets, which is not granted by default. First, under asset settings, check which user has listed under Select a user on behalf of which automated actions can be executed. By default, the user will be automation, but this user can be changed by clicking EDIT at the bottom of the window. To give this user permission to view assets, follow these steps: +To complete the authorization process, this app needs permission to view assets, which is not granted by default. First, navigate to Asset Settings > Advanced, to check which user is listed under Select a user on behalf of which automated actions can be executed. By default, the user will be automation, but this user can be changed by clicking EDIT at the bottom of the window. To give this user permission to view assets, follow these steps:
    -
  • In the main drop-down menu, select Administration, then select the User Management, and under that tab, select Roles. Finally, click + ROLE.
  • -
  • In the Add Role wizard, give the role a name (e.g Asset Viewer), and provide a description. Subsequently, under Available Users, add the user assigned to the asset viewed earlier. Then click the Permissions tab.
  • -
  • On the permission tab, under Available Privileges, give the role the View Assets privilege. Then click SAVE.
  • +
  • In the main drop-down menu, select Administration, then select the User Management, and under that tab, select Roles & Permissions. Finally, click + ROLE.
  • +
  • In the Add Role wizard, give the role a name (e.g Asset Viewer), and provide a description. Subsequently, under the Users tab, click ADD USERS to add the user assigned to the asset viewed earlier. Then click the Permissions tab.
  • +
  • In the permission tab, under Basic Permissions, give the role the View Assets privilege. Then click SAVE.
+

Test connectivity

-After setting up the asset and user, click the TEST CONNECTIVITY button. A window should pop up and display a URL. Navigate to this URL in a separate browser tab. This new tab will redirect to a Microsoft login page. Log in to a Microsoft account with administrator privileges to the desired mailboxes. After logging in, review the requested permissions listed, then click Accept. Finally, close that tab. The test connectivity window should show success. + +

Admin User Workflow

+
    +
  • Configure the asset with required details while keeping the Admin Access Required as checked.
  • +
  • While configuring the asset for the first time, keep Admin Consent Already Provided as unchecked.
  • +
  • The Redirect URLs must be configured before executing test connectivity. To configure Redirect URLs, checkout the section titled Phantom Graph Asset above.
  • +
  • After setting up the asset and user, click the TEST CONNECTIVITY button.
  • +
  • A window should pop up and display a URL. You will be asked to open the link in a new tab. Open the link in the same browser so that you are logged into Splunk Phantom for the redirect. If you wish to use a different browser, log in to the Splunk Phantom first, and then open the provided link. This new tab will redirect to the Microsoft login page.
  • +
  • Log in to the Microsoft account with the admin user.
  • +
  • You will be prompted to agree to the permissions requested by the App.
  • +
  • Review the requested permissions listed, then click Accept.
  • +
  • If all goes well the browser should instruct you to close the tab.
  • +
  • Now go back and check the message on the Test Connectivity dialog box, it should say Test Connectivity Passed.
  • +
  • For subsequent test connectivity or action runs, you can keep Admin Consent Already Provided config parameter as checked. This will skip the interactive flow and use the client credentials for generating tokens. +
+ +

Non-Admin User Workflow

+
    +
  • Configure the asset with required details while keeping the Admin Access Required as unchecked. Admin Consent Already Provided config parameter will be ignored in the non-admin workflow.
  • +
  • Provide Access Scope parameter in the asset configuration. All the actions will get executed according to the scopes provided in the Access Scope config parameter.
  • +
  • The Redirect URLs must be configured before executing test connectivity. To configure Redirect URLs, checkout the section titled Phantom Graph Asset above.
  • +
  • After setting up the asset and user, click the TEST CONNECTIVITY button.
  • +
  • A window should pop up and display a URL. You will be asked to open the link in a new tab. Open the link in the same browser so that you are logged into Splunk Phantom for the redirect. If you wish to use a different browser, log in to the Splunk Phantom first, and then open the provided link. This new tab will redirect to the Microsoft login page.
  • +
  • Log in to the Microsoft account.
  • +
  • You will be prompted to agree to the permissions requested by the App.
  • +
  • Review the requested permissions listed, then click Accept.
  • +
  • If all goes well the browser should instruct you to close the tab.
  • +
  • Now go back and check the message on the Test Connectivity dialog box, it should say Test Connectivity Passed.
  • +


The app should now be ready to be used.
@@ -63,6 +106,7 @@

On-Poll

  • email_address - Ingest from the provided email address.
  • folder - To fetch the emails from the given folder name (must be provided if running ingestion)
  • +
  • get_folder_id - Retrieve the folder ID for the provided folder name/folder path automatically and replace the folder parameter value.
  • first_run_max_emails - Maximum containers to poll for the first scheduled polling (default - 1000).
  • max_containers - Maximum containers to poll after the first scheduled poll completes (default - 100).
  • extract_attachments - Extract all the attachments included in emails.
  • @@ -71,6 +115,24 @@

    On-Poll

  • extract_domains - Extract the domain names present in the emails.
  • extract_hashes - Extract the hashes present in the emails (MD5).
+ +

Guidelines to provide folder parameter value

+

This is applicable to 'on poll', 'copy email', 'move email', and 'run query' actions.

+
    +
  • + The get_folder_id parameter should be enabled only when you have 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 (https://docs.microsoft.com/en-us/graph/api/resources/mailfolder?view=graph-rest-1.0) or the internal o365 folder ID. +
  • +
  • + The folder parameter supports nested folder paths. To specify the complete folder path using the '/' (forward slash) as the separator.
    e.g. to specify 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. +
  • +
+

State file permissions

Please check the permissions for the state file as mentioned below. @@ -95,3 +157,25 @@

Note

  • There is an API limitation that will affect run_query action when providing Unicode values in the subject or in the body as parameters and if the result count exceeds 999, the action will fail.
  • + +

    Port Details

    +

    + The app uses HTTP/ HTTPS protocol for communicating with the Office365 server. Below are the default ports used by the Splunk SOAR Connector. + + + + + + + + + + + + + + + + +
    Service NameTransport ProtocolPort
    httptcp80
    httpstcp443
    +

    diff --git a/release_notes/2.5.0.md b/release_notes/2.5.0.md new file mode 100644 index 0000000..116e72a --- /dev/null +++ b/release_notes/2.5.0.md @@ -0,0 +1,12 @@ +* Added paginator in On Poll Action [PAPP-24562] +* Fixed a bug in the 'folder' config parameter [PAPP-24524] +* Added a new config parameter 'get_folder_id' to support folder name as well as folder_id in the 'folder' config parameter [PAPP-24565] +* Added validation for the extraction of URL artifacts [PAPP-24517] +* Fixed a bug for the extraction of the URL value from the image src attribute [PAPP-24801] +* Added deduplication logic for handling duplicate emails while ingestion [PAPP-24525] +* Fixed an issue for hash extraction while ingesting email [PAPP-25014] +* Added ability to configure ingestion order [PAPP-24564] +* Bug Fixes in On Poll Action [PAPP-25012, PAPP-25013, PAPP-25015, PAPP-25016, PAPP-24561, PAPP-24563, PAPP-25084, PAPP-25295] +* Fixed On Poll issue where playbooks were triggered twice when an email was an attachment [PAPP-25011] +* Updated app documentation [PAPP-24248] +* Compatibility changes for Python 3 support \ No newline at end of file diff --git a/release_notes/release_notes.html b/release_notes/release_notes.html index d0cac06..a208c52 100644 --- a/release_notes/release_notes.html +++ b/release_notes/release_notes.html @@ -1,5 +1,20 @@ -MS Graph for Office 365 Release Notes - Published by Splunk February 14, 2022 +MS Graph for Office 365 Release Notes - Published by Splunk April 19, 2022

    +Version 2.5.0 - Released April 19, 2022 +
      +
    • Added paginator in On Poll Action [PAPP-24562]
    • +
    • Fixed a bug in the 'folder' config parameter [PAPP-24524]
    • +
    • Added a new config parameter 'get_folder_id' to support folder name as well as folder_id in the 'folder' config parameter [PAPP-24565]
    • +
    • Added validation for the extraction of URL artifacts [PAPP-24517]
    • +
    • Fixed a bug for the extraction of the URL value from the image src attribute [PAPP-24801]
    • +
    • Added deduplication logic for handling duplicate emails while ingestion [PAPP-24525]
    • +
    • Fixed an issue for hash extraction while ingesting email [PAPP-25014]
    • +
    • Added ability to configure ingestion order [PAPP-24564]
    • +
    • Bug Fixes in On Poll Action [PAPP-25012, PAPP-25013, PAPP-25015, PAPP-25016, PAPP-24561, PAPP-24563, PAPP-25084, PAPP-25295]
    • +
    • Fixed On Poll issue where playbooks were triggered twice when an email was an attachment [PAPP-25011]
    • +
    • Updated app documentation [PAPP-24248]
    • +
    • Compatibility changes for Python 3 support
    • +
    Version 2.4.14 - Released February 11, 2022
    • Added support for Python 3.9
    • diff --git a/requirements.txt b/requirements.txt index bd1d2f1..b99eb71 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ beautifulsoup4==4.9.1 -Django==3.2.12 +Django==3.2.13 python-magic==0.4.18 requests==2.25.0 diff --git a/tox.ini b/tox.ini index 127a08b..c4644ad 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [flake8] max-line-length = 145 max-complexity = 28 -ignore = F403,E128,E126,E111,E121,E127,E731,E201,E202,F405,E722,D,W292 +extend-ignore = F403,E128,E126,E111,E121,E127,E731,E201,E202,F405,E722,D,W292 [isort] line_length = 145 diff --git a/wheels/py3/Django-3.2.12-py3-none-any.whl b/wheels/py3/Django-3.2.13-py3-none-any.whl similarity index 94% rename from wheels/py3/Django-3.2.12-py3-none-any.whl rename to wheels/py3/Django-3.2.13-py3-none-any.whl index 8e93add..7b386cc 100644 Binary files a/wheels/py3/Django-3.2.12-py3-none-any.whl and b/wheels/py3/Django-3.2.13-py3-none-any.whl differ diff --git a/wheels/py3/soupsieve-2.3.1-py3-none-any.whl b/wheels/py3/soupsieve-2.3.1-py3-none-any.whl deleted file mode 100644 index 85d33de..0000000 Binary files a/wheels/py3/soupsieve-2.3.1-py3-none-any.whl and /dev/null differ diff --git a/wheels/py3/soupsieve-2.3.2-py3-none-any.whl b/wheels/py3/soupsieve-2.3.2-py3-none-any.whl new file mode 100644 index 0000000..0eefa9e Binary files /dev/null and b/wheels/py3/soupsieve-2.3.2-py3-none-any.whl differ diff --git a/wheels/py3/typing_extensions-4.0.1-py3-none-any.whl b/wheels/py3/typing_extensions-4.0.1-py3-none-any.whl deleted file mode 100644 index 65500a1..0000000 Binary files a/wheels/py3/typing_extensions-4.0.1-py3-none-any.whl and /dev/null differ diff --git a/wheels/py3/typing_extensions-4.1.1-py3-none-any.whl b/wheels/py3/typing_extensions-4.1.1-py3-none-any.whl new file mode 100644 index 0000000..73c3dce Binary files /dev/null and b/wheels/py3/typing_extensions-4.1.1-py3-none-any.whl differ diff --git a/wheels/shared/pytz-2021.3-py2.py3-none-any.whl b/wheels/shared/pytz-2022.1-py2.py3-none-any.whl similarity index 69% rename from wheels/shared/pytz-2021.3-py2.py3-none-any.whl rename to wheels/shared/pytz-2022.1-py2.py3-none-any.whl index 36a7ea3..a0f6378 100644 Binary files a/wheels/shared/pytz-2021.3-py2.py3-none-any.whl and b/wheels/shared/pytz-2022.1-py2.py3-none-any.whl differ diff --git a/wheels/shared/urllib3-1.26.8-py2.py3-none-any.whl b/wheels/shared/urllib3-1.26.9-py2.py3-none-any.whl similarity index 68% rename from wheels/shared/urllib3-1.26.8-py2.py3-none-any.whl rename to wheels/shared/urllib3-1.26.9-py2.py3-none-any.whl index bad52ab..5019453 100644 Binary files a/wheels/shared/urllib3-1.26.8-py2.py3-none-any.whl and b/wheels/shared/urllib3-1.26.9-py2.py3-none-any.whl differ