CiscoSMA

The Security Management Appliance (SMA) is used to centralize services from Email Security Appliances (ESAs) and Web Security Appliances (WSAs).

Email · CiscoSMA

Details

IDCiscoSMA
ProviderCisco Systems
CategoryEmail
From Version6.2.0
Docker Imagedemisto/python3:3.12.13.10325753
Supported ModulesAgentix XSIAM EDR Cortex Cloud Cloud Runtime Security

README

The Security Management Appliance (SMA) is used to centralize services from Email Security Appliances (ESAs) and Web Security Appliances (WSAs).
This integration was integrated and tested with version 12.0 of Cisco Security Management Appliance.

Configure Cisco Security Management Appliance in Cortex

Parameter Description Required
Server URL Base URL, e.g., https://XXX.eu.iphmx.com True
Username   True
Password   True
Maximum incidents per fetch Default is 50. Maximum is 100. False
First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days). Timestamp in ISO format or &lt;number&gt; &lt;time unit&gt;,
e.g., 2022-01-01T00:00:00.000Z, 12 hours, 7 days, 3 months, now.
False
Filter by Message field by which to filter the results. False
Filter operator Operator on the message field. False
Filter value The value to search for. False
Recipient filter operator Recipient operator filter. False
Recipient filter value Recipient filter value to fetch by message field. False
Timeout HTTP requests timeout in seconds. The default is 60 seconds. False
Use system proxy settings   False
Trust any certificate (not secure)   False
Incident type   False
Fetch incidents   False

Commands

You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

cisco-sma-spam-quarantine-message-search


Search messages in the spam quarantine.

Base Command

cisco-sma-spam-quarantine-message-search

Input

Argument Name Description Required
start_date Start date in ISO format or <number> <time unit>,
e.g., 2022-01-01T00:00:00.000Z, 12 hours, 7 days, 3 months, now.
Required
end_date End date in ISO format or <number> <time unit>,
e.g., 2022-01-01T00:00:00.000Z, 12 hours, 7 days, 3 months, now.
Required
filter_by Field by which to filter the results. Possible values are: from_address, to_address, subject. Optional
filter_operator Filter operator. Possible values are: contains, is, begins_with, ends_with, does_not_contain. Optional
filter_value The value to search for. This is a user defined value, e.g., filterValue=abc.com. Optional
recipient_filter_operator Recipient operator filter. Possible values are: contains, is, begins_with, ends_with, does_not_contain. Optional
recipient_filter_value Recipient filter value. Optional
order_by How the results should be ordered. Possible values are: from_address, date, subject, size. Optional
order_dir Direction in which the results should be ordered. Possible values are: asc, desc. Optional
page Page number of paginated results.
Minimum value is 1.
Optional
page_size Number of results per page. Maximum value is 100. Optional
limit The maximum number of records to retrieve. Default is 50. Optional

Context Output

Path Type Description
CiscoSMA.SpamQuarantineMessage.envelopeRecipient String Message recipient.
CiscoSMA.SpamQuarantineMessage.toAddress String Message recipient.
CiscoSMA.SpamQuarantineMessage.subject String Message subject.
CiscoSMA.SpamQuarantineMessage.date String Message date.
CiscoSMA.SpamQuarantineMessage.fromAddress String Message sender.
CiscoSMA.SpamQuarantineMessage.size String Message size.
CiscoSMA.SpamQuarantineMessage.mid Number Message ID.

Command example

!cisco-sma-spam-quarantine-message-search start_date=2weeks end_date=now page=3 page_size=2

Context Example

{
    "CiscoSMA": {
        "SpamQuarantineMessage": [
            {
                "date": "11 Sep 2022 07:55 (GMT)",
                "envelopeRecipient": [
                    "test@test.com"
                ],
                "fromAddress": [
                    "Test Test <t1@test.com>"
                ],
                "mid": 70,
                "size": "17.60K",
                "subject": "test 2",
                "toAddress": [
                    "test@test.com <test@test.com>"
                ]
            },
            {
                "date": "11 Sep 2022 07:55 (GMT)",
                "envelopeRecipient": [
                    "test@test.com"
                ],
                "fromAddress": [
                    "Test Test <t1@test.com>"
                ],
                "mid": 69,
                "size": "17.70K",
                "subject": "hello",
                "toAddress": [
                    "test@test.com <test@test.com>"
                ]
            }
        ]
    }
}

Human Readable Output

Spam Quarantine Messages List

Showing page 3.
Current page size: 2.

Mid Date From Address To Address Subject Size
70 11 Sep 2022 07:55 (GMT) Test Test t1@test.com “test@test.com” test@test.com test 2 17.60K
69 11 Sep 2022 07:55 (GMT) Test Test t1@test.com “test@test.com” test@test.com hello 17.70K

cisco-sma-spam-quarantine-message-get


Get spam quarantine message.

Base Command

cisco-sma-spam-quarantine-message-get

Input

Argument Name Description Required
message_id Message ID. Required

Context Output

Path Type Description
CiscoSMA.SpamQuarantineMessage.envelopeRecipient String Message recipient.
CiscoSMA.SpamQuarantineMessage.toAddress String Message recipient.
CiscoSMA.SpamQuarantineMessage.messageBody String Message body.
CiscoSMA.SpamQuarantineMessage.date String Message date.
CiscoSMA.SpamQuarantineMessage.fromAddress String Message sender.
CiscoSMA.SpamQuarantineMessage.subject String Message subject.
CiscoSMA.SpamQuarantineMessage.mid Number Message ID.

Command example

!cisco-sma-spam-quarantine-message-get message_id=64

Context Example

{
    "CiscoSMA": {
        "SpamQuarantineMessage": {
            "attachments": [],
            "date": "11 Sep 2022 06:07 (GMT)",
            "envelopeRecipient": [
                "test@test.com"
            ],
            "fromAddress": [
                "Test Test <t1@test.com>"
            ],
            "messageBody": "Received: from esa2.test.eu.iphmx.com ([2.2.2.2])  by sma1.test.eu.iphmx.com with ESMTP; 11 Sep 2022 06:07:11 +0000Received-SPF: Pass (esa2.test.eu.iphmx.com: domain of  t1@test.com designates 22.22.22.22 as permitted  sender) identity=mailfrom; client-ip=22.22.22.22;  receiver=esa2.test.eu.iphmx.com;  envelope-from=t1@test.com;  x-sender=t1@test.com; x-conformance=spf_only;  x-record-type=v=spf1; x-record-text=v=spf1  ip4:8.8.8.8/15 ip4:1.1.1.1/16 ip4:1.1.1.1/14  ip4:1.1.1.1/17 ip1.1.1.1/48  ip1.1.1.1/49 ip1.1.1.1/50  ip1.1.1.1/51 ip1.1.1.1/52  include:spfd.protection.outlook.com -allAuthentication-Results: esa2.test.eu.iphmx.com; spf=Pass smtp.mailfrom=t1@test.com; dkim=pass (signature verified) header.i=@Qmasters.onmicrosoft.comX-Ironport-Dmarc-Check-Result: validskipIronPort-SDR: 631d7b0e_gYHRKFozU63bNGUcBmI6bZxMVbnKq771Bg3g/PXeqXGnCcb en8XOitOlv+hcIvMhGPgHjLS3GSW298LZ8xVyrA==X-IronPort-RemoteIP: 22.22.22.22X-IronPort-MID: 427X-IronPort-Reputation: 3.5X-IronPort-Listener: MailFlowX-IronPort-SenderGroup: ACCEPTLISTX-IronPort-MailFlowPolicy: $ACCEPTEDX-SLBL-Result: BLOCK-LISTEDX-IronPort-AV: E=McAfee;i=6500,9779,10466; a=427X-IronPort-AV: E=Sophos;i=5.93,307,1654549200;    d=scan'208,217;a=427X-Amp-Result: SKIPPED(no attachment in message)X-Amp-File-Uploaded: FalseX-IPAS-Result: =?us-ascii?q?vGpBb5TsaWco2WF0CJmG5A=3D=3D?=Received: from mail-eopbgr150082.outbound.protection.outlook.com (HELO EUR01-DB5-obe.outbound.protection.outlook.com) ([22.22.22.22])  by esa2.test.eu.iphmx.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Sep 2022 09:07:10 +0300ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=/saT6U5NS0IZCdFJ8PRhIOdlfgGhCHg==ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1 mx.microsoft.com 1; spf=pass smtp.mailfrom=qmasters.co; dmarc=pass action=none header.from=qmasters.co; dkim=pass header.d=qmasters.co; arc=noneDKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Qmasters.onmicrosoft.com; s=selector2-Qmasters-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=8EDhl0WksFhflNDqiZFXIJI/gERNfydqE0p9gIt/k1E=; b=/0nVjDfeQJk=Received: from AS4P192MB1694.EURP192.PROD.OUTLOOK.COM (1.1.1.11) by GV1P192MB1739.EURP192.PROD.OUTLOOK.COM (1.1.1.115) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5612.20; Sun, 11 Sep 2022 06:07:08 +0000Received: from AS4P192MB1694.EURP192.PROD.OUTLOOK.COM ([1.1.1.1ddbc:6c6a:6e24:2ddc]) by AS4P192MB1694.EURP192.PROD.OUTLOOK.COM ([1.1.1.1ddbc:6c6a:6e24:2ddc%5]) with mapi id 15.20.5612.022; Sun, 11 Sep 2022 06:07:08 +0000From: Test Test &lt;t1@test.com&gt;To: test@test.com &lt;test@test.com&gt;Subject: test1Thread-Topic: test1Thread-Index: AdjFpLjMMletPLuSTiamq2aPR00gtw==Date: Sun, 11 Sep 2022 06:07:07 +0000Message-ID:-Language: en-US, he-ILContent-Language: en-USX-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-publictraffictype: Emailx-ms-traffictypediagnostic: AS4P192MB1694:EE_|GV1P192MB1739:EE_x-ms-office365-filtering-correlation-id: 1f4793f4-e7cb-44f4-45d0-08da93bbdbabx-ms-exchange-senderadcheck: 1x-ms-exchange-antispam-relay: 0x-microsoft-antispam: BCL:0;x-microsoft-antispam-message-info:  4DkFMorvBGYa2L7kv5m1ibET5n0EvYTCLJhZmOPqKgjLW+eH0zwrxtxJBRcchZ1ZkamOBS+alGY0FGLHiHyUMavSvkdOvmk526KzQDiXoY5xcIHN6un/c6CzO9pcvrGN2D3aPGL5NGw16o+lG/TlArEoyjMC5PM/forefront-antispam-report:  CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:AS4P192MB1694.EURP192.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230016)(4636009)(346002)(376002)(136003)(366004)(39830400003)(396003)(2906002)(8936002);DIR:OUT;Q?C1JbgP7At7ztN6x7KY7DAv3gpBtr1wcCZy2aTMfk?=Content-Type: multipart/alternative;\tboundary=_000_AS4P192MB1694E446958C283FF6146212AB459AS4P192MB1694EURP_MIME-Version: 1.0X-OriginatorOrg: qmasters.coX-MS-Exchange-CrossTenant-AuthAs: InternalX-MS-Exchange-CrossTenant-AuthSource: AS4P192MB1694.EURP192.PROD.OUTLOOK.COMX-MS-Exchange-CrossTenant-Network-Message-Id: 1f4793f4-e7cb-44f4-45d0-08da93bbdbabX-MS-Exchange-CrossTenant-originalarrivaltime: 11 Sep 2022 06:07:07.9480 (UTC)X-MS-Exchange-CrossTenant-fromentityheader: HostedX-MS-Exchange-CrossTenant-id: ed363dfd-16fd-4038-8e58-9237411a84e5X-MS-Exchange-CrossTenant-mailboxtype: HOSTEDX-MS-Exchange-CrossTenant-userprincipalname: oeEevxfXcCiCthJ0sdKmama9rN1O92XcZ3RYCBNpAtJGc1YO+C9f+UGf6qp4y0t2aVaTNORJqi/cQeynDtX1hQ==X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1P192MB1739",
            "mid": 64,
            "subject": "test1",
            "toAddress": [
                "test@test.com <test@test.com>"
            ]
        }
    }
}

Human Readable Output

Spam Quarantine Message

Found spam quarantine message with ID: 64

Mid From Address To Address Date Subject
64 Test Test t1@test.com “test@test.com” test@test.com 11 Sep 2022 06:07 (GMT) test1

cisco-sma-spam-quarantine-message-release


Release spam quarantined message.

Base Command

cisco-sma-spam-quarantine-message-release

Input

Argument Name Description Required
message_ids Comma-separated list of message IDs. Required

Context Output

There is no context output for this command.

Command example

!cisco-sma-spam-quarantine-message-release message_ids=65

Human Readable Output

Quarantined message 65 successfully released.

cisco-sma-spam-quarantine-message-delete


Delete spam quarantined message.

Base Command

cisco-sma-spam-quarantine-message-delete

Input

Argument Name Description Required
message_ids Comma-separated list of message IDs. Required

Context Output

There is no context output for this command.

Command example

!cisco-sma-spam-quarantine-message-delete message_ids=66

Human Readable Output

Quarantined message 66 successfully deleted.

cisco-sma-list-entry-get


Get spam quarantine blocklist/safelist entry.

Base Command

cisco-sma-list-entry-get

Input

Argument Name Description Required
entry_type List entry type. Possible values are: blocklist, safelist. Required
page Page number of paginated results.
Minimum value is 1.
Optional
page_size Number of results per page. Maximum value is 100. Optional
limit The maximum number of records to retrieve. Default is 50. Optional
order_by How the results should be ordered. Possible values are: recipient, sender. Optional
order_dir Direction in which the results should be ordered. Possible values are: asc, desc. Optional
view_by View results by. Possible values are: recipient, sender. Default is recipient. Optional
search Search for recipients or senders in blocklist/safelist with ‘contains’ operator.
e.g., test@test.com, test.com
This is only supported for the argument view_by=recipient.
Optional

Context Output

Path Type Description
CiscoSMA.ListEntry.Blocklist.senderList String Sender list.
CiscoSMA.ListEntry.Blocklist.recipientAddress String Recipient address.
CiscoSMA.ListEntry.Blocklist.recipientList String Recipient list.
CiscoSMA.ListEntry.Blocklist.senderAddress String Sender address.
CiscoSMA.ListEntry.Safelist.senderList String Sender list.
CiscoSMA.ListEntry.Safelist.recipientAddress String Recipient address.
CiscoSMA.ListEntry.Safelist.recipientList String Recipient list.
CiscoSMA.ListEntry.Safelist.senderAddress String Sender address.

Command example

!cisco-sma-list-entry-get entry_type=safelist page=2 page_size=3 view_by=recipient order_by=recipient order_dir=desc

Context Example

