Repository: demisto/content
Pull request #39741: Add Lookback
Author: login: aaron1535
Labels: name: ForceMerge
description: Forcing the merge of the PR despite the build status
name: ready-for-pipeline-running
description: Whether the pr is ready for running the whole pipeline, including testing on SAAS machines
Created: 2025-04-27T20:23:06Z | Merged: 2025-04-29T07:04:24Z


fixes: [link to the issue](https://jira-dc.paloaltonetworks.com/browse/XSUP-48656)




Diff:
diff --git a/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py b/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py
index cde295b2d141..a75c4a7e4dd5 100644
--- a/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py
+++ b/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py
@@ -42,6 +42,7 @@
 AUTH_CODE = params.get("auth_code_creds", {}).get("password") or params.get("code")
 AUTH_CODE_UNQUOTE_PREFIX = "code="
 LEGACY_NAME = argToBoolean(params.get("legacy_name", False))
+LOOK_BACK_IN_MINUTES = 1
 
 OOB_CLIENT_ID = "391797357217-pa6jda1554dbmlt3hbji2bivphl0j616.apps.googleusercontent.com"  # guardrails-disable-line
 CLIENT_ID = params.get("credentials", {}).get("identifier") or params.get("client_id") or OOB_CLIENT_ID
@@ -1174,10 +1175,9 @@ def get_attachments_command(client: Client):
 
 """FETCH INCIDENTS"""
 
-
 def fetch_incidents(client: Client):
     user_key = "me"
-    query = "" if params["query"] is None else params["query"]
+    query = "" if params.get("query") is None else params.get("query")
     last_run = demisto.getLastRun()
     demisto.debug(f"last run: {last_run}")
     last_fetch = last_run.get("gmt_time")
@@ -1185,6 +1185,7 @@ def fetch_incidents(client: Client):
     page_token = last_run.get("page_token")
     ignore_ids: list[str] = last_run.get("ignore_ids") or []
     ignore_list_used = last_run.get("ignore_list_used") or False  # can we reset the ignore list if we haven't used it
+    lookback_ids_and_dates: list[tuple[str, str]] = last_run.get("lookback_msg", [])
     # handle first time fetch - gets current GMT time -1 day
     if not last_fetch:
         last_fetch, _ = parse_date_range(date_range=FETCH_TIME, utc=True, to_timestamp=False)
@@ -1211,14 +1212,18 @@ def fetch_incidents(client: Client):
     result = execute_gmail_action(service, "list", list_command_args)
 
     incidents = []
+    emails_ids_and_dates: list[tuple] = []
     # so far, so good
     demisto.debug(f"GMAIL: possible new incidents are {result}")
+    lookback_ids = [msg_id for msg_id, _ in lookback_ids_and_dates]
     for msg in result.get("messages", []):
         msg_id = msg["id"]
         if msg_id in ignore_ids:
             demisto.info(f"Ignoring msg id: {msg_id} as it is in the ignore list")
             ignore_list_used = True
             continue
+        if msg_id in lookback_ids:
+            continue
         command_kwargs = {"userId": user_key, "id": msg_id}
         msg_result = execute_gmail_action(service, "get", command_kwargs)
         incident, occurred, is_valid_date = client.mail_to_incident(msg_result, service, user_key)
@@ -1226,6 +1231,9 @@ def fetch_incidents(client: Client):
             demisto.info(f'appending to ignore list msg id: {msg_id}. name: {incident.get("name")}')
             ignore_list_used = True
             ignore_ids.append(msg_id)
+        else:
+            #save new msg date for lookback
+            emails_ids_and_dates.append((msg_id, occurred))
         # update last run only if we trust the occurred timestamp
         if is_valid_date and occurred > next_last_fetch:
             next_last_fetch = occurred + timedelta(seconds=1)
@@ -1238,6 +1246,7 @@ def fetch_incidents(client: Client):
 
     demisto.info(f"extracted {len(incidents)} incidents")
     next_page_token = result.get("nextPageToken", "")
+    msg_to_exclude_in_next_fetch = []
     if next_page_token:
         # we still have more results
         demisto.info(
@@ -1245,21 +1254,32 @@ def fetch_incidents(client: Client):
             f" token: {next_page_token}. Ignoring incremented last_fatch: {next_last_fetch}"
         )
     else:
-        demisto.debug(f"will use new last fetch date (no next page token): {next_last_fetch}")
         # if we are not in a tokenized search and we didn't use the ignore ids we can reset it
         if (not page_token) and (not ignore_list_used) and (len(ignore_ids) > 0):
             demisto.info(f"resetting ignore list of len: {len(ignore_ids)}")
             ignore_ids = []
+        demisto.debug(f"will use new last fetch date (no next page token): {next_last_fetch}")
         last_fetch = next_last_fetch
-    demisto.setLastRun(
-        {
-            "gmt_time": client.get_date_isoformat_server(last_fetch),
-            "next_gmt_time": client.get_date_isoformat_server(next_last_fetch),
-            "page_token": next_page_token,
-            "ignore_ids": ignore_ids,
-            "ignore_list_used": ignore_list_used,
-        }
-    )
+    if emails_ids_and_dates:
+        # Editing the next fetch one minute back to look back. And adding the ids from the last minute to avoid duplicates
+        latest_msg = max([parse_date(client, msg_date, "date")
+                            for _, msg_date in emails_ids_and_dates + lookback_ids_and_dates])
+        lookback_date = latest_msg - timedelta(minutes=LOOK_BACK_IN_MINUTES)  # type: ignore
+        msg_to_exclude_in_next_fetch = [
+            (msg_id, parse_date(client, msg_date))
+            for msg_id, msg_date in emails_ids_and_dates + lookback_ids_and_dates
+            if parse_date(client, msg_date, "date") >= lookback_date  # type: ignore
+        ]
+    new_last_run = {
+        "gmt_time": client.get_date_isoformat_server(last_fetch),
+        "next_gmt_time": client.get_date_isoformat_server(next_last_fetch),
+        "page_token": next_page_token,
+        "ignore_ids": ignore_ids,
+        "ignore_list_used": ignore_list_used,
+        "lookback_msg": msg_to_exclude_in_next_fetch or lookback_ids_and_dates or [],
+    }
+    demisto.debug(f"Gmail: save the following details to LastRun: {new_last_run}")
+    demisto.setLastRun(new_last_run)
     return incidents
 
 
diff --git a/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser_test.py b/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser_test.py
index 43785e0e4d7a..031bb1eb7ab0 100644
--- a/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser_test.py
+++ b/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser_test.py
@@ -606,3 +606,69 @@ def test_get_unix_date(input_args, expected):
     from GmailSingleUser import get_unix_date
     assert get_unix_date(input_args) == expected
 
+
+def test_fetch_incidents_set_last_run_called_correctly(mocker):
+    """
+    Test the `fetch_incidents` function to ensure it correctly updates the 'setLastRun' after fetching incidents.
+
+    Given:
+    - A GmailSingleUser client with a mocked Gmail service and necessary method patches.
+    - A patch on 'GmailSingleUser.execute_gmail_action' to simulate Gmail API responses for 'list' and 'get' actions based on the fetch count.
+    - Initial 'getLastRun' returning a specific datetime indicating the last run time.
+    - An external file 'test_data/a.json' to simulate fetched email details.
+
+    When:
+    - The `fetch_incidents` function is called twice, first with an initial fetch count of 0, then incremented to simulate a subsequent fetch.
+
+    Then:
+    - The function should update 'setLastRun' correctly after each call:
+      - After the first call, 'setLastRun' should contain exactly two messages with IDs '1' and '3'.
+      - After the second call, 'setLastRun' should contain exactly three messages with IDs '1', '2', and '3', reflecting the updated fetch.
+      - The 'lookback_msg' field in the data sent to 'setLastRun' should reflect the correct IDs of the messages fetched in each incident fetch.
+    """  # noqa: E501
+    from GmailSingleUser import fetch_incidents
+    import GmailSingleUser
+    gmail_single_user_client = Client()
+    # Mock the chain of calls: service.users().messages().send().execute()
+    mock_execute = mocker.Mock(return_value={"id": "mock_message_id"})
+    mock_send = mocker.Mock(return_value=mock_execute)
+    mock_messages = mocker.Mock(send=mocker.Mock(return_value=mock_send))
+    mock_users = mocker.Mock(messages=mocker.Mock(return_value=mock_messages))
+    mock_service = mocker.Mock(users=mocker.Mock(return_value=mock_users))
+    # Patch the service object in the Client class to use the mocked service
+    mocker.patch.object(GmailSingleUser.Client, "get_service", new=mock_service)
+    fetch_count = 0
+
+    def execute_gmail_action_side_effect(service, action, args):
+        nonlocal fetch_count
+        if action == "list":
+            if fetch_count == 0:
+                return {'messages': [{'id': '1'}, {'id': '3'}]}
+            return {'messages': [{'id': '1'}, {'id': '2'}, {'id': '3'}]}
+        elif action == "get":
+            message_id = args.get("id")
+            for item in util_load_json("test_data/lookback_emails.json"):
+                if item.get("id") == message_id:
+                    return item
+        return {}
+
+    # Mocking external functions and globals
+    mocker.patch('GmailSingleUser.execute_gmail_action', side_effect=execute_gmail_action_side_effect)
+    mocker.patch('GmailSingleUser.demisto.getLastRun', return_value={"gmt_time": "2025-02-24T15:17:05Z"})
+    mock_set_last_run = mocker.patch('GmailSingleUser.demisto.setLastRun')
+
+    fetch_incidents(gmail_single_user_client)
+
+    last_args = mock_set_last_run.call_args[0][0]
+    assert len(last_args['lookback_msg']) == 2, "lookback_msg does not contain exactly three messages in the first fetch"
+
+    fetch_count += 1
+    fetch_incidents(gmail_single_user_client)
+
+    # Check the last arguments sent to setLastRun
+    last_args = mock_set_last_run.call_args[0][0]
+
+    # Assert the lookback_msg contains the correct messages
+    assert 'lookback_msg' in last_args, "lookback_msg key is missing in the arguments sent to setLastRun"
+    assert len(last_args['lookback_msg']) == 3, "lookback_msg does not contain exactly three messages in the secund fetch"
+    assert [id for id, _ in last_args['lookback_msg']] == ["1", "2", "3"], "lookback_msg do"
diff --git a/Packs/GmailSingleUser/ReleaseNotes/1_4_13.md b/Packs/GmailSingleUser/ReleaseNotes/1_4_13.md
new file mode 100644
index 000000000000..35a605c780a6
--- /dev/null
+++ b/Packs/GmailSingleUser/ReleaseNotes/1_4_13.md
@@ -0,0 +1,6 @@
+
+#### Integrations
+
+##### Gmail Single User
+
+- Fixed an issue where emails arriving up to one minute late were missed during the ***fetch-incidents*** command. We now use the look-back mechanism to ensure all such emails are included.
\ No newline at end of file
diff --git a/Packs/GmailSingleUser/pack_metadata.json b/Packs/GmailSingleUser/pack_metadata.json
index 6c95dba77e57..d30971cbf0d6 100644
--- a/Packs/GmailSingleUser/pack_metadata.json
+++ b/Packs/GmailSingleUser/pack_metadata.json
@@ -2,7 +2,7 @@
     "name": "Gmail Single User",
     "description": "Gmail API using OAuth 2.0.",
     "support": "xsoar",
-    "currentVersion": "1.4.12",
+    "currentVersion": "1.4.13",
     "author": "Cortex XSOAR",
     "url": "https://www.paloaltonetworks.com/cortex",
     "email": "",


Reviews:
user: login: AradCarmi
body: Nice work! 
Please fully test this before merging to prevent more issues and fix my notes.
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T11:30:20Z
user: login: aaron1535
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T13:15:25Z
user: login: AradCarmi
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T13:27:55Z

Review comments:
diff_hunk: @@ -1238,28 +1246,46 @@ def fetch_incidents(client: Client):
 
     demisto.info(f"extracted {len(incidents)} incidents")
     next_page_token = result.get("nextPageToken", "")
+    msg_to_exclude_in_next_fetch = []
     if next_page_token:
         # we still have more results
         demisto.info(
             f"keeping current last fetch: {last_fetch} as result has additional pages to fetch."
             f" token: {next_page_token}. Ignoring incremented last_fatch: {next_last_fetch}"
         )
+        lookback_date = parse_date(client, next_last_fetch, "date") - timedelta(minutes=LOOK_BACK_IN_MINUTES)  # type: ignore
+        msg_to_exclude_in_next_fetch = [
+                (msg_id, parse_date(client, msg_date))
+                for msg_id, msg_date in emails_ids_and_dates + lookback_ids_and_dates
+                if parse_date(client, msg_date, "date") >= lookback_date  # type: ignore
+            ]
     else:
-        demisto.debug(f"will use new last fetch date (no next page token): {next_last_fetch}")
         # if we are not in a tokenized search and we didn't use the ignore ids we can reset it
         if (not page_token) and (not ignore_list_used) and (len(ignore_ids) > 0):
             demisto.info(f"resetting ignore list of len: {len(ignore_ids)}")
             ignore_ids = []
+        if emails_ids_and_dates:
+            # Editing the next fetch one minute back to look back. And adding the ids from the last minute to avoid duplicates
+            latest_msg = max([parse_date(client, msg_date, "date")
+                             for _, msg_date in emails_ids_and_dates + lookback_ids_and_dates])
+            next_last_fetch = latest_msg - timedelta(minutes=LOOK_BACK_IN_MINUTES)  # type: ignore
+            msg_to_exclude_in_next_fetch = [
+                (msg_id, parse_date(client, msg_date))
+                for msg_id, msg_date in emails_ids_and_dates + lookback_ids_and_dates
+                if parse_date(client, msg_date, "date") >= next_last_fetch  # type: ignore
+            ]
path: Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py
user: login: AradCarmi
body: Why do you not move it outside the if/else scope instead of duplicating?

created_at: 2025-04-28T11:26:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,6 @@
+
+#### Integrations
+
+##### Gmail Single User
+
+- Fixed an issue where emails that arrived up to one minute late were missed during fetch. The fetch process now accounts for slight delays and ensures such emails are included.
path: Packs/GmailSingleUser/ReleaseNotes/1_4_13.md
user: login: AradCarmi
body: ```suggestion
Fixed an issue where emails arriving up to one minute late were missed during the ***fetch-incidents*** command. We now use the look-back mechanism to ensure all such emails are included.
```
created_at: 2025-04-28T11:29:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1238,28 +1246,46 @@ def fetch_incidents(client: Client):
 
     demisto.info(f"extracted {len(incidents)} incidents")
     next_page_token = result.get("nextPageToken", "")
+    msg_to_exclude_in_next_fetch = []
     if next_page_token:
         # we still have more results
         demisto.info(
             f"keeping current last fetch: {last_fetch} as result has additional pages to fetch."
             f" token: {next_page_token}. Ignoring incremented last_fatch: {next_last_fetch}"
         )
+        lookback_date = parse_date(client, next_last_fetch, "date") - timedelta(minutes=LOOK_BACK_IN_MINUTES)  # type: ignore
+        msg_to_exclude_in_next_fetch = [
+                (msg_id, parse_date(client, msg_date))
+                for msg_id, msg_date in emails_ids_and_dates + lookback_ids_and_dates
+                if parse_date(client, msg_date, "date") >= lookback_date  # type: ignore
+            ]
     else:
-        demisto.debug(f"will use new last fetch date (no next page token): {next_last_fetch}")
         # if we are not in a tokenized search and we didn't use the ignore ids we can reset it
         if (not page_token) and (not ignore_list_used) and (len(ignore_ids) > 0):
             demisto.info(f"resetting ignore list of len: {len(ignore_ids)}")
             ignore_ids = []
+        if emails_ids_and_dates:
+            # Editing the next fetch one minute back to look back. And adding the ids from the last minute to avoid duplicates
+            latest_msg = max([parse_date(client, msg_date, "date")
+                             for _, msg_date in emails_ids_and_dates + lookback_ids_and_dates])
+            next_last_fetch = latest_msg - timedelta(minutes=LOOK_BACK_IN_MINUTES)  # type: ignore
+            msg_to_exclude_in_next_fetch = [
+                (msg_id, parse_date(client, msg_date))
+                for msg_id, msg_date in emails_ids_and_dates + lookback_ids_and_dates
+                if parse_date(client, msg_date, "date") >= next_last_fetch  # type: ignore
+            ]
path: Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py
user: login: aaron1535
body: Move it Out
created_at: 2025-04-28T13:15:23Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-04-27T20:28:34Z
body: <!-- Pytest Coverage Comment: pre-commit -->
<a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/README.md"><img alt="Coverage" src="https://img.shields.io/badge/Coverage-56%25-orange.svg" /></a><details><summary>Coverage Report </summary><table><tr><th>File</th><th>Stmts</th><th>Miss</th><th>Cover</th><th>Missing</th></tr><tbody><tr><td colspan="5"><b>Packs/GmailSingleUser/Integrations/GmailSingleUser</b></td></tr><tr><td>&nbsp; &nbsp;<a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py">GmailSingleUser.py</a></td><td>750</td><td>324</td><td>56%</td><td><a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L97-L100">97&ndash;100</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L102-L103">102&ndash;103</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L112-L113">112&ndash;113</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L115">115</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L123">123</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L126">126</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L131-L133">131&ndash;133</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L136-L139">136&ndash;139</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L142-L143">142&ndash;143</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L146-L149">146&ndash;149</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L152-L155">152&ndash;155</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L158-L159">158&ndash;159</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L162-L164">162&ndash;164</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L166-L167">166&ndash;167</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L170">170</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L175-L181">175&ndash;181</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L184-L190">184&ndash;190</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L197">197</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L200-L205">200&ndash;205</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L210-L222">210&ndash;222</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L227">227</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L229-L233">229&ndash;233</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L235-L236">235&ndash;236</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L238-L241">238&ndash;241</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L244-L247">244&ndash;247</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L250-L258">250&ndash;258</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L263-L266">263&ndash;266</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L268-L275">268&ndash;275</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L277-L282">277&ndash;282</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L284-L291">284&ndash;291</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L332">332</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L337-L339">337&ndash;339</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L341">341</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L345-L351">345&ndash;351</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L366">366</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L391">391</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L416-L417">416&ndash;417</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L487-L490">487&ndash;490</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L570-L572">570&ndash;572</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L575">575</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L578-L580">578&ndash;580</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L582">582</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L640-L642">640&ndash;642</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L662">662</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L672-L673">672&ndash;673</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L675">675</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L684-L686">684&ndash;686</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L690">690</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L693">693</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L699-L700">699&ndash;700</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L708-L709">708&ndash;709</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L724-L725">724&ndash;725</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L727-L728">727&ndash;728</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L731-L733">731&ndash;733</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L735-L736">735&ndash;736</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L738">738</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L747-L748">747&ndash;748</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L750-L751">750&ndash;751</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L753-L756">753&ndash;756</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L758-L760">758&ndash;760</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L762">762</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L764">764</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L768">768</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L804-L808">804&ndash;808</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L810-L813">810&ndash;813</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L815-L817">815&ndash;817</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L819">819</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L823-L824">823&ndash;824</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L829">829</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L831-L835">831&ndash;835</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L837-L839">837&ndash;839</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L841-L843">841&ndash;843</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L856-L860">856&ndash;860</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L863">863</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L865-L867">865&ndash;867</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L869">869</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L871-L874">871&ndash;874</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L877">877</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L885-L889">885&ndash;889</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L892-L893">892&ndash;893</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L895-L901">895&ndash;901</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L903-L904">903&ndash;904</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L906-L910">906&ndash;910</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L913-L914">913&ndash;914</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L916-L920">916&ndash;920</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L922-L923">922&ndash;923</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L926-L930">926&ndash;930</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L933-L934">933&ndash;934</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L961-L962">961&ndash;962</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L964-L965">964&ndash;965</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L979-L982">979&ndash;982</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1012">1012</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1016-L1018">1016&ndash;1018</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1028-L1030">1028&ndash;1030</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1064">1064</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1079">1079</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1081">1081</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1094">1094</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1146">1146</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1148">1148</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1158-L1162">1158&ndash;1162</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1164">1164</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1168-L1169">1168&ndash;1169</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1171">1171</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1173">1173</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1191-L1192">1191&ndash;1192</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1196">1196</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1206">1206</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1222-L1224">1222&ndash;1224</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1226">1226</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1231-L1233">1231&ndash;1233</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1245">1245</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1252">1252</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1259-L1260">1259&ndash;1260</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1308-L1309">1308&ndash;1309</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1318">1318</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1328-L1329">1328&ndash;1329</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1396-L1397">1396&ndash;1397</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1401-L1402">1401&ndash;1402</a>, <a href="https://github.com/demisto/content/blob/b0d82b615b9e194061655a284e91a5112f22db3f/Packs/GmailSingleUser/Integrations/GmailSingleUser/GmailSingleUser.py#L1469">1469</a></td></tr><tr><td><b>TOTAL</b></td><td><b>750</b></td><td><b>324</b></td><td><b>56%</b></td><td>&nbsp;</td></tr></tbody></table></details>

| Tests | Skipped | Failures | Errors | Time |
| ----- | ------- | -------- | -------- | ------------------ |
| 32 | 0 :zzz: | 0 :x: | 0 :fire: | 3.704s :stopwatch: |

author_association: NONE
user: login: content-bot
created_at: 2025-04-28T13:31:44Z
body: Validate summary

Verdict: PR can be force merged from validate perspective? ✅
author_association: CONTRIBUTOR
user: login: aaron1535
created_at: 2025-04-28T15:47:56Z
body: `Force Marge` is requested because the test playbook `Gmail Single User - Test` falls on 
```
"error": "invalid_grant" "error_description": "Bad Request"
```
 Because **manual** two-step verification is required in the integration instance configuration.
 approved by @AradCarmi 
author_association: CONTRIBUTOR