{
    "CiscoSMA": {
        "ListEntry": {
            "Safelist": [
                {
                    "recipientAddress": "test4@test.com",
                    "senderList": [
                        "t3@test.com"
                    ]
                },
                {
                    "recipientAddress": "test3@test.com",
                    "senderList": [
                        "t3@test.com"
                    ]
                },
                {
                    "recipientAddress": "test2@test.com",
                    "senderList": [
                        "testi@test.com"
                    ]
                }
            ]
        }
    }
}

Human Readable Output

Safelist Entries

Showing page 2.
Current page size: 3.

Recipient Address Sender List
test4@test.com t3@test.com
test3@test.com t3@test.com
test2@test.com testi@test.com

cisco-sma-list-entry-add


Add spam quarantine blocklist/safelist entry.

Base Command

cisco-sma-list-entry-add

Input

Argument Name Description Required
entry_type List entry type. Possible values are: blocklist, safelist. Required
view_by Add list entry by recipient/sender.
When view_by = recipient: recipient_addresses and sender_list are mandatory.
When view_by = sender: sender_addresses and recipient_list are mandatory. Possible values are: recipient, sender. Default is recipient.
Optional
recipient_addresses A comma-separated list of recipients to add. Optional
sender_list A comma-separated list of senders to add. Optional
sender_addresses A comma-separated list of senders to add. Optional
recipient_list A comma-separated list of recipients to add. Optional

Context Output

There is no context output for this command.

Command example

!cisco-sma-list-entry-add entry_type=blocklist view_by=recipient recipient_addresses=test@test.com sender_list=t1@test.com,t2@test.com

Human Readable Output

Successfully added t1@test.com, t2@test.com senders to test@test.com recipients in blocklist.

cisco-sma-list-entry-append


Append spam quarantine blocklist/safelist entry.

Base Command

cisco-sma-list-entry-append

Input

Argument Name Description Required
entry_type List entry type. Possible values are: blocklist, safelist. Required
view_by Append list entry by recipient/sender.
When view_by = recipient: recipient_addresses and sender_list are mandatory.
When view_by = sender: sender_addresses and recipient_list are mandatory. Possible values are: recipient, sender. Default is recipient.
Optional
recipient_list A comma-separated list of recipients to append. Optional
sender_list A comma-separated list of senders to append. Optional
recipient_addresses A comma-separated list of recipients to append. Optional
sender_addresses A comma-separated list of senders to append. Optional

Context Output

There is no context output for this command.

Command example

!cisco-sma-list-entry-append entry_type=blocklist recipient_addresses=test@test.com sender_list=t4@test.com

Human Readable Output

Successfully appended t4@test.com senders to test@test.com recipients in blocklist.

cisco-sma-list-entry-edit


Edit the spam quarantine blocklist/safelist entry. Using this command will override the existing value.

Base Command

cisco-sma-list-entry-edit

Input

Argument Name Description Required
entry_type List entry type. Possible values are: blocklist, safelist. Required
view_by Edit list entry by recipient/sender.
When view_by = recipient: recipient_addresses and sender_list are mandatory.
When view_by = sender: sender_addresses and recipient_list are mandatory. Possible values are: recipient, sender. Default is recipient.
Optional
recipient_list A comma-separated list of recipients to edit. Optional
sender_list A comma-separated list of senders to edit. Optional
recipient_addresses A comma-separated list of recipients to edit. Optional
sender_addresses A comma-separated list of senders to edit. Optional

Context Output

There is no context output for this command.

Command example

!cisco-sma-list-entry-edit entry_type=blocklist view_by=recipient recipient_addresses=test@test.com sender_list=t5@test.com,t6@test.com

Human Readable Output

Successfully edited test@test.com recipients’ senders to t5@test.com, t6@test.com in blocklist.

cisco-sma-list-entry-delete


Delete a spam quarantine blocklist/safelist entry.

Base Command

cisco-sma-list-entry-delete

Input

Argument Name Description Required
entry_type List entry type. Possible values are: blocklist, safelist. Required
view_by Delete list entry by recipient/sender.
When view_by = recipient: recipient_list is mandatory.
When view_by = sender: sender_list is mandatory. Possible values are: recipient, sender. Default is recipient.
Optional
recipient_list A comma-separated list of recipients to delete. Optional
sender_list A comma-separated list of senders to delete. Optional

Context Output

There is no context output for this command.

Command example

!cisco-sma-list-entry-delete entry_type=blocklist view_by=recipient recipient_list=test@test.com

Human Readable Output

Successfully deleted test@test.com recipients from blocklist.

cisco-sma-message-search


Search tracking messages.

Base Command

cisco-sma-message-search

Input

Argument Name Description Required
start_date Start date in ISO format or <number> <time unit>,
e.g., 2022-01-01T00:00:00.000Z, 12 hours, 7 days, 3 months, now.
Required
end_date End date in ISO format or <number> <time unit>,
e.g., 2022-01-01T00:00:00.000Z, 12 hours, 7 days, 3 months, now.
Required
page Page number of paginated results.
Minimum value is 1.
Optional
page_size Number of results per page. Maximum value is 100. Optional
limit The maximum number of records to retrieve. Default is 50. Optional
sender_filter_operator Sender filter operator. Possible values are: contains, is, begins_with. Optional
sender_filter_value Sender filter value. Optional
recipient_filter_operator Recipient filter operator. Possible values are: contains, is, begins_with. Optional
recipient_filter_value Recipient filter value. Optional
subject_filter_operator Subject filter operator. Possible values are: contains, is, begins_with. Optional
subject_filter_value Subject filter value. Optional
attachment_name_operator Attachment name operator. Possible values are: contains, is, begins_with. Optional
attachment_name_value Attachment name value. Optional
cisco_host Cisco host. Default is All_Hosts. Optional
file_sha_256 SHA256 must be 64 characters long and can contain only “0-9” and “a-f” symbols.
E.g., e0d123e5f316bef78bfdf5a008837577e0d123e5f316bef78bfdf5a008837577.
Optional
custom_query Custom query for cisco SMA’s advanced filters.
Syntax: <key>=<value>;<key>=<value>;<key>=<value>
E.g., graymail=True;message_delivered=True.
Optional

Context Output

Path Type Description
CiscoSMA.Message.hostName String Email gateway hostname.
CiscoSMA.Message.friendly_from String Friendly formatted sender email address.
CiscoSMA.Message.isCompleteData String Is complete data pulled?
CiscoSMA.Message.messageStatus String Message delivery status.
CiscoSMA.Message.recipientMap String Recipients list.
CiscoSMA.Message.senderIp String Sender IP address.
CiscoSMA.Message.mailPolicy String Matched mail policy.
CiscoSMA.Message.senderGroup String Matched sender group.
CiscoSMA.Message.subject String Subject of email message.
CiscoSMA.Message.dcid Number Delivery Connection ID.
CiscoSMA.Message.mid String Message ID.
CiscoSMA.Message.senderDomain String Domain of email message sender.
CiscoSMA.Message.finalSubject String Extended email subject.
CiscoSMA.Message.direction String Message direction, incoming or outgoing.
CiscoSMA.Message.icid Number An Injection Connection ID (ICID) is a numerical identifier for an individual SMTP connection to the system.
CiscoSMA.Message.replyTo String Email message reply to.
CiscoSMA.Message.timestamp String Time of email message.
CiscoSMA.Message.messageID String Extended message ID.
CiscoSMA.Message.verdictChart String Verdict visual chart ID.
CiscoSMA.Message.recipient String Recipients email addresses list.
CiscoSMA.Message.sender String Sender email address.
CiscoSMA.Message.serialNumber String Cisco ESA email gateway serial number.
CiscoSMA.Message.allIcid Number ICIDs list.
CiscoSMA.Message.sbrs String Sender Base Reputation Scores.

Command example

!cisco-sma-message-search start_date=1month end_date=now page=3 page_size=2 subject_filter_operator=contains subject_filter_value=test

Context Example

{
    "CiscoSMA": {
        "Message": [
            {
                "allIcid": [
                    13538
                ],
                "unique_message_id": "433",
                "dcid": [],
                "direction": "incoming",
                "finalSubject": {
                    "433": "test 2"
                },
                "friendly_from": [
                    "t1@test.com"
                ],
                "hostName": "esa2.test.eu.iphmx.com",
                "icid": 13538,
                "isCompleteData": "N/A",
                "mailPolicy": [
                    "DEFAULT"
                ],
                "messageID": {
                    "433": "<AS4P192MB1694F8603766320A4C87D29AAB459@AS4P192MB1694.EURP192.PROD.OUTLOOK.COM>"
                },
                "messageStatus": {
                    "433": "Quarantined by Anti-Spam/Graymail"
                },
                "mid": [
                    433
                ],
                "morDetails": {},
                "recipient": [
                    "test@test.com"
                ],
                "recipientMap": {
                    "433": [
                        "test@test.com"
                    ]
                },
                "replyTo": "N/A",
                "sbrs": "3.5",
                "sender": "t1@test.com",
                "senderDomain": "qmasters.co",
                "senderGroup": "ACCEPTLIST",
                "senderIp": "1.1.1.1",
                "serialNumber": "423ADC9EBD9C5F1A7A64-B81D2582608C",
                "subject": "test 2",
                "timestamp": "2022-09-11T07:55:25Z",
                "verdictChart": {
                    "433": "16140210"
                }
            },
            {
                "allIcid": [
                    13536
                ],
                "unique_message_id": "431",
                "dcid": [],
                "direction": "incoming",
                "finalSubject": {
                    "431": "test1"
                },
                "friendly_from": [
                    "t1@test.com"
                ],
                "hostName": "esa2.test.eu.iphmx.com",
                "icid": 13536,
                "isCompleteData": "N/A",
                "mailPolicy": [
                    "DEFAULT"
                ],
                "messageID": {
                    "431": "<AS4P192MB1694630ADD929556BCEC2F09AB459@AS4P192MB1694.EURP192.PROD.OUTLOOK.COM>"
                },
                "messageStatus": {
                    "431": "Quarantined by Anti-Spam/Graymail"
                },
                "mid": [
                    431
                ],
                "morDetails": {},
                "recipient": [
                    "test@test.com"
                ],
                "recipientMap": {
                    "431": [
                        "test@test.com"
                    ]
                },
                "replyTo": "N/A",
                "sbrs": "3.5",
                "sender": "t1@test.com",
                "senderDomain": "qmasters.co",
                "senderGroup": "ACCEPTLIST",
                "senderIp": "1.1.1.1",
                "serialNumber": "423ADC9EBD9C5F1A7A64-B81D2582608C",
                "subject": "test1",
                "timestamp": "2022-09-11T07:55:15Z",
                "verdictChart": {
                    "431": "16140210"
                }
            }
        ]
    }
}

Human Readable Output

Messages List

Showing page 3.
Current page size: 2.

Mid All Icid Serial Number Sender Recipient Subject Message Status Timestamp Sender Ip Sbrs
433 13538 423ADC9EBD9C5F1A7A64-B81D2582608C t1@test.com test@test.com test 2 433: Quarantined by Anti-Spam/Graymail 2022-09-11T07:55:25Z 1.1.1.1 3.5
431 13536 423ADC9EBD9C5F1A7A64-B81D2582608C t1@test.com test@test.com test1 431: Quarantined by Anti-Spam/Graymail 2022-09-11T07:55:15Z 1.1.1.1 3.5

cisco-sma-message-details-get


Get more details on the message.

Base Command

cisco-sma-message-details-get

Input

Argument Name Description Required
serial_number Email gateway serial number. Required
message_ids Message ID list. Required
injection_connection_id Injection connection ID. Optional
delivery_connection_id Delivery connection ID. Optional

Context Output

Path Type Description
CiscoSMA.Message.sdrAge String Sender Domain Reputation age.
CiscoSMA.Message.attachments String Message attachments.
CiscoSMA.Message.hostName String Email gateway hostname.
CiscoSMA.Message.direction String Message direction, incoming or outgoing.
CiscoSMA.Message.isCompleteData Boolean Is complete data pulled?
CiscoSMA.Message.messageStatus String Message delivery status.
CiscoSMA.Message.mailPolicy String Matched mail policy.
CiscoSMA.Message.senderGroup String Matched sender group.
CiscoSMA.Message.subject String Email message subject.
CiscoSMA.Message.showSummaryTimeBox Boolean Whether to show the summary time box.
CiscoSMA.Message.sdrCategory String Sender Domain Reputation category.
CiscoSMA.Message.mid String Message ID.
CiscoSMA.Message.sendingHostSummary.reverseDnsHostname String Sending host reverse DNS hostname.
CiscoSMA.Message.sendingHostSummary.ipAddress String Sending host IP address.
CiscoSMA.Message.sendingHostSummary.sbrsScore String Sending host Sender Base Reputation scores.
CiscoSMA.Message.smtpAuthId String SMTP auth ID.
CiscoSMA.Message.midHeader String Message ID header.
CiscoSMA.Message.timestamp String Email message time.
CiscoSMA.Message.showDLP Boolean Whether the DLP report is available.
CiscoSMA.Message.messageSize String Email message size.
CiscoSMA.Message.sdrThreatLevels String Sender Domain Reputation threat levels.
CiscoSMA.Message.sdrReputation String Sender Domain Reputation.
CiscoSMA.Message.showURL Boolean Whether the URL report is available.
CiscoSMA.Message.recipient String Message recipient email address.
CiscoSMA.Message.sender String Message sender email address.
CiscoSMA.Message.showAMP Boolean Whether the AMP report is available.
CiscoSMA.Message.summary.timestamp String Event summary time.
CiscoSMA.Message.summary.description String Event summary description.
CiscoSMA.Message.summary.lastEvent Boolean Whether the event summary is the last event.
CiscoSMA.Message.allIcid Number ICIDs list.
CiscoSMA.Message.headerFrom String Email header from.

Command example

!cisco-sma-message-details-get serial_number=423ADC9EBD9C5F1A7A64-B81D2582608C message_ids=322 injection_connection_id=10821 delivery_connection_id=4368

Context Example

{
    "CiscoSMA": {
        "Message": {
            "allIcid": [
                10821
            ],
            "ampTgCategories": [],
            "attachments": "",
            "unique_message_id": "322",
            "direction": "incoming",
            "headerFrom": "defender-noreply@microsoft.com",
            "hostName": "esa2.test.eu.iphmx.com (2.2.2.2)",
            "isCompleteData": true,
            "mailPolicy": [
                "DEFAULT"
            ],
            "messageSize": "70.3 (KB)",
            "messageStatus": "Delivered",
            "mid": [
                322
            ],
            "midHeader": "<add53137-42a8-4753-af53-bad0752af24d@az.westeurope.production.microsoft.com>",
            "recipient": [
                "t2@test.com"
            ],
            "sdrAge": "30 days (or greater)",
            "sdrCategory": "N/A",
            "sdrReputation": "Neutral",
            "sdrThreatLevels": "3",
            "sender": "azure-noreply@microsoft.com",
            "senderGroup": "ACCEPTLIST",
            "sendingHostSummary": {
                "ipAddress": "7.7.7.7",
                "reverseDnsHostname": "test.cloudapp.net (verified)",
                "sbrsScore": "3.5"
            },
            "showAMP": false,
            "showDLP": false,
            "showSummaryTimeBox": true,
            "showURL": false,
            "smtpAuthId": "",
            "subject": "Microsoft 365 Defender has detected a security threat",
            "summary": [
                {
                    "description": "Incoming connection (ICID 10821) has sender_group: ACCEPTLIST, sender_ip: 7.7.7.7 and sbrs: 3.5",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Protocol SMTP interface Data 1  (IP 2.2.2.2) on incoming connection (ICID 10821) from sender IP 7.7.7.7. Reverse DNS  host test.cloudapp.net verified yes.",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "(ICID 10821) ACCEPT sender group ACCEPTLIST match sbrs[0.0:10.0] SBRS 3.5 country Netherlands",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Incoming connection (ICID 10821) successfully accepted TLS protocol TLSv1.2 cipher ECDHE-RSA-AES256-GCM-SHA384.",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322 Sender Domain: microsoft.com",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Start message 322 on incoming connection (ICID 10821).",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322 enqueued on incoming connection (ICID 10821) from azure-noreply@microsoft.com.",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322 direction: incoming",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322 Domains for which SDR is requested: reverse DNS host: test.cloudapp.net, helo: test.cloudapp.net, env-from: microsoft.com, header_from: Not Present, reply_to: Not Present",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322 Consolidated Sender Threat Level: Neutral, Threat Category: N/A, Suspected Domain(s) : N/A (other reasons for verdict). Sender Maturity: 30 days (or greater) for domain: test.cloudapp.net",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322 on incoming connection (ICID 10821) added recipient (t2@test.com).",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322 SPF: mailfrom identity azure-noreply@microsoft.com Pass",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322 DKIM: pass signature verified (d=microsoft.com s=s1024-meo i=defender-noreply@microsoft.com)",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322: DMARC Message from domain microsoft.com, DMARC pass (SPF aligned True, DKIM aligned True),",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322: DMARC verification passed.",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322 contains message ID header '<add53137-42a8-4753-af53-bad0752af24d@az.westeurope.production.microsoft.com>'.",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322 original subject on injection: Microsoft 365 Defender has detected a security threat",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322 Domains for which SDR is requested: reverse DNS host: test.cloudapp.net, helo: test.cloudapp.net, env-from: microsoft.com, header_from: microsoft.com, reply_to: Not Present",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322 Consolidated Sender Threat Level: Neutral, Threat Category: N/A, Suspected Domain(s) : N/A (other reasons for verdict). Sender Maturity: 30 days (or greater) for domain: test.cloudapp.net",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322 (71983 bytes) from azure-noreply@microsoft.com ready.",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322 has sender_group: ACCEPTLIST, sender_ip: 7.7.7.7 and sbrs: 3.5",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:18Z"
                },
                {
                    "description": "Message 322 matched per-recipient policy DEFAULT for inbound mail policies.",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:19Z"
                },
                {
                    "description": "Incoming connection (ICID 10821) lost.",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:19Z"
                },
                {
                    "description": "Message 322 scanned by Anti-Spam engine: CASE. Interim verdict: Negative",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:19Z"
                },
                {
                    "description": "Message 322 scanned by Anti-Spam engine CASE. Interim verdict: definitely negative.",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:19Z"
                },
                {
                    "description": "Message 322 scanned by Anti-Spam engine: CASE. Final verdict: Negative",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:19Z"
                },
                {
                    "description": "Message 322 scanned by Anti-Virus engine McAfee. Interim verdict: CLEAN",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:19Z"
                },
                {
                    "description": "Message 322 scanned by Anti-Virus engine Sophos. Interim verdict: CLEAN",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:19Z"
                },
                {
                    "description": "Message 322 scanned by Anti-Virus engine. Final verdict: Negative ",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:19Z"
                },
                {
                    "description": "Message 322 scanned by Advanced Malware Protection engine. Final verdict: SKIPPED(no attachment in message)",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:19Z"
                },
                {
                    "description": "Message 322 scanned by Outbreak Filters. Verdict: Negative",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:19Z"
                },
                {
                    "description": "Message 322 queued for delivery.",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:19Z"
                },
                {
                    "description": "SMTP delivery connection (DCID 4368) opened from Cisco IronPort interface 2.2.2.2 to IP address 1.1.1.1 on port 25.",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:19Z"
                },
                {
                    "description": "Delivery connection (DCID 4368) successfully accepted TLS protocol TLSv1.2 cipher ECDHE-RSA-AES256-GCM-SHA384 None.",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:19Z"
                },
                {
                    "description": "(DCID 4368) Delivery started for message 322 to t2@test.com.",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:19Z"
                },
                {
                    "description": "(DCID 4368) Delivery details: Message 322 sent to t2@test.com [('from', 'Microsoft 365 Defender <defender-noreply@microsoft.com>'), ('to', 't2@test.com')]",
                    "lastEvent": false,
                    "timestamp": "2022-09-07T10:11:20Z"
                },
                {
                    "description": "Message 322 to t2@test.com received remote SMTP response '2.6.0 <add53137-42a8-4753-af53-bad0752af24d@az.westeurope.production.microsoft.com> [InternalId=1511828495895, Hostname=test.test.PROD.OUTLOOK.COM] 92322 bytes in 0.189, 475.293 KB/sec Queued mail for delivery'.",
                    "lastEvent": true,
                    "timestamp": "2022-09-07T10:11:21Z"
                }
            ],
            "timestamp": "2022-09-07T10:11:18Z"
        }
    }
}

Human Readable Output

Message Details

Found message with ID 322.

Mid All Icid Subject Sender Recipient Timestamp Message Size Sending Host Summary Message Status Direction Mail Policy Sender Group Show AMP Show DLP Show URL
322 10821 Microsoft 365 Defender has detected a security threat azure-noreply@microsoft.com t2@test.com 2022-09-07T10:11:18Z 70.3 (KB) reverseDnsHostname: test.cloudapp.net (verified) ipAddress: 7.7.7.7 sbrsScore: 3.5 Delivered incoming DEFAULT ACCEPTLIST false false false

Message Summary

Description Timestamp Last Event
Incoming connection (ICID 10821) has sender_group: ACCEPTLIST, sender_ip: 7.7.7.7 and sbrs: 3.5 2022-09-07T10:11:18Z false
Protocol SMTP interface Data 1 (IP 2.2.2.2) on incoming connection (ICID 10821) from sender IP 7.7.7.7. Reverse DNS host test.cloudapp.net verified yes. 2022-09-07T10:11:18Z false
(ICID 10821) ACCEPT sender group ACCEPTLIST match sbrs[0.0:10.0] SBRS 3.5 country Netherlands 2022-09-07T10:11:18Z false
Incoming connection (ICID 10821) successfully accepted TLS protocol TLSv1.2 cipher ECDHE-RSA-AES256-GCM-SHA384. 2022-09-07T10:11:18Z false
Message 322 Sender Domain: microsoft.com 2022-09-07T10:11:18Z false
Start message 322 on incoming connection (ICID 10821). 2022-09-07T10:11:18Z false
Message 322 enqueued on incoming connection (ICID 10821) from azure-noreply@microsoft.com. 2022-09-07T10:11:18Z false
Message 322 direction: incoming 2022-09-07T10:11:18Z false
Message 322 Domains for which SDR is requested: reverse DNS host: test.cloudapp.net, helo: test.cloudapp.net, env-from: microsoft.com, header_from: Not Present, reply_to: Not Present 2022-09-07T10:11:18Z false
Message 322 Consolidated Sender Threat Level: Neutral, Threat Category: N/A, Suspected Domain(s) : N/A (other reasons for verdict). Sender Maturity: 30 days (or greater) for domain: test.cloudapp.net 2022-09-07T10:11:18Z false
Message 322 on incoming connection (ICID 10821) added recipient (t2@test.com). 2022-09-07T10:11:18Z false
Message 322 SPF: mailfrom identity azure-noreply@microsoft.com Pass 2022-09-07T10:11:18Z false
Message 322 DKIM: pass signature verified (d=microsoft.com s=s1024-meo i=defender-noreply@microsoft.com) 2022-09-07T10:11:18Z false
Message 322: DMARC Message from domain microsoft.com, DMARC pass (SPF aligned True, DKIM aligned True), 2022-09-07T10:11:18Z false
Message 322: DMARC verification passed. 2022-09-07T10:11:18Z false
Message 322 contains message ID header ‘add53137-42a8-4753-af53-bad0752af24d@az.westeurope.production.microsoft.com’. 2022-09-07T10:11:18Z false
Message 322 original subject on injection: Microsoft 365 Defender has detected a security threat 2022-09-07T10:11:18Z false
Message 322 Domains for which SDR is requested: reverse DNS host: test.cloudapp.net, helo: test.cloudapp.net, env-from: microsoft.com, header_from: microsoft.com, reply_to: Not Present 2022-09-07T10:11:18Z false
Message 322 Consolidated Sender Threat Level: Neutral, Threat Category: N/A, Suspected Domain(s) : N/A (other reasons for verdict). Sender Maturity: 30 days (or greater) for domain: test.cloudapp.net 2022-09-07T10:11:18Z false
Message 322 (71983 bytes) from azure-noreply@microsoft.com ready. 2022-09-07T10:11:18Z false
Message 322 has sender_group: ACCEPTLIST, sender_ip: 7.7.7.7 and sbrs: 3.5 2022-09-07T10:11:18Z false
Message 322 matched per-recipient policy DEFAULT for inbound mail policies. 2022-09-07T10:11:19Z false
Incoming connection (ICID 10821) lost. 2022-09-07T10:11:19Z false
Message 322 scanned by Anti-Spam engine: CASE. Interim verdict: Negative 2022-09-07T10:11:19Z false
Message 322 scanned by Anti-Spam engine CASE. Interim verdict: definitely negative. 2022-09-07T10:11:19Z false
Message 322 scanned by Anti-Spam engine: CASE. Final verdict: Negative 2022-09-07T10:11:19Z false
Message 322 scanned by Anti-Virus engine McAfee. Interim verdict: CLEAN 2022-09-07T10:11:19Z false
Message 322 scanned by Anti-Virus engine Sophos. Interim verdict: CLEAN 2022-09-07T10:11:19Z false
Message 322 scanned by Anti-Virus engine. Final verdict: Negative 2022-09-07T10:11:19Z false
Message 322 scanned by Advanced Malware Protection engine. Final verdict: SKIPPED(no attachment in message) 2022-09-07T10:11:19Z false
Message 322 scanned by Outbreak Filters. Verdict: Negative 2022-09-07T10:11:19Z false
Message 322 queued for delivery. 2022-09-07T10:11:19Z false
SMTP delivery connection (DCID 4368) opened from Cisco IronPort interface 2.2.2.2 to IP address 1.1.1.1 on port 25. 2022-09-07T10:11:19Z false
Delivery connection (DCID 4368) successfully accepted TLS protocol TLSv1.2 cipher ECDHE-RSA-AES256-GCM-SHA384 None. 2022-09-07T10:11:19Z false
(DCID 4368) Delivery started for message 322 to t2@test.com. 2022-09-07T10:11:19Z false
(DCID 4368) Delivery details: Message 322 sent to t2@test.com [(‘from’, ‘Microsoft 365 Defender defender-noreply@microsoft.com’), (‘to’, ‘t2@test.com’)] 2022-09-07T10:11:20Z false
Message 322 to t2@test.com received remote SMTP response ‘2.6.0 add53137-42a8-4753-af53-bad0752af24d@az.westeurope.production.microsoft.com [InternalId=1511828495895, Hostname=test.test.PROD.OUTLOOK.COM] 92322 bytes in 0.189, 475.293 KB/sec Queued mail for delivery’. 2022-09-07T10:11:21Z true

cisco-sma-message-amp-details-get


Get message AMP summary details.

Base Command

cisco-sma-message-amp-details-get

Input

Argument Name Description Required
serial_number Email gateway serial number. Required
message_ids Message ID list. Required

Context Output

Path Type Description
CiscoSMA.AMPDetail.sdrAge String Sender Domain Reputation age.
CiscoSMA.AMPDetail.attachments String Message attachments.
CiscoSMA.AMPDetail.hostName String Email gateway hostname.
CiscoSMA.AMPDetail.direction String Message direction, incoming or outgoing.
CiscoSMA.AMPDetail.messageStatus String Message delivery status.
CiscoSMA.AMPDetail.senderGroup String Matched sender group.
CiscoSMA.AMPDetail.subject String Email message subject.
CiscoSMA.AMPDetail.sdrCategory String Sender Domain Reputation category.
CiscoSMA.AMPDetail.mid Number Message ID.
CiscoSMA.AMPDetail.ampDetails.timestamp String AMP event summary details timestamp.
CiscoSMA.AMPDetail.ampDetails.description String AMP event summary details description.
CiscoSMA.AMPDetail.ampDetails.lastEvent Boolean AMP event summary details last event.
CiscoSMA.AMPDetail.smtpAuthId String SMTP auth ID.
CiscoSMA.AMPDetail.midHeader String Message ID header.
CiscoSMA.AMPDetail.timestamp String Email message time.
CiscoSMA.AMPDetail.messageSize String Email message size.
CiscoSMA.AMPDetail.sdrThreatLevels String Sender Domain Reputation threat levels.
CiscoSMA.AMPDetail.sdrReputation String Sender Domain Reputation.
CiscoSMA.AMPDetail.recipient String Message recipient email address.
CiscoSMA.AMPDetail.sender String Message sender email address.
CiscoSMA.AMPDetail.showAMPDetails Boolean Whether to show AMP details.
CiscoSMA.AMPDetail.allIcid Number ICIDs list.
CiscoSMA.AMPDetail.headerFrom String Email header from.

Command example

!cisco-sma-message-amp-details-get message_ids=21 serial_number=42356DFA5D016457B182-3616BA148E19

Context Example

{
    "CiscoSMA": {
        "AMPDetail": {
            "allIcid": [
                1269
            ],
            "ampDetails": [
                {
                    "description": "File reputation query initiating. File Name = test.jpg, MID = 21, File Size = 325663 bytes, File Type = image/jpeg",
                    "timestamp": "2022-08-24T10:05:55Z"
                },
                {
                    "description": "Response received for file reputation query from Cloud. File Name = test.jpg, MID = 21, Disposition = FILE UNKNOWN, Malware = None, Analysis Score = 0, sha256 = 23a9113530549916cd5b410edee79cb5a0fc01233eb9051f9c882a2e7c3fbfbe, upload_action = Recommended to send the file for analysis, verdict_source = AMP",
                    "timestamp": "2022-08-24T10:05:56Z"
                },
                {
                    "description": "File not uploaded for analysis. MID = 21 File SHA256[23a9113530549916cd5b410edee79cb5a0fc01233eb9051f9c882a2e7c3fbfbe] file mime[image/jpeg] Reason: The file type is not configured for analysis",
                    "lastEvent": true,
                    "timestamp": "2022-08-24T10:05:56Z"
                }
            ],
            "ampTgCategories": [],
            "attachments": [
                "test.jpg"
            ],
            "direction": "incoming",
            "headerFrom": "t3@test.com",
            "hostName": "esa1.test.eu.iphmx.com (1.1.1.1)",
            "messageSize": "439.29 (KB)",
            "messageStatus": "Quarantined by Content Filters",
            "mid": [
                21
            ],
            "midHeader": "<CAMuXvaVQMGq8uzJQXmfyoYQB55rOCJ0nW9OKncfnuCAnEc5S4g@mail.gmail.com>",
            "recipient": [
                "test@test.com"
            ],
            "sdrAge": "30 days (or greater)",
            "sdrCategory": "N/A",
            "sdrReputation": "Neutral",
            "sdrThreatLevels": "3",
            "sender": "t3@test.com",
            "senderGroup": "ACCEPTLIST",
            "sendingHostSummary": {},
            "showAMPDetails": true,
            "smtpAuthId": "",
            "subject": "Fwd: test12345",
            "timestamp": "2022-08-24T10:05:52Z"
        }
    }
}

Human Readable Output

Message AMP Report Details

Found AMP details for message ID 21.

Mid All Icid Subject Sender Recipient Attachments Timestamp Message Size Message Status Direction Sender Group
21 1269 Fwd: test12345 t3@test.com test@test.com test.jpg 2022-08-24T10:05:52Z 439.29 (KB) Quarantined by Content Filters incoming ACCEPTLIST

Message AMP Report Details Summary

Description Timestamp
File reputation query initiating. File Name = test.jpg, MID = 21, File Size = 325663 bytes, File Type = image/jpeg 2022-08-24T10:05:55Z
Response received for file reputation query from Cloud. File Name = test.jpg, MID = 21, Disposition = FILE UNKNOWN, Malware = None, Analysis Score = 0, sha256 = 23a9113530549916cd5b410edee79cb5a0fc01233eb9051f9c882a2e7c3fbfbe, upload_action = Recommended to send the file for analysis, verdict_source = AMP 2022-08-24T10:05:56Z
File not uploaded for analysis. MID = 21 File SHA256[23a9113530549916cd5b410edee79cb5a0fc01233eb9051f9c882a2e7c3fbfbe] file mime[image/jpeg] Reason: The file type is not configured for analysis 2022-08-24T10:05:56Z

cisco-sma-message-dlp-details-get


Get message DLP summary details.

Base Command

cisco-sma-message-dlp-details-get

Input

Argument Name Description Required
serial_number Email gateway serial number. Required
message_ids Message ID list. Required

Context Output

Path Type Description
CiscoSMA.DLPDetail.direction String Message direction, incoming or outgoing.
CiscoSMA.DLPDetail.smtpAuthId String SMTP auth ID.
CiscoSMA.DLPDetail.sdrAge String Sender Domain Reputation age.
CiscoSMA.DLPDetail.sender String Message sender email address.
CiscoSMA.DLPDetail.midHeader String Message ID header.
CiscoSMA.DLPDetail.timestamp String Email message time.
CiscoSMA.DLPDetail.sdrCategory String Sender Domain Reputation category.
CiscoSMA.DLPDetail.hostName String Email gateway hostname.
CiscoSMA.DLPDetail.mid Number Message ID.
CiscoSMA.DLPDetail.attachments String Message attachments.
CiscoSMA.DLPDetail.messageSize String Email message size.
CiscoSMA.DLPDetail.dlpDetails.violationSeverity String DLP details violation severity.
CiscoSMA.DLPDetail.dlpDetails.dlpMatchedContent.messagePartMatch.classifier String DLP matched content classifier.
CiscoSMA.DLPDetail.dlpDetails.dlpMatchedContent.messagePartMatch.classifierMatch String DLP matched content classifier match.
CiscoSMA.DLPDetail.dlpDetails.dlpMatchedContent.messagePart String DLP matched content message part.
CiscoSMA.DLPDetail.dlpDetails.mid String DLP message ID.
CiscoSMA.DLPDetail.dlpDetails.riskFactor Number DLP risk factor.
CiscoSMA.DLPDetail.dlpDetails.dlpPolicy String DLP policy.
CiscoSMA.DLPDetail.sdrThreatLevels String Sender Domain Reputation threat levels.
CiscoSMA.DLPDetail.sdrReputation String Sender Domain Reputation.
CiscoSMA.DLPDetail.messageStatus String Message delivery status.
CiscoSMA.DLPDetail.allIcid Number ICIDs list.
CiscoSMA.DLPDetail.senderGroup String Matched sender group.
CiscoSMA.DLPDetail.recipient String Message recipient email address.
CiscoSMA.DLPDetail.subject String Email message subject.
CiscoSMA.DLPDetail.headerFrom String Email header from.

Command example

!cisco-sma-message-dlp-details-get message_ids=84 serial_number=423ADC9EBD9C5F1A7A64-B81D2582608C

Context Example

{
    "CiscoSMA": {
        "DLPDetail": {
            "allIcid": [
                3862
            ],
            "ampTgCategories": [],
            "attachments": "",
            "direction": "outgoing",
            "dlpDetails": {
                "dlpMatchedContent": [
                    {
                        "messagePart": "Message",
                        "messagePartMatch": [
                            {
                                "classifier": "Credit Card Numbers",
                                "classifierMatch": [
                                    "CVV Code Country/Currency Result
                                    Amex 374245455400126 05/2023 Success
                                    Amex 378282246310005",
                                    "Visa 4917484589897107",
                                    "Visa 4263982640269299 (3 matches)",
                                ]
                            }
                        ]
                    }
                ],
                "dlpPolicy": "PCI-DSS (Payment Card Industry Data Security Standard)",
                "mid": 84,
                "riskFactor": 72,
                "violationSeverity": "HIGH"
            },
            "headerFrom": "test@test.com",
            "hostName": "esa2.test.eu.iphmx.com (2.2.2.2)",
            "messageSize": "84.56 (KB)",
            "messageStatus": "Delivered",
            "mid": [
                84
            ],
            "midHeader": "<AM5PR10MB1649CD2104EBDB7ACB849744B6779@AM5PR10MB1649.EURPRD10.PROD.OUTLOOK.COM>",
            "recipient": [
                "t1@test.com"
            ],
            "sender": "test@test.com",
            "senderGroup": "RELAY_O365",
            "sendingHostSummary": {},
            "showDLPDetails": true,
            "smtpAuthId": "",
            "subject": "Fw: Re: ",
            "timestamp": "2022-08-28T06:56:26Z"
        }
    }
}

Human Readable Output

Message DLP Report Details

Found DLP details for message ID 84.

Mid All Icid Subject Sender Recipient Timestamp Message Size Message Status Direction Sender Group
84 3862 Fw: Re: test@test.com t1@test.com 2022-08-28T06:56:26Z 84.56 (KB) Delivered outgoing RELAY_O365

Message DLP Report Details Summary

Mid Violation Severity Risk Factor Dlp Policy
84 HIGH 72 PCI-DSS (Payment Card Industry Data Security Standard)

cisco-sma-message-url-details-get


Get message URL summary details.

Base Command

cisco-sma-message-url-details-get

Input

Argument Name Description Required
serial_number Email gateway serial number. Required
message_ids Message ID list. Required

Context Output

Path Type Description
CiscoSMA.URLDetail.sdrAge String Sender Domain Reputation age.
CiscoSMA.URLDetail.attachments String Message attachments.
CiscoSMA.URLDetail.showURLDetails Boolean Whether to show URL event details.
CiscoSMA.URLDetail.urlDetails.timestamp String URL event details timestamp.
CiscoSMA.URLDetail.urlDetails.description String URL event details description.
CiscoSMA.URLDetail.hostName String Email gateway hostname.
CiscoSMA.URLDetail.direction String Message direction, incoming or outgoing.
CiscoSMA.URLDetail.messageStatus String Message delivery status.
CiscoSMA.URLDetail.senderGroup String Matched sender group.
CiscoSMA.URLDetail.subject String Email message subject.
CiscoSMA.URLDetail.sdrCategory String Sender Domain Reputation category.
CiscoSMA.URLDetail.mid Number Message ID.
CiscoSMA.URLDetail.smtpAuthId String SMTP auth ID.
CiscoSMA.URLDetail.midHeader String Message ID header.
CiscoSMA.URLDetail.timestamp String Email message time.
CiscoSMA.URLDetail.messageSize String Email message size.
CiscoSMA.URLDetail.sdrThreatLevels String Sender Domain Reputation threat levels.
CiscoSMA.URLDetail.sdrReputation String Sender Domain Reputation.
CiscoSMA.URLDetail.recipient String Message recipient Email address.
CiscoSMA.URLDetail.sender String Message sender email address.
CiscoSMA.URLDetail.allIcid Number ICIDs list.
CiscoSMA.URLDetail.headerFrom String Email header from.

Command example

!cisco-sma-message-url-details-get message_ids=21 serial_number=42356DFA5D016457B182-3616BA148E19

Context Example

{
    "CiscoSMA": {
        "URLDetail": {
            "allIcid": [
                1269
            ],
            "ampTgCategories": [],
            "attachments": [
                "test.jpg"
            ],
            "direction": "incoming",
            "headerFrom": "t3@test.com",
            "hostName": "esa1.test.eu.iphmx.com (1.1.1.1)",
            "messageSize": "439.29 (KB)",
            "messageStatus": "Quarantined by Content Filters",
            "mid": [
                21
            ],
            "midHeader": "<CAMuXvaVQMGq8uzJQXmfyoYQB55rOCJ0nW9OKncfnuCAnEc5S4g@mail.gmail.com>",
            "recipient": [
                "test@test.com"
            ],
            "sdrAge": "30 days (or greater)",
            "sdrCategory": "N/A",
            "sdrReputation": "Neutral",
            "sdrThreatLevels": "3",
            "sender": "t3@test.com",
            "senderGroup": "ACCEPTLIST",
            "sendingHostSummary": {},
            "showURLDetails": true,
            "smtpAuthId": "",
            "subject": "Fwd: test12345",
            "timestamp": "2022-08-24T10:05:52Z",
            "urlDetails": [
                {
                    "description": "Message 21 URL: http://9.9.9.9:8080/ , URL reputation: -6.8, Condition: URL Reputation Rule.",
                    "timestamp": "2022-08-24T10:05:56Z"
                },
                {
                    "description": "Message 21 URL: https://test.com/x1OrRZcf/onIpchhYNy4wy9f4/ , URL reputation: -6.6, Condition: URL Reputation Rule.",
                    "timestamp": "2022-08-24T10:05:56Z"
                },
                {
                    "description": "Message 21 URL: http://9.9.9.9:8080 , URL reputation: -6.8, Condition: URL Reputation Rule.",
                    "timestamp": "2022-08-24T10:05:56Z"
                }
            ]
        }
    }
}

Human Readable Output

Message URL Report Details

Found URL details for message ID 21.

Mid All Icid Subject Sender Recipient Attachments Timestamp Message Size Message Status Direction Sender Group
21 1269 Fwd: test12345 t3@test.com test@test.com test.jpg 2022-08-24T10:05:52Z 439.29 (KB) Quarantined by Content Filters incoming ACCEPTLIST

Message URL Report Details Summary

Description Timestamp
Message 21 URL: http://9.9.9.9:8080/ , URL reputation: -6.8, Condition: URL Reputation Rule. 2022-08-24T10:05:56Z
Message 21 URL: https://test.com/test/test/ , URL reputation: -6.6, Condition: URL Reputation Rule. 2022-08-24T10:05:56Z
Message 21 URL: http://9.9.9.9:8080 , URL reputation: -6.8, Condition: URL Reputation Rule. 2022-08-24T10:05:56Z

cisco-sma-report-get


Get statistics reports.
Note that each report type is compatible with different arguments.
Refer to the following link (“ESA Reporting” section in the file) in order to view the dedicated arguments for each report type.
https://www.cisco.com/c/dam/en/us/td/docs/security/security_management/sma/sma12-0/AsyncOS-API-Addendum-GD_General_Deployment.xlsx.

Base Command

cisco-sma-report-get

Input

Argument Name Description Required
report_type Report Type. Possible values are: mail_incoming_traffic_summary, reporting_system, mail_vof_threat_summary, mail_vof_specific_threat_summary, mail_amp_threat_summary. Default is mail_incoming_traffic_summary. Optional
custom_report_type Custom report type.
Specify this argument in order to get a report that does not exist in the report_type argument.
Optional
start_date Start date in ISO format or <number> <time unit>,
e.g., 2022-01-01T00:00:00.000Z, 12 hours, 7 days, 3 months, now.
Required
end_date End date in ISO format or <number> <time unit>,
e.g., 2022-01-01T00:00:00.000Z, 12 hours, 7 days, 3 months, now.
Required
device_group_name The device group name. Default is Hosted_Cluster. Optional
device_name The device name. Optional
order_by Specify the attribute by which to order the data in the response. For example, orderBy=total_clean_recipients. Optional
order_dir The report order direction. Specify sort direction. Possible values are: asc, desc. Optional
top Specify the number of records with the highest values to return. Optional
filter_value The value to search for. Optional
filter_by The filter field to use. Filter the data to be retrieved according to the filter property and value. Optional
filter_operator Filter the response data based on the value specified. Possible values are: begins_with, is. Optional

Context Output

Path Type Description
CiscoSMA.Report.type String Report type.
CiscoSMA.Report.resultSet Number Report results summary.

Command example

!cisco-sma-report-get start_date=2weeks end_date=now device_group_name=Hosted_Cluster report_type=mail_incoming_traffic_summary

Context Example

{
    "CiscoSMA": {
        "Report": {
            "resultSet": [
                {
                    "failed_dkim": 0
                },
                {
                    "total_graymail_recipients": 6
                },
                {
                    "detected_spam": 35
                },
                {
                    "malicious_url": 2
                },
                {
                    "total_spoofed_emails": 0
                },
                {
                    "verif_decrypt_success": 0
                },
                {
                    "detected_virus": 0
                },
                {
                    "threat_content_filter": 1
                },
                {
                    "blocked_invalid_recipient": 6
                },
                {
                    "blocked_sdr": 0
                },
                {
                    "marketing_mail": 5
                },
                {
                    "ims_spam_increment_over_case": 0
                },
                {
                    "total_mailbox_auto_remediated_recipients": 0
                },
                {
                    "detected_spam_certain": 35
                },
                {
                    "detected_spam_suspect": 0
                },
                {
                    "blocked_dmarc": 0
                },
                {
                    "total_threat_recipients": 3498
                },
                {
                    "total_recipients": 4069
                },
                {
                    "verif_decrypt_fail": 0
                },
                {
                    "detected_amp": 0
                },
                {
                    "bulk_mail": 1
                },
                {
                    "social_mail": 0
                },
                {
                    "total_clean_recipients": 565
                },
                {
                    "detected_virus_per_msg": 0
                },
                {
                    "failed_spf": 0
                },
                {
                    "blocked_reputation": 3454
                }
            ],
            "type": "mail_incoming_traffic_summary",
            "uuid": "54db5cef-36a4-44a7-a121-37d9fb4e3971"
        }
    }
}

Human Readable Output

Report type: mail_incoming_traffic_summary

Report UUID: 54db5cef-36a4-44a7-a121-37d9fb4e3971

Blocked Dmarc Blocked Invalid Recipient Blocked Reputation Blocked Sdr Bulk Mail Detected Amp Detected Spam Detected Spam Certain Detected Spam Suspect Detected Virus Detected Virus Per Msg Failed Dkim Failed Spf Ims Spam Increment Over Case Malicious Url Marketing Mail Social Mail Threat Content Filter Total Clean Recipients Total Graymail Recipients Total Mailbox Auto Remediated Recipients Total Recipients Total Spoofed Emails Total Threat Recipients Verif Decrypt Fail Verif Decrypt Success
0 6 3454 0 1 0 35 35 0 0 0 0 0 0 2 5 0 1 565 6 0 4069 0 3498 0 0

Configuration parameters

  • base_url — Server URL (required)
  • credentials — Username (required)
  • max_fetch — Maximum incidents per fetch
  • first_fetch — First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days).
  • filter_by — Filter by
  • filter_operator — Filter operator
  • filter_value — Filter value
  • recipient_filter_operator — Recipient filter operator
  • recipient_filter_value — Recipient filter value
  • timeout — Timeout
  • proxy — Use system proxy settings
  • insecure — Trust any certificate (not secure)
  • incidentType — Incident type
  • incidentFetchInterval — Incidents Fetch Interval
  • isFetch — Fetch incidents

Commands (15)

  • cisco-sma-list-entry-add

    Add spam quarantine blocklist/safelist entry.

  • cisco-sma-list-entry-append

    Append spam quarantine blocklist/safelist entry.

  • cisco-sma-list-entry-delete

    Delete a spam quarantine blocklist/safelist entry.

  • cisco-sma-list-entry-edit

    Edit the spam quarantine blocklist/safelist entry. Using this command will override the existing value.

  • cisco-sma-list-entry-get

    Get spam quarantine blocklist/safelist entry.

  • cisco-sma-message-amp-details-get

    Get message AMP summary details.

  • cisco-sma-message-details-get

    Get more details on the message.

  • cisco-sma-message-dlp-details-get

    Get message DLP summary details.

  • cisco-sma-message-search

    Search tracking messages.

  • cisco-sma-message-url-details-get

    Get message URL summary details.

  • cisco-sma-report-get

    Get statistics reports. Note that each report type is compatible with different arguments. Refer to the following link ("ESA Reporting" section in the file) in order to view the dedicated arguments for each report type. https://www.cisco.com/c/dam/en/us/td/docs/security/security_management/sma/sma12-0/AsyncOS-API-Addendum-GD_General_Deployment.xlsx.

  • cisco-sma-spam-quarantine-message-delete

    Delete spam quarantined message.

  • cisco-sma-spam-quarantine-message-get

    Get spam quarantine message.

  • cisco-sma-spam-quarantine-message-release

    Release spam quarantined message.

  • cisco-sma-spam-quarantine-message-search

    Search messages in the spam quarantine.

import uuid
from collections.abc import Callable

import demistomock as demisto  # noqa: F401
from CommonServerPython import *  # noqa: F401

JWT_TOKEN_EXPIRATION_PERIOD = 30
DEFAULT_FETCH = 50
TIMESTAMP_FORMAT = "%d %b %Y %H:%M:%S (%Z)"
QUARANTINE_TIMESTAMP_FORMAT = "%d %b %Y %H:%M (%Z)"

DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
CISCO_TIME_FORMAT = "%Y-%m-%dT%H:%M:00.000Z"
CISCO_REPORTING_TIME_FORMAT = "%Y-%m-%dT%H:00:00.000Z"

MIN_PAGE_NUMBER = 1
MIN_LIMIT = 1
MIN_PAGE_SIZE = 1
MAX_PAGE_SIZE = 100
REQUEST_MAX_PULL = 100

QUARANTINE_TYPE = "spam"
VIEW_ACTION = "view"
RELEASE_ACTION = "release"
ADD_ACTION = "add"
APPEND_ACTION = "append"
EDIT_ACTION = "edit"


class Client(BaseClient):
    """Client class to interact with Cisco SMA API."""

    def __init__(self, server_url: str, username: str, password: str, verify: bool, proxy: bool, timeout: None | int = 60):
        super().__init__(base_url=server_url, headers={}, verify=verify, proxy=proxy, timeout=timeout)
        self.username = username
        self.password = password
        self.handle_request_headers()

    def handle_request_headers(self):
        """Retrieve and save to integration context JWT token for authorized client class API requests."""
        integration_context = get_integration_context()
        jwt_token = integration_context.get("jwt_token")
        jwt_token_issued_time = integration_context.get("jwt_token_issued_time")
        if jwt_token and jwt_token_issued_time >= datetime.timestamp(
            datetime.now() - timedelta(minutes=JWT_TOKEN_EXPIRATION_PERIOD)
        ):
            self._headers["jwtToken"] = jwt_token
        else:
            jwt_token = self.retrieve_jwt_token()
            set_integration_context({"jwt_token": jwt_token, "jwt_token_issued_time": time.time()})
            self._headers["jwtToken"] = jwt_token

    def retrieve_jwt_token(self) -> str:
        """
        Retrieve JWT token from Cisco SMA.

        Returns:
            str: JWT token from Cisco SMA.
        """
        data = {
            "data": {
                "userName": b64_encode(self.username),
                "passphrase": b64_encode(self.password),
            }
        }
        try:
            response = self._http_request("POST", "login", json_data=data)
            return dict_safe_get(response, ["data", "jwtToken"])

        except DemistoException as e:
            if hasattr(e.res, "status_code") and e.res.status_code == 401:
                raise Exception("Authorization Error: make sure username and password are set correctly.")
            raise e

    def spam_quarantine_message_search_request(
        self,
        quarantine_type: str,
        start_date: str,
        end_date: str,
        offset: int,
        limit: int,
        filter_by: str = None,
        filter_operator: str = None,
        filter_value: str = None,
        recipient_filter_operator: str = None,
        recipient_filter_value: str = None,
        order_by: str = None,
        order_dir: str = None,
    ) -> Dict[str, Any]:
        """
        Search spam quarantine messages.

        Args:
            quarantine_type (str): Quarantine type.
            start_date (str): Start date in ISO format.
            end_date (str): End date in ISO format.
            offset (int): Offset of results to skip.
            limit (int): Limit of results to retrieve.
            filter_by (str, Optional): Filter by field.
                Required if filter_operator/filter_value are specified. Defaults to None.
            filter_operator (str, Optional): Filter operator.
                Required if filter_by/filter_value are specified. Defaults to None.
            filter_value (str, Optional): Filter value.
                Required if filter_by/filter_operator are specified. Defaults to None.
            recipient_filter_operator (str, Optional): Recipient filter operator.
                Required if recipient_filter_value is specified. Defaults to None.
            recipient_filter_value (str, Optional): Recipient address filter.
                Required if recipient_filter_operator is specified. Defaults to None.
            order_by (str, Optional): Results order by field.
                Required if order_dir is specified. Defaults to None.
            order_dir (str, Optional): Results order direction.
                Required if order_by is specified. Defaults to None.

        Returns:
            Dict[str, Any]: API response from Cisco SMA.
        """

        params = assign_params(
            quarantineType=quarantine_type,
            startDate=start_date,
            endDate=end_date,
            filterBy=filter_by,
            filterOperator=filter_operator,
            filterValue=filter_value,
            envelopeRecipientFilterOperator=recipient_filter_operator,
            envelopeRecipientFilterValue=recipient_filter_value,
            offset=offset,
            limit=limit,
            orderBy=order_by,
            orderDir=order_dir,
        )

        return self._http_request("GET", "quarantine/messages", params=params)

    def spam_quarantine_message_get_request(self, quarantine_type: str, message_id: str) -> Dict[str, Any]:
        """
        Get spam quarantine message.

        Args:
            quarantine_type (str): Quarantine Type.
            message_id (str): Message ID.

        Returns:
            Dict[str, Any]: API response from Cisco SMA.
        """

        params = assign_params(quarantineType=quarantine_type, mid=message_id)

        return self._http_request("GET", "quarantine/messages/details", params=params)

    def spam_quarantine_message_release_request(
        self, action: str, quarantine_type: str, message_ids: List[int]
    ) -> Dict[str, Any]:
        """
        Release spam quarantine message.

        Args:
            action (str): Release action.
            quarantine_type (str): Quarantine type.
            message_ids (List[int]): Message IDs list.

        Returns:
            Dict[str, Any]: API response from Cisco SMA.
        """
        data = assign_params(action=action, mids=message_ids, quarantineType=quarantine_type)

        return self._http_request("POST", "quarantine/messages", json_data=data)

    def spam_quarantine_message_delete_request(self, quarantine_type: str, message_ids: List[int]) -> Dict[str, Any]:
        """
        Delete spam quarantine message.

        Args:
            quarantine_type (str): Quarantine type.
            message_ids (List[int]): Message IDs list.

        Returns:
            Dict[str, Any]: API response from Cisco SMA.
        """
        data = assign_params(mids=message_ids, quarantineType=quarantine_type)

        return self._http_request("DELETE", "quarantine/messages", json_data=data)

    def list_entry_get_request(
        self,
        entry_type: str,
        action: str,
        limit: int,
        offset: int,
        quarantine_type: str,
        view_by: str,
        order_by: str = None,
        order_dir: str = None,
        search: str = None,
    ) -> Dict[str, Any]:
        """
        List spam quarantine blocklist/safelist.

        Args:
            entry_type (str): Blocklist/Safelist list type.
            action (str): List action.
            limit (int): Limit of results to retrieve.
            offset (int): Offset of results to skip.
            quarantine_type (str): Quarantine type.
            view_by (str): View list entry results by recipient/sender.
            order_by (str, Optional): Results order by field.
                Required if order_dir is specified. Defaults to None.
            order_dir (str, Optional): Results order direction.
                Required if order_by is specified. Defaults to None.
            search (str, Optional): Search for results in blocklist/safelist. Defaults to None.

        Returns:
            Dict[str, Any]: API response from Cisco SMA.
        """

        params = assign_params(
            action=action,
            limit=limit,
            offset=offset,
            orderBy=order_by,
            orderDir=order_dir,
            quarantineType=quarantine_type,
            viewBy=view_by,
            search=search,
        )

        return self._http_request("GET", f"quarantine/{entry_type}", params=params)

    def list_entry_add_request(
        self,
        entry_type: str,
        quarantine_type: str,
        action: str,
        view_by: str,
        recipient_addresses: List[str] = None,
        sender_list: List[str] = None,
        sender_addresses: List[str] = None,
        recipient_list: List[str] = None,
    ) -> Dict[str, Any]:
        """
        Add spam quarantine blocklist/safelist entries.

        Args:
            entry_type (str): Blocklist/Safelist list type.
            quarantine_type (str): Quarantine type.
            action (str): Add action.
            view_by (str): Add list entry results by recipient/sender.
            recipient_addresses (List[str], Optional): Recipient addresses list to add. Defaults to None.
            sender_list (List[str], Optional): Sender addresses list to add. Defaults to None.
            sender_addresses (List[str], Optional): Sender addresses list to add. Defaults to None.
            recipient_list (List[str], Optional): Recipient addresses list to add. Defaults to None.

        Returns:
            Dict[str, Any]: API response from Cisco SMA.
        """

        data = assign_params(
            action=action,
            quarantineType=quarantine_type,
            viewBy=view_by,
            recipientAddresses=recipient_addresses,
            senderAddresses=sender_addresses,
            recipientList=recipient_list,
            senderList=sender_list,
        )

        return self._http_request("POST", f"quarantine/{entry_type}", json_data=data)

    def list_entry_append_request(
        self,
        entry_type: str,
        quarantine_type: str,
        action: str,
        view_by: str,
        recipient_addresses: List[str] = None,
        sender_list: List[str] = None,
        sender_addresses: List[str] = None,
        recipient_list: List[str] = None,
    ) -> Dict[str, Any]:
        """
        Append spam quarantine blocklist/safelist entries.

        Args:
            entry_type (str): Blocklist/Safelist list type.
            quarantine_type (str): Quarantine type.
            action (str): Append action.
            view_by (str): Append list entry results by recipient/sender.
            recipient_addresses (List[str], Optional): Recipient addresses list to append. Defaults to None.
            sender_list (List[str], Optional): Sender addresses list to append. Defaults to None.
            sender_addresses (List[str], Optional): Sender addresses list to append. Defaults to None.
            recipient_list (List[str], Optional): Recipient addresses list to append. Defaults to None.

        Returns:
            Dict[str, Any]: API response from Cisco SMA.
        """

        data = assign_params(
            action=action,
            quarantineType=quarantine_type,
            viewBy=view_by,
            recipientAddresses=recipient_addresses,
            senderAddresses=sender_addresses,
            recipientList=recipient_list,
            senderList=sender_list,
        )

        return self._http_request("POST", f"quarantine/{entry_type}", json_data=data)

    def list_entry_edit_request(
        self,
        entry_type: str,
        quarantine_type: str,
        action: str,
        view_by: str,
        recipient_addresses: List[str] = None,
        sender_list: List[str] = None,
        sender_addresses: List[str] = None,
        recipient_list: List[str] = None,
    ) -> Dict[str, Any]:
        """
        Edit spam quarantine blocklist/safelist entries.

        Args:
            entry_type (str): Blocklist/Safelist list type.
            quarantine_type (str): Quarantine type.
            action (str): Edit action.
            view_by (str): Edit list entry results by recipient/sender.
            recipient_addresses (List[str], Optional): Recipient addresses list to edit Defaults to None.
            sender_list (List[str], Optional): Sender addresses list to edit Defaults to None.
            sender_addresses (List[str], Optional): Sender addresses list to edit Defaults to None.
            recipient_list (List[str], Optional): Recipient addresses list to edit Defaults to None.

        Returns:
            Dict[str, Any]: API response from Cisco SMA.
        """
        data = assign_params(
            action=action,
            quarantineType=quarantine_type,
            viewBy=view_by,
            recipientAddresses=recipient_addresses,
            senderAddresses=sender_addresses,
            recipientList=recipient_list,
            senderList=sender_list,
        )

        return self._http_request("POST", f"quarantine/{entry_type}", json_data=data)

    def list_entry_delete_request(
        self,
        entry_type: str,
        quarantine_type: str,
        view_by: str,
        recipient_list: List[str] = None,
        sender_list: List[str] = None,
    ) -> Dict[str, Any]:
        """
        Delete spam quarantine blocklist/safelist entries.

        Args:
            entry_type (str): Blocklist/Safelist list type.
            quarantine_type (str): Quarantine type.
            view_by (str): Delete list entry results by recipient/sender.
            recipient_list (List[str], Optional): Recipient list to delete. Defaults to None.
            sender_list (List[str], Optional): Sender list to delete. Defaults to None.

        Returns:
            Dict[str, Any]: API response from Cisco SMA.
        """
        data = assign_params(
            quarantineType=quarantine_type,
            recipientList=recipient_list,
            senderList=sender_list,
            viewBy=view_by,
        )

        return self._http_request("DELETE", f"quarantine/{entry_type}", json_data=data)

    def message_search_request(
        self,
        start_date: str,
        end_date: str,
        offset: int,
        limit: int,
        search_option: str,
        cisco_host: str,
        sender_filter_operator: str = None,
        sender_filter_value: str = None,
        recipient_filter_operator: str = None,
        recipient_filter_value: str = None,
        subject_filter_operator: str = None,
        subject_filter_value: str = None,
        attachment_name_operator: str = None,
        attachment_name_value: str = None,
        file_sha_256: str = None,
        custom_query: str = None,
    ) -> Dict[str, Any]:
        """
        Search tracking messages.

        Args:
            start_date (str): Start date in ISO format.
            end_date (str): End date in ISO format.
            offset (int): Offset of results to skip.
            limit (int): Limit of results to retrieve.
            search_option (str): Messages option.
            cisco_host (str): Cisco host.
            sender_filter_operator (str, Optional): Sender filter operator.
                Required if sender_filter_value is specified. Defaults to None.
            sender_filter_value (str, Optional): Sender address filter.
                Required if sender_filter_operator is specified. Defaults to None.
            recipient_filter_operator (str, Optional): Recipient filter operator.
                Required if recipient_filter_value is specified. Defaults to None.
            recipient_filter_value (str, Optional): Recipient address filter.
                Required if recipient_filter_operator is specified. Defaults to None.
            subject_filter_operator (str, Optional): Subject filter operator.
                Required if subject_filter_value is specified. Defaults to None.
            subject_filter_value (str, Optional): Subject address filter.
                Required if subject_filter_operator is specified. Defaults to None.
            attachment_name_operator (str, Optional): Attachment name operator.
                Required if attachment_name_value is specified. Defaults to None.
            attachment_name_value (str, Optional): Attachment name filter.
                Required if attachment_name_operator is specified. Defaults to None.
            file_sha_256 (str, Optional): SHA256 must be 64 characters long
            and can contain only "0-9" and "a-f" symbols.
            e.g. e0d123e5f316bef78bfdf5a008837577e0d123e5f316bef78bfdf5a008837577. Defaults to None.
            custom_query (str, Optional): Custom query for cisco SMA advanced filters. Defaults to None.
        Returns:
            Dict[str, Any]: API response from Cisco SMA.
        """

        params = assign_params(
            startDate=start_date,
            endDate=end_date,
            envelopeSenderfilterOperator=sender_filter_operator,
            envelopeSenderfilterValue=sender_filter_value,
            envelopeRecipientfilterOperator=recipient_filter_operator,
            envelopeRecipientfilterValue=recipient_filter_value,
            subjectfilterOperator=subject_filter_operator,
            subjectfilterValue=subject_filter_value,
            ciscoHost=cisco_host,
            searchOption=search_option,
            offset=offset,
            limit=limit,
            fileSha256=file_sha_256,
            attachmentNameOperator=attachment_name_operator,
            attachmentNameValue=attachment_name_value,
            **format_custom_query_args(custom_query),
        )

        return self._http_request("GET", "message-tracking/messages", params=params, params_parser=urllib.parse.quote)

    def message_details_get_request(
        self,
        serial_number: str,
        message_ids: List[int],
        injection_connection_id: int = None,
        delivery_connection_id: int = None,
    ) -> Dict[str, Any]:
        """
        Get message details.

        Args:
            serial_number (str): mail Gateway serial number.
            message_id (List[int]): Message ID List.
            injection_connection_id (int, Optional): ICID, injection connection ID. Defaults to None.
            delivery_connection_id (int, Optional): DCID, delivery connection ID. Defaults to None.

        Returns:
            Dict[str, Any]: API response from Cisco SMA.
        """
        params = assign_params(
            serialNumber=serial_number,
            mid=message_ids,
            icid=injection_connection_id,
            dcid=delivery_connection_id,
        )

        return self._http_request("GET", "message-tracking/details", params=params)

    def message_amp_details_get_request(self, serial_number: str, message_ids: List[int]) -> Dict[str, Any]:
        """
        Get message AMP report details.

        Args:
            serial_number (str): mail Gateway serial number.
            message_id (List[int]): Message ID List.

        Returns:
            Dict[str, Any]: API response from Cisco SMA.
        """
        params = assign_params(
            serialNumber=serial_number,
            mid=message_ids,
        )

        return self._http_request("GET", "message-tracking/amp-details", params=params)

    def message_dlp_details_get_request(self, serial_number: str, message_ids: List[int]) -> Dict[str, Any]:
        """
        Get message DLP report details.

        Args:
            serial_number (str): mail Gateway serial number.
            message_id (List[int]): Message ID List.

        Returns:
            Dict[str, Any]: API response from Cisco SMA.
        """
        params = assign_params(
            serialNumber=serial_number,
            mid=message_ids,
        )

        return self._http_request("GET", "message-tracking/dlp-details", params=params)

    def message_url_details_get_request(self, serial_number: str, message_ids: List[int]) -> Dict[str, Any]:
        """
        Get message URL report details.

        Args:
            serial_number (str): mail Gateway serial number.
            message_id (List[int]): Message ID List.

        Returns:
            Dict[str, Any]: API response from Cisco SMA.
        """
        params = assign_params(
            serialNumber=serial_number,
            mid=message_ids,
        )

        return self._http_request("GET", "message-tracking/url-details", params=params)

    def report_get_request(
        self,
        report_type: str,
        start_date: str,
        end_date: str,
        device_type: str,
        device_group_name: str = None,
        device_name: str = None,
        order_by: str = None,
        order_dir: str = None,
        top: str = None,
        filter_value: str = None,
        filter_by: str = None,
        filter_operator: str = None,
    ) -> Dict[str, Any]:
        """
        Get statistics reports.

        Args:
            report_type (str): Report type.
            start_date (str): Start date.
            end_date (str): End date.
            device_type (str): Device type.
            device_group_name (str, optional): Device group name. Defaults to None.
            device_name (str, optional): Device name. Defaults to None.
            order_by (str, optional): Order results by field. Defaults to None.
            order_dir (str, optional): Order direction. Defaults to None.
            top (str, optional): Number of records with the highest values to return. Defaults to None.
            filter_value (str, optional): Filter value. Defaults to None.
            filter_by (str, optional): Filter by field. Defaults to None.
            filter_operator (str, optional): Filter operator. Defaults to None.

        Returns:
            Dict[str, Any]: API response from Cisco SMA.
        """
        params = assign_params(
            startDate=start_date,
            endDate=end_date,
            device_type=device_type,
            device_group_name=device_group_name,
            device_name=device_name,
            orderBy=order_by,
            orderDir=order_dir,
            top=top,
            filterValue=filter_value,
            filterBy=filter_by,
            filterOperator=filter_operator,
        )

        return self._http_request("GET", f"reporting/{report_type}", params=params)


def format_custom_query_args(custom_query: str = None) -> Dict[str, Any]:
    """
    Format custom query arguments for tracking message advanced filters.

    Args:
        custom_query (str, optional): Custom query of advanced filters. Defaults to None.

    Returns:
        Dict[str, Any]: Formatted dictionary of custom query arguments.
    """
    try:
        if custom_query:
            return dict(field.split("=") for field in custom_query.split(";"))
        else:
            return {}
    except ValueError:
        raise ValueError('Please validate the format of argument "custom_query". For example: "key1=value1;key2=value2".')


def format_datetime(time_expression: str) -> str:
    """
    Format string from time expression to Cisco SMA datetime format.

    Args:
        time_expression (str): Time expression or ISO format datetime.

    Returns:
        str: Datetime formatted string.
    """
    return arg_to_datetime(time_expression).strftime(CISCO_TIME_FORMAT)  # type: ignore


def format_reporting_datetime(time_expression: str) -> str:
    """
    Format string from time expression to Cisco SMA reporting datetime format.

    Args:
        time_expression (str): Time expression or ISO format datetime.

    Returns:
        str: Datetime formatted string.
    """
    return arg_to_datetime(time_expression).strftime(CISCO_REPORTING_TIME_FORMAT)  # type: ignore


def format_timestamp(timestamp: str, output_format: str = DATETIME_FORMAT) -> str:
    """
    Format Cisco SMA timestamp to datetime string.

    Args:
        timestamp (str): Cisco SMA timestamp.
        output_format (str): The format of the return date.

    Returns:
        str: Datetime formatted string.
    """

    try:
        datetime_res = arg_to_datetime(timestamp)
    except ValueError:
        timestamp = timestamp.replace("GMT ", "GMT")
        datetime_res = arg_to_datetime(timestamp)
    return datetime_res.strftime(output_format)  # type: ignore


def format_number_list_argument(number_list_string: str) -> List[int]:
    """
    Format number list argument to list of integer type.

    Args:
        number_list_string (str): Number list argument.

    Returns:
        List[int]: List of integers.
    """
    return [arg_to_number(number) for number in argToList(number_list_string)]  # type: ignore


def validate_pagination_arguments(page: Optional[int], page_size: Optional[int], limit: Optional[int]):
    """
    Validate pagination arguments, raise error if argument is not valid.

    Args:
        page (int): Page.
        page_size (int): Page Size.
        limit (int): Limit.
    """
    if page and page_size:
        if page_size < MIN_PAGE_SIZE or page_size > MAX_PAGE_SIZE:
            raise ValueError(
                f"page size argument must be greater than or equal to {MIN_PAGE_SIZE} "
                f"and smaller or equal to {MAX_PAGE_SIZE}."
            )

        if page < MIN_PAGE_NUMBER:
            raise ValueError(f"page argument must be equal or greater than {MIN_PAGE_NUMBER}.")
    else:
        if limit and limit < MIN_LIMIT:
            raise ValueError(f"limit argument must be equal or greater than {MIN_LIMIT}.")


def validate_related_arguments(args: Dict[str, Any], related_arguments_list: List[List[str]]):
    """
    Validate correct usage of arguments that are related to each other.

    Args:
        args (Dict[str, Any]): Command arguments.
        related_arguments_list (List[List[str]]): Related arguments list.
    """
    args = {key: value for key, value in args.items() if value != ""}
    for related_arguments in related_arguments_list:
        exist_list = [argument in args for argument in related_arguments]
        if not all(exist_list) and any(exist_list):
            raise ValueError(f"{', '.join(related_arguments)} arguments should be used together but one or more are empty.")


def format_list_entry_arguments(view_by: str, args: Dict[str, Any]) -> Dict[str, Any]:
    """
    Format list entry arguments.

    Args:
        view_by (str): View by recipient/sender.
        args (Dict[str, Any]): Command arguments to format.

    Returns:
        Dict[str, Any]: Formatted list entry arguments.
    """
    if view_by == "recipient":
        if args.get("recipient_addresses") and args.get("sender_list"):
            args["sender_addresses"] = None
            args["recipient_list"] = None
        else:
            raise DemistoException("Please specify recipient_addresses and sender_list arguments when using view_by recipient.")
    elif view_by == "sender":
        if args.get("sender_addresses") and args.get("recipient_list"):
            args["recipient_addresses"] = None
            args["sender_list"] = None
        else:
            raise DemistoException("Please specify sender_addresses and recipient_list arguments when using view_by sender.")
    else:
        raise DemistoException(f'Please check the value of argument "view_by". Valid values are recipient/sender, got {view_by}.')

    return args


def pagination(request_command: Callable, args: Dict[str, Any], **kwargs) -> tuple:
    """
    Executing Manual Pagination (using the page and page size arguments)
    or Automatic Pagination (display a number of total results).

    Args:
        request_command (Callable): The command to execute.
        args (Dict[str, Any]): The command arguments.

    Returns:
        Tuple: output, pagination message for Command Results.
    """
    page = arg_to_number(args.get("page"))
    page_size = arg_to_number(args.get("page_size"))
    limit = arg_to_number(args.get("limit"))

    validate_pagination_arguments(page, page_size, limit)

    if page and page_size:
        offset = page_size * (page - 1)
        output = request_command(offset=offset, limit=page_size, **kwargs).get("data")
        pagination_message = f"Showing page {page}.\n Current page size: {page_size}."
    elif limit:
        output = []
        offset = 0
        while limit > 0:
            page_size = min(limit, REQUEST_MAX_PULL)
            output.extend(request_command(offset=offset, limit=page_size, **kwargs).get("data"))
            limit -= REQUEST_MAX_PULL
            offset += REQUEST_MAX_PULL
        pagination_message = f"Showing {len(output)} rows." if len(output) > 0 else None  # type: ignore
    else:
        pagination_message = "No pagination."
        output = []
        demisto.debug(f"No pagination params -> {pagination_message}")

    return output, pagination_message


def spam_quarantine_message_search_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Search spam quarantine messages.

    Args:
        client (Client): Cisco SMA API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: readable outputs for XSOAR.
    """
    quarantine_type = QUARANTINE_TYPE
    start_date = format_datetime(args["start_date"])
    end_date = format_datetime(args["end_date"])
    filter_by = args.get("filter_by")
    filter_operator = args.get("filter_operator")
    filter_value = args.get("filter_value")
    recipient_filter_operator = args.get("recipient_filter_operator")
    recipient_filter_value = args.get("recipient_filter_value")
    order_by = args.get("order_by")
    order_dir = args.get("order_dir")

    validate_related_arguments(
        args=args,
        related_arguments_list=[
            ["filter_by", "filter_operator", "filter_value"],
            ["recipient_filter_operator", "recipient_filter_value"],
            ["order_by", "order_dir"],
        ],
    )

    output, pagination_message = pagination(
        client.spam_quarantine_message_search_request,
        args=args,
        quarantine_type=quarantine_type,
        start_date=start_date,
        end_date=end_date,
        filter_by=filter_by,
        filter_operator=filter_operator,
        filter_value=filter_value,
        recipient_filter_operator=recipient_filter_operator,
        recipient_filter_value=recipient_filter_value,
        order_by=order_by,
        order_dir=order_dir,
    )

    spam_quarantine_message_lists = [dict(message.get("attributes", {}), mid=message.get("mid")) for message in output]

    readable_output = tableToMarkdown(
        name="Spam Quarantine Messages List",
        metadata=pagination_message,
        t=spam_quarantine_message_lists,
        headers=["mid", "date", "fromAddress", "toAddress", "subject", "size"],
        headerTransform=pascalToSpace,
    )

    return CommandResults(
        readable_output=readable_output,
        outputs_prefix="CiscoSMA.SpamQuarantineMessage",
        outputs_key_field="mid",
        outputs=spam_quarantine_message_lists,
        raw_response=spam_quarantine_message_lists,
    )


def spam_quarantine_message_get_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Get spam quarantine message details.

    Args:
        client (Client): Cisco SMA API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: readable outputs for XSOAR.
    """
    quarantine_type = QUARANTINE_TYPE
    message_id = args["message_id"]

    response: Dict[str, Any] = client.spam_quarantine_message_get_request(quarantine_type, message_id).get("data", [])

    new_message = dict(response.get("attributes", {}), mid=response.get("mid"))
    readable_message = f'Found spam quarantine message with ID: {new_message.get("mid")}'

    readable_output = tableToMarkdown(
        name="Spam Quarantine Message",
        metadata=readable_message,
        t=new_message,
        headers=["mid", "fromAddress", "toAddress", "date", "subject", "attachments"],
        headerTransform=pascalToSpace,
        removeNull=True,
    )

    return CommandResults(
        readable_output=readable_output,
        outputs_prefix="CiscoSMA.SpamQuarantineMessage",
        outputs_key_field="mid",
        outputs=new_message,
        raw_response=response,
    )


def spam_quarantine_message_release_command(client: Client, args: Dict[str, Any]) -> List[CommandResults]:
    """
    Release spam quarantine message.

    Args:
        client (Client): Cisco SMA API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        List[CommandResults]: readable outputs for XSOAR.
    """
    action = RELEASE_ACTION
    quarantine_type = QUARANTINE_TYPE
    message_ids = format_number_list_argument(args["message_ids"])

    command_results_list = []

    for message_id in message_ids:
        response = client.spam_quarantine_message_release_request(action, quarantine_type, [message_id])

        if dict_safe_get(response, ["data", "totalCount"]) == 1:
            readable_output = f"Quarantined message {message_id} successfully released."
        else:
            readable_output = f"Quarantined message {message_id} not found."

        command_results_list.append(CommandResults(readable_output=readable_output))

    return command_results_list


def spam_quarantine_message_delete_command(client: Client, args: Dict[str, Any]) -> List[CommandResults]:
    """
    Delete spam quarantine message details.

    Args:
        client (Client): Cisco SMA API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        List[CommandResults]: readable outputs for XSOAR.
    """
    quarantine_type = QUARANTINE_TYPE
    message_ids = format_number_list_argument(args["message_ids"])

    command_results_list = []

    for message_id in message_ids:
        response = client.spam_quarantine_message_delete_request(quarantine_type, [message_id])

        if dict_safe_get(response, ["data", "totalCount"]) == 1:
            readable_output = f"Quarantined message {message_id} successfully deleted."
        else:
            readable_output = f"Quarantined message {message_id} not found."

        command_results_list.append(CommandResults(readable_output=readable_output))

    return command_results_list


def list_entry_get_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    List spam quarantine blocklist/safelist.

    Args:
        client (Client): Cisco SMA API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: readable outputs for XSOAR.
    """
    entry_type: str = args["entry_type"]
    action = VIEW_ACTION
    order_by = args.get("order_by")
    order_dir = args.get("order_dir")
    quarantine_type = QUARANTINE_TYPE
    view_by = args.get("view_by")
    search = args.get("search")

    validate_related_arguments(args=args, related_arguments_list=[["order_by", "order_dir"]])

    output, pagination_message = pagination(
        client.list_entry_get_request,
        args=args,
        entry_type=entry_type,
        action=action,
        quarantine_type=quarantine_type,
        view_by=view_by,
        order_by=order_by,
        order_dir=order_dir,
        search=search,
    )

    readable_output = tableToMarkdown(
        name=f"{entry_type.title()} Entries",
        metadata=pagination_message,
        t=output,
        headers=["recipientAddress", "senderList"] if view_by == "recipient" else ["senderAddress", "recipientList"],
        headerTransform=pascalToSpace,
    )

    return CommandResults(
        readable_output=readable_output,
        outputs_prefix=f"CiscoSMA.ListEntry.{entry_type.title()}",
        outputs_key_field="recipientAddress" if view_by == "recipient" else "senderAddress",
        outputs=output,
        raw_response=output,
    )


def list_entry_add_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Add spam quarantine blocklist/safelist entries.

    Args:
        client (Client): Cisco SMA API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: readable outputs for XSOAR.
    """
    entry_type = args["entry_type"]
    quarantine_type = QUARANTINE_TYPE
    action = ADD_ACTION
    view_by = args["view_by"]

    formatted_arguments = format_list_entry_arguments(view_by=view_by, args=args)

    recipient_addresses = argToList(formatted_arguments.get("recipient_addresses"))
    sender_list = argToList(formatted_arguments.get("sender_list"))
    sender_addresses = argToList(formatted_arguments.get("sender_addresses"))
    recipient_list = argToList(formatted_arguments.get("recipient_list"))

    response = client.list_entry_add_request(
        entry_type=entry_type,
        quarantine_type=quarantine_type,
        action=action,
        view_by=view_by,
        recipient_addresses=recipient_addresses,
        sender_list=sender_list,
        sender_addresses=sender_addresses,
        recipient_list=recipient_list,
    )

    if view_by == "recipient":
        readable_output = (
            f'Successfully added {", ".join(sender_list)} senders to '
            f'{", ".join(recipient_addresses)} recipients in {entry_type}.'
        )
    else:
        readable_output = (
            f'Successfully added {", ".join(recipient_list)} recipients to '
            f'{", ".join(sender_addresses)} senders in {entry_type}.'
        )

    return CommandResults(readable_output=readable_output, raw_response=response)


def list_entry_append_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Append spam quarantine blocklist/safelist entries.

    Args:
        client (Client): Cisco SMA API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: readable outputs for XSOAR.
    """
    entry_type = args["entry_type"]
    quarantine_type = QUARANTINE_TYPE
    action = APPEND_ACTION
    view_by = args["view_by"]

    formatted_arguments = format_list_entry_arguments(view_by=view_by, args=args)

    recipient_addresses = argToList(formatted_arguments.get("recipient_addresses"))
    sender_list = argToList(formatted_arguments.get("sender_list"))
    sender_addresses = argToList(formatted_arguments.get("sender_addresses"))
    recipient_list = argToList(formatted_arguments.get("recipient_list"))

    response = client.list_entry_append_request(
        entry_type=entry_type,
        quarantine_type=quarantine_type,
        action=action,
        view_by=view_by,
        recipient_addresses=recipient_addresses,
        sender_list=sender_list,
        sender_addresses=sender_addresses,
        recipient_list=recipient_list,
    )

    if view_by == "recipient":
        readable_output = (
            f'Successfully appended {", ".join(sender_list)} senders to '
            f'{", ".join(recipient_addresses)} recipients in {entry_type}.'
        )
    else:
        readable_output = (
            f'Successfully appended {", ".join(recipient_list)} recipients to '
            f'{", ".join(sender_addresses)} senders in {entry_type}.'
        )

    return CommandResults(readable_output=readable_output, raw_response=response)


def list_entry_edit_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Edit spam quarantine blocklist/safelist entries.

    Args:
        client (Client): Cisco SMA API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: readable outputs for XSOAR.
    """
    entry_type = args["entry_type"]
    quarantine_type = QUARANTINE_TYPE
    action = EDIT_ACTION
    view_by = args["view_by"]

    formatted_arguments = format_list_entry_arguments(view_by=view_by, args=args)

    recipient_addresses = argToList(formatted_arguments.get("recipient_addresses"))
    sender_list = argToList(formatted_arguments.get("sender_list"))
    sender_addresses = argToList(formatted_arguments.get("sender_addresses"))
    recipient_list = argToList(formatted_arguments.get("recipient_list"))

    response = client.list_entry_edit_request(
        entry_type=entry_type,
        quarantine_type=quarantine_type,
        action=action,
        view_by=view_by,
        recipient_addresses=recipient_addresses,
        sender_list=sender_list,
        sender_addresses=sender_addresses,
        recipient_list=recipient_list,
    )

    if view_by == "recipient":
        readable_output = (
            f"Successfully edited {', '.join(recipient_addresses)} recipients' senders to "
            f"{', '.join(sender_list)} in {entry_type}."
        )
    else:
        readable_output = (
            f"Successfully edited {', '.join(sender_addresses)} senders' recipients to "
            f"{', '.join(recipient_list)} in {entry_type}."
        )

    return CommandResults(readable_output=readable_output, raw_response=response)


def list_entry_delete_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Delete spam quarantine blocklist/safelist entries.

    Args:
        client (Client): Cisco SMA API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: readable outputs for XSOAR.
    """
    entry_type = args["entry_type"]
    quarantine_type = QUARANTINE_TYPE
    view_by = args["view_by"]
    recipient_list = argToList(args.get("recipient_list"))
    sender_list = argToList(args.get("sender_list"))

    if view_by == "recipient":
        if recipient_list:
            sender_list = None
        else:
            raise DemistoException("Please specify recipient_list argument when using view_by recipient.")
    else:
        if sender_list:
            recipient_list = None
        else:
            raise DemistoException("Please specify sender_list argument when using view_by sender.")

    response = client.list_entry_delete_request(
        entry_type=entry_type,
        quarantine_type=quarantine_type,
        view_by=view_by,
        recipient_list=recipient_list,
        sender_list=sender_list,
    )

    deleted_entries = ", ".join(recipient_list if view_by == "recipient" else sender_list)

    return CommandResults(
        readable_output=f"Successfully deleted {deleted_entries} {view_by}s from {entry_type}.",
        raw_response=response,
    )


def message_search_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Search tracking messages.

    Args:
        client (Client): Cisco SMA API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: readable outputs for XSOAR.
    """
    start_date = format_datetime(args["start_date"])
    end_date = format_datetime(args["end_date"])
    sender_filter_operator = args.get("sender_filter_operator")
    sender_filter_value = args.get("sender_filter_value")
    recipient_filter_operator = args.get("recipient_filter_operator")
    recipient_filter_value = args.get("recipient_filter_value")
    subject_filter_operator = args.get("subject_filter_operator")
    subject_filter_value = args.get("subject_filter_value")
    attachment_name_operator = args.get("attachment_name_operator")
    attachment_name_value = args.get("attachment_name_value")
    cisco_host = args.get("cisco_host")
    search_option = "messages"
    file_sha_256 = args.get("file_sha_256")
    custom_query = args.get("custom_query")

    validate_related_arguments(
        args=args,
        related_arguments_list=[
            ["sender_filter_operator", "sender_filter_value"],
            ["recipient_filter_operator", "recipient_filter_value"],
            ["subject_filter_operator", "subject_filter_value"],
            ["attachment_name_operator", "attachment_name_value"],
            ["order_by", "order_dir"],
        ],
    )

    output, pagination_message = pagination(
        client.message_search_request,
        args=args,
        start_date=start_date,
        end_date=end_date,
        sender_filter_operator=sender_filter_operator,
        sender_filter_value=sender_filter_value,
        recipient_filter_operator=recipient_filter_operator,
        recipient_filter_value=recipient_filter_value,
        subject_filter_operator=subject_filter_operator,
        subject_filter_value=subject_filter_value,
        attachment_name_operator=attachment_name_operator,
        attachment_name_value=attachment_name_value,
        cisco_host=cisco_host,
        search_option=search_option,
        file_sha_256=file_sha_256,
        custom_query=custom_query,
    )

    messages_lists = [
        dict(
            message.get("attributes", {}),
            timestamp=format_timestamp(dict_safe_get(message, ["attributes", "timestamp"])),
            unique_message_id="".join(map(str, dict_safe_get(message, ["attributes", "mid"]))),
        )
        for message in output
    ]

    readable_output = tableToMarkdown(
        name="Messages List",
        metadata=pagination_message,
        t=messages_lists,
        headers=[
            "mid",
            "allIcid",
            "dcid",
            "serialNumber",
            "sender",
            "recipient",
            "subject",
            "messageStatus",
            "timestamp",
            "senderIp",
            "sbrs",
        ],
        headerTransform=pascalToSpace,
        removeNull=True,
    )

    return CommandResults(
        readable_output=readable_output,
        outputs_prefix="CiscoSMA.Message",
        outputs_key_field="unique_message_id",
        outputs=messages_lists,
        raw_response=messages_lists,
    )


def message_details_get_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Get message details.

    Args:
        client (Client): Cisco SMA API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: readable outputs for XSOAR.
    """
    serial_number = args["serial_number"]
    message_ids = format_number_list_argument(args["message_ids"])
    injection_connection_id = arg_to_number(args.get("injection_connection_id"))
    delivery_connection_id = arg_to_number(args.get("delivery_connection_id"))

    response = (
        client.message_details_get_request(
            serial_number=serial_number,
            message_ids=message_ids,
            injection_connection_id=injection_connection_id,
            delivery_connection_id=delivery_connection_id,
        )
        .get("data", {})
        .get("messages", {})
    )

    mid = response.get("mid")
    if not mid or "N/A" in mid:
        raise DemistoException(
            f'Message ID {", ".join(map(str, message_ids))} was not found.\nPlease check message IDs or Serial Number.'
        )

    response["timestamp"] = format_timestamp(response.get("timestamp"))
    response["unique_message_id"] = "".join(map(str, response.get("mid")))

    for event in response.get("summary"):
        event["timestamp"] = format_timestamp(event.get("timestamp"))

    readable_output = tableToMarkdown(
        name="Message Details",
        metadata=f'Found message with ID {", ".join(map(str, response.get("mid")))}.',
        t=response,
        headers=[
            "mid",
            "allIcid",
            "subject",
            "sender",
            "recipient",
            "timestamp",
            "messageSize",
            "sendingHostSummary",
            "messageStatus",
            "direction",
            "mailPolicy",
            "senderGroup",
            "showAMP",
            "showDLP",
            "showURL",
        ],
        headerTransform=pascalToSpace,
    )

    summary_readable_output = tableToMarkdown(
        name="Message Summary",
        t=response.get("summary"),
        headers=["description", "timestamp", "lastEvent"],
        headerTransform=pascalToSpace,
        removeNull=True,
    )

    return CommandResults(
        readable_output=readable_output + summary_readable_output,
        outputs_prefix="CiscoSMA.Message",
        outputs_key_field="unique_message_id",
        outputs=response,
        raw_response=response,
    )


def message_amp_details_get_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Get message AMP report details.

    Args:
        client (Client): Cisco SMA API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: readable outputs for XSOAR.
    """
    serial_number = args["serial_number"]
    message_ids = format_number_list_argument(args["message_ids"])

    response = (
        client.message_amp_details_get_request(serial_number=serial_number, message_ids=message_ids)
        .get("data", {})
        .get("messages", {})
    )

    mid = response.get("mid")
    if not mid or "N/A" in mid:
        raise DemistoException(
            f'Message ID {", ".join(map(str, message_ids))} was not found.\nPlease check message IDs or Serial Number.'
        )

    response["timestamp"] = format_timestamp(response.get("timestamp"))

    readable_output = tableToMarkdown(
        name="Message AMP Report Details",
        metadata=f'Found AMP details for message ID {", ".join(map(str, response.get("mid")))}.',
        t=response,
        headers=[
            "mid",
            "allIcid",
            "subject",
            "sender",
            "recipient",
            "attachments",
            "timestamp",
            "messageSize",
            "messageStatus",
            "direction",
            "senderGroup",
        ],
        headerTransform=pascalToSpace,
    )

    amp_summary: List[Dict[str, Any]] = response.get("ampDetails")
    if amp_summary:
        for event in amp_summary:
            timestamp = event.get("timestamp")
            if timestamp:
                event["timestamp"] = format_timestamp(timestamp)

    summary_readable_output = tableToMarkdown(
        name="Message AMP Report Details Summary",
        t=amp_summary,
        headers=["description", "timestamp"],
        headerTransform=pascalToSpace,
        removeNull=True,
    )

    return CommandResults(
        readable_output=readable_output + summary_readable_output,
        outputs_prefix="CiscoSMA.AMPDetail",
        outputs_key_field="mid",
        outputs=response,
        raw_response=response,
    )


def message_dlp_details_get_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Get message DLP report details.

    Args:
        client (Client): Cisco SMA API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: readable outputs for XSOAR.
    """
    serial_number = args["serial_number"]
    message_ids = format_number_list_argument(args["message_ids"])

    response = (
        client.message_dlp_details_get_request(serial_number=serial_number, message_ids=message_ids)
        .get("data", {})
        .get("messages", {})
    )

    mid = response.get("mid")
    if not mid or "N/A" in mid:
        raise DemistoException(
            f'Message ID {", ".join(map(str, message_ids))} was not found.\nPlease check message IDs or Serial Number.'
        )

    response["timestamp"] = format_timestamp(response.get("timestamp"))

    readable_output = tableToMarkdown(
        name="Message DLP Report Details",
        metadata=f'Found DLP details for message ID {", ".join(map(str, response.get("mid")))}.',
        t=response,
        headers=[
            "mid",
            "allIcid",
            "subject",
            "sender",
            "recipient",
            "attachments",
            "timestamp",
            "messageSize",
            "messageStatus",
            "direction",
            "senderGroup",
        ],
        headerTransform=pascalToSpace,
        removeNull=True,
    )

    dlp_summary: List[Dict[str, Any]] = response.get("dlpDetails")

    summary_readable_output = tableToMarkdown(
        name="Message DLP Report Details Summary",
        t=dlp_summary,
        headers=["mid", "violationSeverity", "riskFactor", "dlpPolicy"],
        headerTransform=pascalToSpace,
    )

    return CommandResults(
        readable_output=readable_output + summary_readable_output,
        outputs_prefix="CiscoSMA.DLPDetail",
        outputs_key_field="mid",
        outputs=response,
        raw_response=response,
    )


def message_url_details_get_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Get message URL report details.

    Args:
        client (Client): Cisco SMA API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: readable outputs for XSOAR.
    """
    serial_number = args["serial_number"]
    message_ids = format_number_list_argument(args["message_ids"])

    response = (
        client.message_url_details_get_request(serial_number=serial_number, message_ids=message_ids)
        .get("data", {})
        .get("messages", {})
    )

    mid = response.get("mid")
    if not mid or "N/A" in mid:
        raise DemistoException(
            f'Message ID {", ".join(map(str, message_ids))} was not found.\nPlease check message IDs or Serial Number.'
        )

    response["timestamp"] = format_timestamp(response.get("timestamp"))

    url_summary: List[Dict[str, Any]] = response.get("urlDetails")
    if url_summary:
        for event in url_summary:
            timestamp = event.get("timestamp")
            if timestamp:
                event["timestamp"] = format_timestamp(timestamp)

    readable_output = tableToMarkdown(
        name="Message URL Report Details",
        metadata=f'Found URL details for message ID {", ".join(map(str, response.get("mid")))}.',
        t=response,
        headers=[
            "mid",
            "allIcid",
            "subject",
            "sender",
            "recipient",
            "attachments",
            "timestamp",
            "messageSize",
            "messageStatus",
            "direction",
            "senderGroup",
        ],
        headerTransform=pascalToSpace,
    )

    summary_readable_output = tableToMarkdown(
        name="Message URL Report Details Summary",
        t=url_summary,
        headers=["description", "timestamp"],
        headerTransform=pascalToSpace,
        removeNull=True,
    )

    return CommandResults(
        readable_output=readable_output + summary_readable_output,
        outputs_prefix="CiscoSMA.URLDetail",
        outputs_key_field="mid",
        outputs=response,
        raw_response=response,
    )


def report_get_command(client: Client, args: Dict[str, Any]) -> CommandResults:
    """
    Get statistics reports.

    Args:
        client (Client): Cisco SMA API client.
        args (Dict[str, Any]): Command arguments from XSOAR.

    Returns:
        CommandResults: readable outputs for XSOAR.
    """
    report_type = args.get("custom_report_type", args.get("report_type"))
    start_date = format_reporting_datetime(args["start_date"])
    end_date = format_reporting_datetime(args["end_date"])
    device_type = "esa"
    device_name = args.get("device_name")
    device_group_name = args.get("device_group_name") if device_name is None else None
    order_by = args.get("order_by")
    order_dir = args.get("order_dir")
    top = args.get("top")
    filter_value = args.get("filter_value")
    filter_by = args.get("filter_by")
    filter_operator = args.get("filter_operator")

    response: Dict[str, Any] = client.report_get_request(
        report_type=report_type,
        start_date=start_date,
        end_date=end_date,
        device_type=device_type,
        device_group_name=device_group_name,
        device_name=device_name,
        order_by=order_by,
        order_dir=order_dir,
        top=top,
        filter_value=filter_value,
        filter_by=filter_by,
        filter_operator=filter_operator,
    ).get("data", [])

    response["uuid"] = str(uuid.uuid4())

    try:
        table = {k: v for results in response.get("resultSet", [{}]) for k, v in results.items()}
    except Exception:
        table = response.get("resultSet", response)

    readable_output = tableToMarkdown(
        name=f'Report type: {response.get("type")}',
        metadata=f'Report UUID: {response["uuid"]}',
        t=table,
        headerTransform=string_to_table_header,
        removeNull=True,
    )

    return CommandResults(
        readable_output=readable_output,
        outputs_prefix="CiscoSMA.Report",
        outputs_key_field="uuid",
        outputs=response,
        raw_response=response,
    )


def fetch_incidents(
    client: Client,
    max_fetch: int,
    first_fetch: str,
    last_run: Dict[str, Any],
    filter_by: str = None,
    filter_operator: str = None,
    filter_value: str = None,
    recipient_filter_operator: str = None,
    recipient_filter_value: str = None,
) -> tuple:
    """
    Fetch Cisco SMA quarantined messages as incidents.

    Args:
        client (Client): Cisco SMA API client.
        max_fetch (int): Max number of messages to fetch.
        first_fetch (str): From which time to fetch.
        last_run (Dict[str, Any]): Last run info.
        filter_by (str, optional): Filter results by message field. Defaults to None.
        filter_operator (str, optional): Filter operator. Defaults to None.
        filter_value (str, optional): Filter value. Defaults to None.
        recipient_filter_operator (str, optional): Recipient filter operator. Defaults to None.
        recipient_filter_value (str, optional): Recipient filter value. Defaults to None.

    Returns:
        tuple: Incidents and last run info.
    """
    start_time = last_run.get("start_time")
    start_date = format_timestamp(start_time, output_format=CISCO_TIME_FORMAT) if start_time else format_datetime(first_fetch)
    end_date = format_datetime("now")
    quarantine_type = QUARANTINE_TYPE
    offset = 0
    order_by = "date"
    order_dir = "asc"

    quarantine_messages: List[Dict[str, Any]] = client.spam_quarantine_message_search_request(
        quarantine_type=quarantine_type,
        start_date=start_date,
        end_date=end_date,
        offset=offset,
        limit=max_fetch,
        filter_by=filter_by,
        filter_operator=filter_operator,
        filter_value=filter_value,
        recipient_filter_operator=recipient_filter_operator,
        recipient_filter_value=recipient_filter_value,
        order_by=order_by,
        order_dir=order_dir,
    ).get("data", [])

    incidents: List[Dict[str, Any]] = []
    last_minute_incident_ids = last_run.get("last_minute_incident_ids", [])
    for incident in quarantine_messages:
        incident_datetime = format_timestamp(
            dict_safe_get(incident, ["attributes", "date"]),
        )
        message_id = incident.get("mid")
        if message_id and message_id not in last_minute_incident_ids and start_date < incident_datetime:
            quarantine_message: Dict[str, Any] = client.spam_quarantine_message_get_request(
                quarantine_type=quarantine_type, message_id=message_id
            ).get("data", {})

            incident_details = dict(
                quarantine_message.get("attributes", {}),
                mid=quarantine_message.get("mid"),
            )
            incidents.append(
                {
                    "name": incident_details.get("subject"),
                    "occurred": incident_datetime,
                    "rawJSON": json.dumps(incident_details, ensure_ascii=False),
                }
            )

    if incidents:
        start_time = incidents[-1].get("occurred")
        last_run["start_time"] = start_time
        last_run["last_minute_incident_ids"] = [
            json.loads(incident.get("rawJSON", {})).get("mid") for incident in incidents if incident.get("occurred") == start_time
        ]

    return incidents, last_run


def test_module(client: Client, **kwargs) -> str:
    """
    Validates the correctness of the instance parameters and connectivity to Cisco SMA API service.

    Args:
        client (Client): Cisco SMA API client.
    """
    arg_to_datetime(kwargs.get("first_fetch"))

    validate_related_arguments(
        kwargs,
        [
            ["filter_by", "filter_operator", "filter_value"],
            ["recipient_filter_operator", "recipient_filter_value"],
        ],
    )

    start_date = format_datetime("1 month")
    end_date = format_datetime("now")
    offset = 0
    limit = 1
    search_option = "messages"
    cisco_host = "All_Hosts"

    client.message_search_request(
        start_date=start_date,
        end_date=end_date,
        offset=offset,
        limit=limit,
        search_option=search_option,
        cisco_host=cisco_host,
    )

    return "ok"


def main() -> None:
    params: Dict[str, Any] = demisto.params()
    args: Dict[str, Any] = demisto.args()

    base_url = params.get("base_url")
    username = params.get("credentials", {}).get("identifier")
    password = params.get("credentials", {}).get("password")

    max_fetch = arg_to_number(params.get("max_fetch", DEFAULT_FETCH))
    first_fetch = params.get("first_fetch") or "7 days"
    filter_by = params.get("filter_by")
    filter_operator = params.get("filter_operator")
    filter_value = params.get("filter_value")
    recipient_filter_operator = params.get("recipient_filter_operator")
    recipient_filter_value = params.get("recipient_filter_value")
    timeout = arg_to_number(params.get("timeout") or 60)
    verify_certificate: bool = not params.get("insecure", False)
    proxy = params.get("proxy", False)

    command = demisto.command()
    commands = {
        "cisco-sma-spam-quarantine-message-search": spam_quarantine_message_search_command,
        "cisco-sma-spam-quarantine-message-get": spam_quarantine_message_get_command,
        "cisco-sma-spam-quarantine-message-release": spam_quarantine_message_release_command,
        "cisco-sma-spam-quarantine-message-delete": spam_quarantine_message_delete_command,
        "cisco-sma-list-entry-get": list_entry_get_command,
        "cisco-sma-list-entry-add": list_entry_add_command,
        "cisco-sma-list-entry-append": list_entry_append_command,
        "cisco-sma-list-entry-edit": list_entry_edit_command,
        "cisco-sma-list-entry-delete": list_entry_delete_command,
        "cisco-sma-message-search": message_search_command,
        "cisco-sma-message-details-get": message_details_get_command,
        "cisco-sma-message-amp-details-get": message_amp_details_get_command,
        "cisco-sma-message-dlp-details-get": message_dlp_details_get_command,
        "cisco-sma-message-url-details-get": message_url_details_get_command,
        "cisco-sma-report-get": report_get_command,
    }
    try:
        client: Client = Client(
            urljoin(base_url, "/sma/api/v2.0"), username, password, verify_certificate, proxy, timeout=timeout
        )

        if command == "test-module":
            return_results(
                test_module(
                    client,
                    max_fetch=max_fetch,
                    first_fetch=first_fetch,
                    filter_by=filter_by,
                    filter_operator=filter_operator,
                    filter_value=filter_value,
                    recipient_filter_operator=recipient_filter_operator,
                    recipient_filter_value=recipient_filter_value,
                )
            )
        elif command == "fetch-incidents":
            incidents, last_run = fetch_incidents(
                client,
                max_fetch,  # type: ignore
                first_fetch,  # type: ignore
                demisto.getLastRun(),
                filter_by,
                filter_operator,
                filter_value,
                recipient_filter_operator,
                recipient_filter_value,
            )

            demisto.setLastRun(last_run)
            demisto.incidents(incidents)
        elif command in commands:
            return_results(commands[command](client, args))
        else:
            raise NotImplementedError(f"{command} command is not implemented.")

    except Exception as e:
        return_error(str(e))


if __name__ in ["__main__", "builtin", "builtins"]:
    main()