CiscoESA
The Cisco Email Security Appliance is an email security gateway product. It is designed to detect and block a wide variety of email-born threats, such as malware, spam and phishing attempts.
Network Security · Cisco Email Security Appliance (IronPort)
Details
| ID | CiscoESA |
|---|---|
| Provider | Cisco Systems |
| Category | Network Security |
| From Version | 6.5.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
The Cisco Email Security Appliance is an email security gateway product. It is designed to detect and block a wide variety of email-born threats, such as malware, spam and phishing attempts.
This integration was integrated and tested with version 16.0 of Cisco Email Security Appliance.
Configure Cisco ESA 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 | Timestamp in ISO format or number time unit, e.g., 2022-01-01T00:00:00000Z, 12 hours, 7 days, 3 months, now. |
False |
| Filter by | The message field by which to fetch results. | False |
| Filter operator | The message field operator by which to fetch results. | False |
| Filter value | The message filter value by which to fetch results. | False |
| Recipient filter operator | The message recipient filter operator by which to fetch results. | False |
| Recipient filter value | The message recipient filter value by which to fetch results. | False |
| Time to live for the JWT connection token (in minutes). | False | |
| Use system proxy settings | False | |
| Trust any certificate (not secure) | False | |
| Incident type | False | |
| Fetch incidents | False |
Troubleshooting
If you encounter multiple recurring errors similar to the following message:
Authorization Error: make sure username and password are set correctly.
By default, the integration assumes your JWT session tokens have a time to live of 30 minutes.
If the time to live is shorter, it can lead to the authorization error above. To resolve this error, reduce the value for the Time to live for JWT session token parameter.
By default, this value is 30 minutes and should only be reduced if these errors occur.
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-esa-spam-quarantine-message-search
Search messages in the spam quarantine.
Base Command
cisco-esa-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 | The message field by which to filter the results. Possible values are: from_address, to_address, subject. | Optional |
| filter_operator | Filter operator by which to filter the results. 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. D.g., filterValue=abc.com. | Optional |
| recipient_filter_operator | Recipient operator filter by which to filter the results. Possible values are: contains, is, begins_with, ends_with, does_not_contain. | Optional |
| recipient_filter_value | Recipient filter by which to filter the results. | Optional |
| order_by | The attribute by which to order the data in the response. Possible values are: from_address, date, subject, size. | Optional |
| order_dir | Results order direction. Possible values are: asc, desc. | Optional |
| page | Page number of paginated results. Minimum value: 1. |
Optional |
| page_size | Number of results per page. Maximum value 100. | Optional |
| limit | The maximum number of records to retrieve. Default is 50. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoESA.SpamQuarantineMessage.envelopeRecipient | String | Recipient email address. |
| CiscoESA.SpamQuarantineMessage.toAddress | String | Recipient email address. |
| CiscoESA.SpamQuarantineMessage.subject | String | Email subject. |
| CiscoESA.SpamQuarantineMessage.date | String | Email due date. |
| CiscoESA.SpamQuarantineMessage.fromAddress | String | Sender email address. |
| CiscoESA.SpamQuarantineMessage.size | String | email size. |
| CiscoESA.SpamQuarantineMessage.mid | Number | Message ID. |
Command example
!cisco-esa-spam-quarantine-message-search start_date=2weeks end_date=now page=3 page_size=2
Context Example
{
"CiscoESA": {
"SpamQuarantineMessage": [
{
"date": "13 Oct 2022 11:56 (GMT +00:00)",
"envelopeRecipient": [
"test@test.com"
],
"fromAddress": [
"Test Test <test@test.com>"
],
"mid": 1573,
"size": "10.20K",
"subject": "hello 1",
"toAddress": [
"test@test.com <test@test.com>"
]
},
{
"date": "13 Oct 2022 11:54 (GMT +00:00)",
"envelopeRecipient": [
"test@test.com"
],
"fromAddress": [
"Test Test <test@test.com>"
],
"mid": 1571,
"size": "10.20K",
"subject": "test 2",
"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 1573 13 Oct 2022 11:56 (GMT +00:00) Test Test test@test.com “test@test.com” test@test.com hello 1 10.20K 1571 13 Oct 2022 11:54 (GMT +00:00) Test Test test@test.com “test@test.com” test@test.com test 2 10.20K
cisco-esa-spam-quarantine-message-get
Get spam quarantine message details.
Base Command
cisco-esa-spam-quarantine-message-get
Input
| Argument Name | Description | Required |
|---|---|---|
| message_id | Message ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoESA.SpamQuarantineMessage.envelopeRecipient | String | Message recipient. |
| CiscoESA.SpamQuarantineMessage.toAddress | String | Message recipient. |
| CiscoESA.SpamQuarantineMessage.messageBody | String | Message body. |
| CiscoESA.SpamQuarantineMessage.date | String | Message date. |
| CiscoESA.SpamQuarantineMessage.fromAddress | String | Message sender. |
| CiscoESA.SpamQuarantineMessage.subject | String | Message subject. |
| CiscoESA.SpamQuarantineMessage.mid | Number | Message ID. |
Command example
!cisco-esa-spam-quarantine-message-get message_id=1572
Context Example
{
"CiscoESA": {
"SpamQuarantineMessage": {
"attachments": [],
"date": "13 Oct 2022 11:56 (GMT +00:00)",
"envelopeRecipient": [
"test@test.com"
],
"fromAddress": [
"Test Test <test@test.com>"
],
"messageBody": "X-MGA-submission: MDFwkBZw0xxrJATK37WrEGRJETolGcH/Ec0fhopBiCRuw7z3sB/lgKvnfUMzauVhijIde5pya7OR9Xn3ykXf7DGOX2PG4OSu//hcfzlboDzNMfYKbQ2c3Zs+883VYMeiUtz+xN/UCnIv9OHLDgJQ93IexI75JnATjKoedFoZpy80/g==<br />\nIronPort-HdrOrdr: A9a23:3J6AuqN81clqn8BcTyb155DYdb4zR+YMi2TDiHoddfUFSKalfp\r\n 6V98jzjSWE7gr5K0tQ4OxoWZPwNk80kKQY3WB/B8bHYOCLggqVxeJZnP3fKl/bakrDH4dmvM\r\n 8OHZSWY+eAbmSS+PyKhTVQZOxQouVvnprJuc7ui1NWCS16YaBp6Al0TiyBFFdteQVADZ0lUL\r\n KB+8tuvVObCDwqR/X+IkNAc/nIptXNmp6jSwUBHQQb5A6Hii7twKLmEiKfwgwVX1p0sPwfGC\r\n n+4kbED5eYwr2GIyznpiDuBlNt6ZXcI+54dYGxYw4uW3TRY0iTFcRcsva5zUgISamUmS0XeZ\r\n /30l4d1o1ImgnsV3Dwrh331wb61jEyr3fk1F+DmHPm5df0XTQgFqN69PBkmzbimjodVetHod\r\n F29nPcs4ASAQLLnSz76dSNXxZ2llCsqX5nleIIlXRQXYYXdbcU9OUkjTdoOYZFGDi/5JEsEe\r\n FoAs2Z7PFKcUmCZ3ScumV02tSjUnk6Ax/72<br />\nX-SLBL-Result: BLOCK-LISTED<br />\nX-IronPort-MailFlowPolicy: $ACCEPTED<br />\nX-IronPort-SenderGroup: ACCEPTLIST<br />\nX-IronPort-Listener: MailFlow<br />\nX-IronPort-Reputation: 3.5<br />\nX-IronPort-MID: 1572<br />\nX-IronPort-RemoteIP: 1.1.1.1<br />\nIronPort-SDR:\r\n\tboundary=_000_AS4P192MB1694AF23A0D358D3FE1B6B71AB259AS4P192MB1694EURP_<br />\nMIME-Version: 1.0<br />\nX-OriginatorOrg: test.com<br />\nX-MS-Exchange-CrossTenant-AuthAs: Internal<br />\nX-MS-Exchange-CrossTenant-AuthSource: test.test.COM<br />\nX-MS-Exchange-CrossTenant-Network-Message-Id: 26a48316-d039-47af-e556-08daad11e929<br />\nX-MS-Exchange-CrossTenant-originalarrivaltime: 13 Oct 2022 11:56:06.4076\r\n (UTC)<br />\nX-MS-Exchange-CrossTenant-fromentityheader: Hosted<br />\nX-MS-Exchange-CrossTenant-id: ed363dfd-16fd-4038-8e58-9237411a84e5<br />\nX-MS-Exchange-CrossTenant-mailboxtype: HOSTED<br />\nX-MS-Exchange-CrossTenant-userprincipalname: CkxCbZ1GZcqcuiVMCbo/AlVFa3/u8MxVWLuGIDg099YXDpyeHTh+tTrYpdMa/AWXF41GXNn/phrOWU4SsBEH6A==<br />\nX-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8P192MB0598<br /><br />\n\r<br>\n",
"mid": 1572,
"subject": "hello",
"toAddress": [
"test@test.com <test@test.com>"
]
}
}
}
Human Readable Output
Spam Quarantine Message
Found spam quarantine message with ID: 1572
Mid From Address To Address Date Subject 1572 Test Test test@test.com “test@test.com” test@test.com 13 Oct 2022 11:56 (GMT +00:00) hello
cisco-esa-spam-quarantine-message-release
Release quarantine emails.
Base Command
cisco-esa-spam-quarantine-message-release
Input
| Argument Name | Description | Required |
|---|---|---|
| message_ids | A comma-separated list of message IDs. | Required |
Context Output
There is no context output for this command.
Command example
!cisco-esa-spam-quarantine-message-release message_ids=1573
Human Readable Output
Quarantined message 1573 successfully released.
cisco-esa-spam-quarantine-message-delete
Delete quarantine emails.
Base Command
cisco-esa-spam-quarantine-message-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| message_ids | A comma-separated list of message IDs to delete. | Required |
Context Output
There is no context output for this command.
Command example
!cisco-esa-spam-quarantine-message-delete message_ids=1574
Human Readable Output
Quarantined message 1574 successfully deleted.
cisco-esa-list-entry-get
Get spam quarantine blocklist/safelist entry.
Base Command
cisco-esa-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: 1. |
Optional |
| page_size | Number of results per page. Maximum value 100. | Optional |
| limit | The maximum number of records to retrieve. Default is 50. | Optional |
| order_by | The attribute by which to order the data in the response. Possible values are: recipient, sender. | Optional |
| order_dir | Results order direction. 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 |
|---|---|---|
| CiscoESA.ListEntry.Blocklist.senderList | String | Sender list. |
| CiscoESA.ListEntry.Blocklist.recipientAddress | String | Recipient address. |
| CiscoESA.ListEntry.Blocklist.recipientList | String | Recipient list. |
| CiscoESA.ListEntry.Blocklist.senderAddress | String | Sender address. |
| CiscoESA.ListEntry.Safelist.senderList | String | Sender list. |
| CiscoESA.ListEntry.Safelist.recipientAddress | String | Recipient address. |
| CiscoESA.ListEntry.Safelist.recipientList | String | Recipient list. |
| CiscoESA.ListEntry.Safelist.senderAddress | String | Sender address. |
Command example
!cisco-esa-list-entry-get entry_type=safelist page=2 page_size=3 view_by=recipient order_by=recipient order_dir=desc
Context Example
{
"CiscoESA": {
"ListEntry": {
"Safelist": [
{
"recipientAddress": "test4@test.com",
"senderList": [
"test@test.com"
]
},
{
"recipientAddress": "test3@test.com",
"senderList": [
"test@test.com"
]
},
{
"recipientAddress": "test2@test.com",
"senderList": [
"test@test.com"
]
}
]
}
}
}
Human Readable Output
Safelist Entries
Showing page 2.
Current page size: 3.
Recipient Address Sender List test4@test.com test@test.com test3@test.com test@test.com test2@test.com test@test.com
cisco-esa-list-entry-add
Add spam quarantine blocklist/safelist entry.
Base Command
cisco-esa-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 recipient addresses to add. | Optional |
| sender_list | A comma-separated list of senders to add. | Optional |
| sender_addresses | A comma-separated list of sender addresses 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-esa-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-esa-list-entry-append
Append spam quarantine blocklist/safelist entry.
Base Command
cisco-esa-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 recipient addresses to append. | Optional |
| sender_addresses | A comma-separated list of sender addresses to append. | Optional |
Context Output
There is no context output for this command.
Command example
!cisco-esa-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-esa-list-entry-edit
Edit spam quarantine blocklist/safelist entry. Using this command will override the existing value.
Base Command
cisco-esa-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 recipient addresses to edit. | Optional |
| sender_addresses | A comma-separated list of sender addresses to edit. | Optional |
Context Output
There is no context output for this command.
Command example
!cisco-esa-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-esa-list-entry-delete
Delete spam quarantine blocklist/safelist entry.
Base Command
cisco-esa-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 | List of recipient/sender addresses to delete. | Optional |
| sender_list | List of recipient/sender addresses to delete. | Optional |
Context Output
There is no context output for this command.
Command example
!cisco-esa-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-esa-message-search
Search tracking messages.
Base Command
cisco-esa-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: 1. |
Optional |
| page_size | Number of results per page. Maximum value 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 |
| file_sha_256 | SHA256 must be 64 characters long and can contain only “0-9” and “a-f” characters. e.g. e0d123e5f316bef78bfdf5a008837577e0d123e5f316bef78bfdf5a008837577. |
Optional |
| custom_query | Custom query for cisco ESA’s advanced filters. Syntax: <key>=<value>;<key>=<value>;<key>=<value> e.g., graymail=True;message_delivered=True. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoESA.Message.hostName | String | Email gateway hostname. |
| CiscoESA.Message.friendly_from | String | Friendly formatted sender email address. |
| CiscoESA.Message.isCompleteData | String | Whether the entire data was pulled. |
| CiscoESA.Message.messageStatus | String | Message delivery status. |
| CiscoESA.Message.recipientMap | String | Recipients list. |
| CiscoESA.Message.senderIp | String | Sender IP address. |
| CiscoESA.Message.mailPolicy | String | Matched mail policy. |
| CiscoESA.Message.senderGroup | String | Matched sender group. |
| CiscoESA.Message.subject | String | Subject of email message. |
| CiscoESA.Message.mid | Number | Message ID. |
| CiscoESA.Message.senderDomain | String | Domain of email message sender. |
| CiscoESA.Message.finalSubject | String | Extended email subject. |
| CiscoESA.Message.direction | String | Message direction, incoming or outgoing. |
| CiscoESA.Message.icid | Number | An Injection Connection ID (ICID). A numerical identifier for an individual SMTP connection to the system. |
| CiscoESA.Message.replyTo | String | Email message reply to. |
| CiscoESA.Message.timestamp | String | Time of the email message. |
| CiscoESA.Message.messageID | String | Extended message ID. |
| CiscoESA.Message.verdictChart | String | Verdict visual chart ID. |
| CiscoESA.Message.recipient | String | Recipients email addresses list. |
| CiscoESA.Message.sender | String | Sender email address. |
| CiscoESA.Message.serialNumber | String | Cisco ESA email gateway serial number. |
| CiscoESA.Message.allIcid | Number | ICIDs list. |
| CiscoESA.Message.sbrs | String | Sender Base Reputation Scores. |
Command example
!cisco-esa-message-search start_date=1month end_date=now page=3 page_size=2 subject_filter_operator=contains subject_filter_value=test
Context Example
{
"CiscoESA": {
"Message": [
{
"allIcid": [
29969
],
"direction": "incoming",
"finalSubject": {
"1438": "test"
},
"friendly_from": [
"test@test.com"
],
"hostName": "",
"icid": 29969,
"isCompleteData": "N/A",
"mailPolicy": [
"DEFAULT"
],
"messageID": {
"1438": "<test@test.test.COM>"
},
"messageStatus": {
"1438": "Quarantined by Anti-Spam/Graymail"
},
"mid": [
1438
],
"morDetails": {},
"recipient": [
"test@test.com"
],
"recipientMap": {
"1438": [
"test@test.com"
]
},
"replyTo": "N/A",
"sbrs": "3.5",
"sender": "test@test.com",
"senderDomain": "test.com",
"senderGroup": "ACCEPTLIST",
"senderIp": "1.1.1.1",
"serialNumber": "test-test",
"subject": "test",
"timestamp": "2022-10-03T11:54:28Z",
"unique_message_id": "1438",
"verdictChart": {
"1438": "16140210"
}
},
{
"allIcid": [
19653
],
"direction": "incoming",
"finalSubject": {
"758": "test123"
},
"friendly_from": [
"test@test.com"
],
"hostName": "",
"icid": 19653,
"isCompleteData": "N/A",
"mailPolicy": [
"DEFAULT"
],
"messageID": {
"758": "<test@test.test.COM>"
},
"messageStatus": {
"758": "Quarantined by Anti-Spam/Graymail"
},
"mid": [
758
],
"morDetails": {},
"recipient": [
"test@test.com"
],
"recipientMap": {
"758": [
"test@test.com"
]
},
"replyTo": "N/A",
"sbrs": "3.5",
"sender": "test@test.com",
"senderDomain": "test.com",
"senderGroup": "ACCEPTLIST",
"senderIp": "1.1.1.1",
"serialNumber": "test-test",
"subject": "test123",
"timestamp": "2022-09-20T15:03:40Z",
"unique_message_id": "758",
"verdictChart": {
"758": "16130210"
}
}
]
}
}
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 1438 29969 test-test test@test.com test@test.com test 1438: Quarantined by Anti-Spam/Graymail 2022-10-03T11:54:28Z 1.1.1.1 3.5 758 19653 test-test test@test.com test@test.com test123 758: Quarantined by Anti-Spam/Graymail 2022-09-20T15:03:40Z 1.1.1.1 3.5
cisco-esa-message-details-get
Get message details.
Base Command
cisco-esa-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 |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoESA.Message.sdrAge | String | Sender domain reputation age. |
| CiscoESA.Message.attachments | String | Message attachments. |
| CiscoESA.Message.hostName | String | Email gateway hostname. |
| CiscoESA.Message.isCompleteData | Boolean | Whether the entire data was pulled. |
| CiscoESA.Message.messageStatus | String | Message delivery status. |
| CiscoESA.Message.mailPolicy | String | Matched mail policy. |
| CiscoESA.Message.senderGroup | String | Matched sender group. |
| CiscoESA.Message.subject | String | Subject of email message. |
| CiscoESA.Message.showSummaryTimeBox | Boolean | Whether to display the summary timebox. |
| CiscoESA.Message.sdrCategory | String | Sender domain reputation category. |
| CiscoESA.Message.mid | Number | Message ID. |
| CiscoESA.Message.sendingHostSummary.reverseDnsHostname | String | Sending host reverse DNS hostname. |
| CiscoESA.Message.sendingHostSummary.ipAddress | String | Sending host IP address. |
| CiscoESA.Message.sendingHostSummary.sbrsScore | String | Sending host sender base reputation scores. |
| CiscoESA.Message.direction | String | Message direction, incoming or outgoing. |
| CiscoESA.Message.smtpAuthId | String | SMTP authorization ID. |
| CiscoESA.Message.midHeader | String | Message ID header. |
| CiscoESA.Message.timestamp | String | Email message time. |
| CiscoESA.Message.showDLP | Boolean | Whether the DLP report is available. |
| CiscoESA.Message.messageSize | String | Email message size. |
| CiscoESA.Message.sdrReputation | String | Sender domain reputation. |
| CiscoESA.Message.showURL | Boolean | Whether the URL report is available. |
| CiscoESA.Message.recipient | String | Message recipient email address. |
| CiscoESA.Message.sender | String | Message sender email address. |
| CiscoESA.Message.showAMP | Boolean | Whether the AMP report is available. |
| CiscoESA.Message.summary.timestamp | String | Event summary time. |
| CiscoESA.Message.summary.description | String | Event summary description |
| CiscoESA.Message.summary.lastEvent | Boolean | Whether this is the last summary event. |
| CiscoESA.Message.allIcid | Number | ICIDs list. |
| CiscoESA.Message.headerFrom | String | Email message header from. |
Command example
!cisco-esa-message-details-get serial_number=test-test message_ids=1576 injection_connection_id=36859
Context Example
{
"CiscoESA": {
"Message": {
"allIcid": [
36859
],
"ampTgCategories": [],
"attachments": [],
"direction": "incoming",
"headerFrom": "test@test.com",
"hostName": "(Name unresolved, SN:test-test)",
"isCompleteData": false,
"mailPolicy": [
"DEFAULT"
],
"messageSize": "9.17 (KB)",
"messageStatus": "Quarantined by Anti-Spam/Graymail",
"mid": [
1576
],
"midHeader": "<test@test.test.com>",
"recipient": [
"test@test.com"
],
"sdrAge": "30 days (or greater)",
"sdrCategory": "N/A",
"sdrReputation": "Neutral",
"sdrThreatLevels": "3",
"sender": "test@test.com",
"senderGroup": "ACCEPTLIST",
"sendingHostSummary": {
"ipAddress": "1.1.1.1",
"reverseDnsHostname": "mail-test.test.test.test.com (verified)",
"sbrsScore": "3.5"
},
"showAMP": false,
"showDLP": false,
"showSummaryTimeBox": true,
"showURL": false,
"smtpAuthId": "",
"subject": "hello 4",
"summary": [
{
"description": "Incoming connection (ICID 36859) has sender_group: ACCEPTLIST, sender_ip: 1.1.1.1 and sbrs: 3.5",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:22Z"
},
{
"description": "Protocol SMTP interface Data 1 (IP 1.1.1.1) on incoming connection (ICID 36859) from sender IP 1.1.1.1. Reverse DNS host mail-test.test.test.test.com verified yes.",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:22Z"
},
{
"description": "(ICID 36859) ACCEPT sender group ACCEPTLIST match sbrs[0.0:10.0] SBRS 3.5 country Ireland",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:22Z"
},
{
"description": "Incoming connection (ICID 36859) successfully accepted TLS protocol TLSv1.2 cipher test-test-test.",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 Sender Domain: test.com",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Start message 1576 on incoming connection (ICID 36859).",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 enqueued on incoming connection (ICID 36859) from test@test.com.",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 direction: incoming",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 Domains for which SDR is requested: reverse DNS host: mail-test.test.test.test.com, helo: test.test.test.com, env-from: test.com, header_from: Not Present, reply_to: Not Present",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 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.com",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 on incoming connection (ICID 36859) added recipient (test@test.com).",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 SPF: mailfrom identity test@test.com Pass",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 DKIM: pass signature verified (d=test.test.com s=selector2-test-test-com i=@test.test.com)",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576: DMARC Verification skipped (No record found for the sending domain).",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 contains message ID header '<test@test.test.com>'.",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 original subject on injection: hello 4",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 Domains for which SDR is requested: reverse DNS host: mail-test.test.test.test.com, helo: test.test.test.com, env-from: test.com, header_from: test.com, reply_to: Not Present",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 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.com",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 (9389 bytes) from test@test.com ready.",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 has sender_group: ACCEPTLIST, sender_ip: 1.1.1.1 and sbrs: 3.5",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 matched per-recipient policy DEFAULT for inbound mail policies.",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 scanned by Anti-Spam engine: SLBL. Interim verdict: Positive",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 scanned by Anti-Spam engine: SLBL. Final verdict: Positive",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Incoming connection (ICID 36859) lost.",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 scanned by Anti-Virus engine McAfee. Interim verdict: CLEAN",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 scanned by Anti-Virus engine Sophos. Interim verdict: CLEAN",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 scanned by Anti-Virus engine. Final verdict: Negative ",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 scanned by Advanced Malware Protection engine. Final verdict: SKIPPED(no attachment in message)",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:23Z"
},
{
"description": "Message 1576 scanned by Outbreak Filters. Verdict: Negative",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:24Z"
},
{
"description": "Message 1576 queued for delivery.",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:24Z"
},
{
"description": "Remote procedure call connection (RCID 1) started for message 1576 to local Spam Quarantine.",
"lastEvent": false,
"timestamp": "2022-10-13T11:56:27Z"
},
{
"description": "Message 1576 quarantined in Spam Quarantine.",
"lastEvent": true,
"timestamp": "2022-10-13T11:56:27Z"
}
],
"timestamp": "2022-10-13T11:56:23Z",
"unique_message_id": "1576"
}
}
}
Human Readable Output
Message Details
Found message with ID 1576.
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 1576 36859 hello 4 test@test.com test@test.com 2022-10-13T11:56:23Z 9.17 (KB) reverseDnsHostname: mail-test.test.test.test.com (verified)
ipAddress: 1.1.1.1
sbrsScore: 3.5Quarantined by Anti-Spam/Graymail incoming DEFAULT ACCEPTLIST false false false Message Summary
Description Timestamp Last Event Incoming connection (ICID 36859) has sender_group: ACCEPTLIST, sender_ip: 1.1.1.1 and sbrs: 3.5 2022-10-13T11:56:22Z false Protocol SMTP interface Data 1 (IP 1.1.1.1) on incoming connection (ICID 36859) from sender IP 1.1.1.1. Reverse DNS host mail-test.test.test.test.com verified yes. 2022-10-13T11:56:22Z false (ICID 36859) ACCEPT sender group ACCEPTLIST match sbrs[0.0:10.0] SBRS 3.5 country Ireland 2022-10-13T11:56:22Z false Incoming connection (ICID 36859) successfully accepted TLS protocol TLSv1.2 cipher test-test-test. 2022-10-13T11:56:23Z false Message 1576 Sender Domain: test.com 2022-10-13T11:56:23Z false Start message 1576 on incoming connection (ICID 36859). 2022-10-13T11:56:23Z false Message 1576 enqueued on incoming connection (ICID 36859) from test@test.com. 2022-10-13T11:56:23Z false Message 1576 direction: incoming 2022-10-13T11:56:23Z false Message 1576 Domains for which SDR is requested: reverse DNS host: mail-test.test.test.test.com, helo: test.test.test.com, env-from: test.com, header_from: Not Present, reply_to: Not Present 2022-10-13T11:56:23Z false Message 1576 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.com 2022-10-13T11:56:23Z false Message 1576 on incoming connection (ICID 36859) added recipient (test@test.com). 2022-10-13T11:56:23Z false Message 1576 SPF: mailfrom identity test@test.com Pass 2022-10-13T11:56:23Z false Message 1576 DKIM: pass signature verified (d=test.test.com s=selector2-test-test-com i=@test.test.com) 2022-10-13T11:56:23Z false Message 1576: DMARC Verification skipped (No record found for the sending domain). 2022-10-13T11:56:23Z false Message 1576 contains message ID header ‘test@test.test.com’. 2022-10-13T11:56:23Z false Message 1576 original subject on injection: hello 4 2022-10-13T11:56:23Z false Message 1576 Domains for which SDR is requested: reverse DNS host: mail-test.test.test.test.com, helo: test.test.test.com, env-from: test.com, header_from: test.com, reply_to: Not Present 2022-10-13T11:56:23Z false Message 1576 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.com 2022-10-13T11:56:23Z false Message 1576 (9389 bytes) from test@test.com ready. 2022-10-13T11:56:23Z false Message 1576 has sender_group: ACCEPTLIST, sender_ip: 1.1.1.1 and sbrs: 3.5 2022-10-13T11:56:23Z false Message 1576 matched per-recipient policy DEFAULT for inbound mail policies. 2022-10-13T11:56:23Z false Message 1576 scanned by Anti-Spam engine: SLBL. Interim verdict: Positive 2022-10-13T11:56:23Z false Message 1576 scanned by Anti-Spam engine: SLBL. Final verdict: Positive 2022-10-13T11:56:23Z false Incoming connection (ICID 36859) lost. 2022-10-13T11:56:23Z false Message 1576 scanned by Anti-Virus engine McAfee. Interim verdict: CLEAN 2022-10-13T11:56:23Z false Message 1576 scanned by Anti-Virus engine Sophos. Interim verdict: CLEAN 2022-10-13T11:56:23Z false Message 1576 scanned by Anti-Virus engine. Final verdict: Negative 2022-10-13T11:56:23Z false Message 1576 scanned by Advanced Malware Protection engine. Final verdict: SKIPPED(no attachment in message) 2022-10-13T11:56:23Z false Message 1576 scanned by Outbreak Filters. Verdict: Negative 2022-10-13T11:56:24Z false Message 1576 queued for delivery. 2022-10-13T11:56:24Z false Remote procedure call connection (RCID 1) started for message 1576 to local Spam Quarantine. 2022-10-13T11:56:27Z false Message 1576 quarantined in Spam Quarantine. 2022-10-13T11:56:27Z true
cisco-esa-message-amp-details-get
Get message AMP summary details.
Base Command
cisco-esa-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 |
|---|---|---|
| CiscoESA.AMPDetail.sdrAge | String | Sender domain reputation age. |
| CiscoESA.AMPDetail.attachments | String | Message attachments. |
| CiscoESA.AMPDetail.hostName | String | Email gateway hostname. |
| CiscoESA.AMPDetail.direction | String | Message direction, incoming or outgoing. |
| CiscoESA.AMPDetail.messageStatus | String | Message delivery status. |
| CiscoESA.AMPDetail.senderGroup | String | Matched sender group. |
| CiscoESA.AMPDetail.subject | String | Email message subject. |
| CiscoESA.AMPDetail.sdrCategory | String | Sender domain reputation category. |
| CiscoESA.AMPDetail.mid | Number | Message ID. |
| CiscoESA.AMPDetail.ampDetails.timestamp | String | AMP event summary details timestamp. |
| CiscoESA.AMPDetail.ampDetails.description | String | AMP event summary details description. |
| CiscoESA.AMPDetail.ampDetails.lastEvent | Boolean | AMP event summary details last event. |
| CiscoESA.AMPDetail.smtpAuthId | String | SMTP authorization ID. |
| CiscoESA.AMPDetail.midHeader | String | Message ID header. |
| CiscoESA.AMPDetail.timestamp | String | Email message time. |
| CiscoESA.AMPDetail.messageSize | String | Email message size. |
| CiscoESA.AMPDetail.sdrThreatLevels | String | Sender domain reputation threat levels. |
| CiscoESA.AMPDetail.sdrReputation | String | Sender domain reputation. |
| CiscoESA.AMPDetail.recipient | String | Message recipient email address. |
| CiscoESA.AMPDetail.sender | String | Message sender email address. |
| CiscoESA.AMPDetail.showAMPDetails | Boolean | Whether to show AMP details. |
| CiscoESA.AMPDetail.allIcid | Number | ICIDs list. |
| CiscoESA.AMPDetail.headerFrom | String | Email header from. |
Command example
!cisco-esa-message-amp-details-get message_ids=741,742,743 serial_number=test-test
Context Example
{
"CiscoESA": {
"AMPDetail": {
"allIcid": [
19599
],
"ampDetails": [
{
"description": "File reputation query initiating. File Name = bear.jpg, MID = 741, File Size = 325663 bytes, File Type = image/jpeg",
"timestamp": "2022-09-20T13:31:18Z"
},
{
"description": "Response received for file reputation query from Cache. File Name = bear.jpg, MID = 741, Disposition = FILE UNKNOWN, Malware = None, Analysis Score = 0, sha256 = 23a9113530549916cd5b410edee79cb5a0fc01233eb9051f9c882a2e7c3fbfbe, upload_action = Recommended to send the file for analysis, verdict_source = AMP, Suspected Malware Categories = None",
"timestamp": "2022-09-20T13:31:18Z"
},
{
"description": "File not uploaded for analysis. MID = 741 File SHA256[23a9113530549916cd5b410edee79cb5a0fc01233eb9051f9c882a2e7c3fbfbe] file mime[image/jpeg] Reason: The file type is not configured for analysis",
"lastEvent": true,
"timestamp": "2022-09-20T13:31:18Z"
}
],
"ampTgCategories": [],
"attachments": [
"bear.jpg"
],
"direction": "incoming",
"headerFrom": "test@test.com",
"hostName": "(Name unresolved, SN:test-test)",
"messageSize": "439.26 (KB)",
"messageStatus": "Quarantined by Multiple Engines",
"mid": [
741,
742,
743
],
"midHeader": "<test@test.test.com>",
"recipient": [
"test@test.com"
],
"sdrAge": "30 days (or greater)",
"sdrCategory": "N/A",
"sdrReputation": "Neutral",
"sdrThreatLevels": "3",
"sender": "test@test.com",
"senderGroup": "ACCEPTLIST",
"sendingHostSummary": {},
"showAMPDetails": true,
"smtpAuthId": "",
"subject": "Fwd: test",
"timestamp": "2022-09-20T13:31:15Z"
}
}
}
Human Readable Output
Message AMP Report Details
Found AMP details for message ID 741, 742, 743.
Mid All Icid Subject Sender Recipient Attachments Timestamp Message Size Message Status Direction Sender Group 741,
742,
74319599 Fwd: test test@test.com test@test.com bear.jpg 2022-09-20T13:31:15Z 439.26 (KB) Quarantined by Multiple Engines incoming ACCEPTLIST Message AMP Report Details Summary
Description Timestamp File reputation query initiating. File Name = bear.jpg, MID = 741, File Size = 325663 bytes, File Type = image/jpeg 2022-09-20T13:31:18Z Response received for file reputation query from Cache. File Name = bear.jpg, MID = 741, Disposition = FILE UNKNOWN, Malware = None, Analysis Score = 0, sha256 = 23a9113530549916cd5b410edee79cb5a0fc01233eb9051f9c882a2e7c3fbfbe, upload_action = Recommended to send the file for analysis, verdict_source = AMP, Suspected Malware Categories = None 2022-09-20T13:31:18Z File not uploaded for analysis. MID = 741 File SHA256[23a9113530549916cd5b410edee79cb5a0fc01233eb9051f9c882a2e7c3fbfbe] file mime[image/jpeg] Reason: The file type is not configured for analysis 2022-09-20T13:31:18Z
cisco-esa-message-dlp-details-get
Get message DLP summary details.
Base Command
cisco-esa-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 |
|---|---|---|
| CiscoESA.DLPDetail.direction | String | Message direction, incoming or outgoing. |
| CiscoESA.DLPDetail.smtpAuthId | String | SMTP authorization ID. |
| CiscoESA.DLPDetail.sdrAge | String | Sender domain reputation age. |
| CiscoESA.DLPDetail.sender | String | Message sender email address. |
| CiscoESA.DLPDetail.midHeader | String | Message ID header. |
| CiscoESA.DLPDetail.timestamp | String | Email message time. |
| CiscoESA.DLPDetail.sdrCategory | String | Sender domain reputation category. |
| CiscoESA.DLPDetail.hostName | String | Email gateway hostname. |
| CiscoESA.DLPDetail.mid | Number | Message ID. |
| CiscoESA.DLPDetail.attachments | String | Message attachments. |
| CiscoESA.DLPDetail.messageSize | String | Email message size. |
| CiscoESA.DLPDetail.dlpDetails.violationSeverity | String | DLP details violation severity. |
| CiscoESA.DLPDetail.dlpDetails.dlpMatchedContent.messagePartMatch.classifier | String | DLP matched content classifier. |
| CiscoESA.DLPDetail.dlpDetails.dlpMatchedContent.messagePartMatch.classifierMatch | String | DLP matched content classifier match. |
| CiscoESA.DLPDetail.dlpDetails.dlpMatchedContent.messagePart | String | DLP matched content message part. |
| CiscoESA.DLPDetail.dlpDetails.mid | String | DLP message ID. |
| CiscoESA.DLPDetail.dlpDetails.riskFactor | Number | DLP risk factor. |
| CiscoESA.DLPDetail.dlpDetails.dlpPolicy | String | DLP policy. |
| CiscoESA.DLPDetail.sdrThreatLevels | String | Sender domain reputation threat levels. |
| CiscoESA.DLPDetail.sdrReputation | String | Sender domain reputation. |
| CiscoESA.DLPDetail.messageStatus | String | Message delivery status. |
| CiscoESA.DLPDetail.allIcid | Number | ICIDs list. |
| CiscoESA.DLPDetail.senderGroup | String | Matched sender group. |
| CiscoESA.DLPDetail.recipient | String | Message recipient email address. |
| CiscoESA.DLPDetail.subject | String | Email message subject. |
| CiscoESA.DLPDetail.headerFrom | String | Email header from. |
Command example
!cisco-esa-message-dlp-details-get message_ids=1131 serial_number=test-test
Context Example
{
"CiscoESA": {
"DLPDetail": {
"allIcid": [
20460
],
"ampTgCategories": [],
"attachments": [],
"direction": "outgoing",
"dlpDetails": {
"dlpMatchedContent": [
{
"messagePart": "Message",
"messagePartMatch": [
{
"classifier": "Proper Names (US)",
"classifierMatch": [
"Tim Testmane",
"Albert Iorio",
"Adriane Morrison",
"Lisa Garrison",
"Charles Testman",
"Dan Example",
"Christopher Diaz",
"Marjorie Green",
"Mark Testman",
"Stacey Peacock",
"Robert Aragon",
"Thomas Conley"
]
},
{
"classifier": "Personal Information (US)",
"classifierMatch": [
"Test Test <test@test.com>\nSubject: DLP\n\nFirst and Last Name SSN Credit Card Number\nVisa MC AMEX\nRobert Aragon 489-36-8350 4929-3813-3266-4295\nAshley Borden 514-14-8905 5370-4638-8881-3020\nThomas Conley 690-05-5315 4916-4811-5814-8111\nSusan Davis 421-37-1396 4916-4034-9269-8783\nChristopher Diaz 458-02-6124 5299-1561-5689-1938\nRick Edwards 612-20-6832 5293-8502-0071-3058\nVictor Faulkner 300-62-3266 5548-0246-6336-5664\nLisa Garrison 660-03-8360 4539-5385-7425-5825\nMarjorie Green 213-46-8915 4916-9766-5240-6147\nMark Testman 449-48-3135 4556-0072-1294-7415\nJames Heard 559-81-1301 4532-4220-6922-9909\nAlbert Iorio 322-84-2281 4916-6734-7572-5015\nCharles Testman 646-44-9061 5218-0144-2703-9266\nTeresa Kaminski 465-73-5022 5399-0706-4128-0178\nTim Testmane 044-34-6954 5144-8691-2776-1108\nMonte Mceachern 477-36-0282 5527-1247-5046-7780\nAdriane Morrison 421-90-3440 4539-0031-3703-0728\nJerome Munsch 524-02-7657 5180-3807-3679-8221\nAgnes Nelson 205-52-0027 5413-4428-0145-0036\nLynette Oyola 587-03-2682 4532-9929-3036-9308\nStacey Peacock 687-05-8365 5495-8602-4508-6804\nJulie Renfro 751-01-2327"
]
}
]
}
],
"dlpPolicy": "US HIPAA and HITECH (Low Threshold)",
"mid": "1131",
"riskFactor": 72,
"violationSeverity": "HIGH"
},
"headerFrom": "test@test.com",
"hostName": "(Name unresolved, SN:test-test)",
"messageSize": "29.67 (KB)",
"messageStatus": "Delivered",
"mid": [
1131
],
"midHeader": "<test@test.test.com>",
"recipient": [
"test@test.com"
],
"sender": "test@test.com",
"senderGroup": "RELAY_O365",
"sendingHostSummary": {},
"showDLPDetails": true,
"smtpAuthId": "",
"subject": "Fw: DLP",
"timestamp": "2022-09-21T08:42:32Z"
}
}
}
Human Readable Output
Message DLP Report Details
Found DLP details for message ID 1131.
Mid All Icid Subject Sender Recipient Timestamp Message Size Message Status Direction Sender Group 1131 20460 Fw: DLP test@test.com test@test.com 2022-09-21T08:42:32Z 29.67 (KB) Delivered outgoing RELAY_O365 Message DLP Report Details Summary
Mid Violation Severity Risk Factor Dlp Policy 1131 HIGH 72 US HIPAA and HITECH (Low Threshold)
cisco-esa-message-url-details-get
Get message URL summary details.
Base Command
cisco-esa-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 |
|---|---|---|
| CiscoESA.URLDetail.sdrAge | String | Sender domain reputation age. |
| CiscoESA.URLDetail.attachments | String | Message attachments. |
| CiscoESA.URLDetail.showURLDetails | Boolean | Whether to show URL event details. |
| CiscoESA.URLDetail.urlDetails.timestamp | String | URL event details timestamp. |
| CiscoESA.URLDetail.urlDetails.description | String | URL event details description. |
| CiscoESA.URLDetail.hostName | String | Email gateway hostname. |
| CiscoESA.URLDetail.direction | String | Message direction, incoming or outgoing. |
| CiscoESA.URLDetail.messageStatus | String | Message delivery status. |
| CiscoESA.URLDetail.senderGroup | String | Matched sender group. |
| CiscoESA.URLDetail.subject | String | Email message subject. |
| CiscoESA.URLDetail.sdrCategory | String | Sender domain reputation category. |
| CiscoESA.URLDetail.mid | Number | Message ID. |
| CiscoESA.URLDetail.smtpAuthId | String | SMTP authorization ID. |
| CiscoESA.URLDetail.midHeader | String | Message ID header. |
| CiscoESA.URLDetail.timestamp | String | Email message time. |
| CiscoESA.URLDetail.messageSize | String | Email message size. |
| CiscoESA.URLDetail.sdrThreatLevels | String | Sender domain reputation threat levels. |
| CiscoESA.URLDetail.sdrReputation | String | Sender domain reputation. |
| CiscoESA.URLDetail.recipient | String | Message recipient email address. |
| CiscoESA.URLDetail.sender | String | Message sender email address. |
| CiscoESA.URLDetail.allIcid | Number | ICIDs list. |
| CiscoESA.URLDetail.headerFrom | String | Email header from. |
Command example
!cisco-esa-message-url-details-get message_ids=737,738,739 serial_number=test-test
Context Example
{
"CiscoESA": {
"URLDetail": {
"allIcid": [
19598
],
"ampTgCategories": [],
"attachments": [
"bear.jpg"
],
"direction": "incoming",
"headerFrom": "test@test.com",
"hostName": "(Name unresolved, SN:test-test)",
"messageSize": "439.25 (KB)",
"messageStatus": "Quarantined by Multiple Engines",
"mid": [
737,
738,
739
],
"midHeader": "<test@test.test.com>",
"recipient": [
"test@test.com"
],
"sdrAge": "30 days (or greater)",
"sdrCategory": "N/A",
"sdrReputation": "Neutral",
"sdrThreatLevels": "3",
"sender": "test@test.com",
"senderGroup": "ACCEPTLIST",
"sendingHostSummary": {},
"showURLDetails": true,
"smtpAuthId": "",
"subject": "Fwd: test",
"timestamp": "2022-09-20T13:31:08Z",
"urlDetails": [
{
"description": "Message 737 URL: http://1.1.1.1:8080/, URL reputation: -6.8, Condition: URL Reputation Rule.",
"timestamp": "2022-09-20T13:31:12Z"
},
{
"description": "Message 737 URL: https://test.com/test/, URL reputation: -6.6, Condition: URL Reputation Rule.",
"timestamp": "2022-09-20T13:31:12Z"
},
{
"description": "Message 737 URL: http://1.1.1.1:8080, URL reputation: -6.8, Condition: URL Reputation Rule.",
"timestamp": "2022-09-20T13:31:12Z"
},
{
"description": "Message 737 rewritten URL u'http://1.1.1.1:8080'.",
"timestamp": "2022-09-20T13:31:12Z"
},
{
"description": "Message 737 rewritten URL u'https://test.com/test/'.",
"timestamp": "2022-09-20T13:31:12Z"
},
{
"description": "Message 737 rewritten URL u'http://1.1.1.1:8080/'.",
"timestamp": "2022-09-20T13:31:12Z"
},
{
"description": "Message 737 rewritten URL u'https://test.com/test/'.",
"timestamp": "2022-09-20T13:31:12Z"
}
]
}
}
}
Human Readable Output
Message URL Report Details
Found URL details for message ID 737, 738, 739.
Mid All Icid Subject Sender Recipient Attachments Timestamp Message Size Message Status Direction Sender Group 737,
738,
73919598 Fwd: test test@test.com test@test.com bear.jpg 2022-09-20T13:31:08Z 439.25 (KB) Quarantined by Multiple Engines incoming ACCEPTLIST Message URL Report Details Summary
Description Timestamp Message 737 URL: http://1.1.1.1:8080/, URL reputation: -6.8, Condition: URL Reputation Rule. 2022-09-20T13:31:12Z Message 737 URL: https://test.com/test/, URL reputation: -6.6, Condition: URL Reputation Rule. 2022-09-20T13:31:12Z Message 737 URL: http://1.1.1.1:8080, URL reputation: -6.8, Condition: URL Reputation Rule. 2022-09-20T13:31:12Z Message 737 rewritten URL u’http://1.1.1.1:8080’. 2022-09-20T13:31:12Z Message 737 rewritten URL u’https://test.com/test/’. 2022-09-20T13:31:12Z Message 737 rewritten URL u’http://1.1.1.1:8080/’. 2022-09-20T13:31:12Z Message 737 rewritten URL u’https://test.com/test/’. 2022-09-20T13:31:12Z
cisco-esa-report-get
Get statistics reports.
Note that each report type is compatible with different arguments.
Refer to Addendum for Cisco Secure Email Gateway (“Secure Email Reporting” sheet in the file), to view the dedicated arguments for each report type.
https://www.cisco.com/c/dam/en/us/td/docs/security/esa/esa14-0/api/AsyncOS-14-0-API-Addendum.xlsx
Base Command
cisco-esa-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 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 |
| order_by | The attribute by which to order the data in the response. For example, orderBy=total_clean_recipients. | Optional |
| order_dir | The report sort order direction. Possible values are: asc, desc. | Optional |
| top | The number of records with the highest values to return. | Optional |
| filter_value | The filter 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 | The filter operator. Filter the response data based on the value specified. Possible values are: begins_with, is. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoESA.Report.type | String | Report type. |
| CiscoESA.Report.resultSet | Number | Report results summary. |
Command example
!cisco-esa-report-get start_date=2weeks end_date=now report_type=mail_incoming_traffic_summary
Context Example
{
"CiscoESA": {
"Report": {
"resultSet": [
{
"failed_dkim": 0
},
{
"total_graymail_recipients": 5
},
{
"detected_spam": 19
},
{
"malicious_url": 3
},
{
"total_spoofed_emails": 1
},
{
"verif_decrypt_success": 0
},
{
"detected_virus": 0
},
{
"threat_content_filter": 4
},
{
"blocked_invalid_recipient": 12
},
{
"blocked_sdr": 0
},
{
"marketing_mail": 4
},
{
"ims_spam_increment_over_case": 0
},
{
"total_mailbox_auto_remediated_recipients": 0
},
{
"detected_spam_certain": 15
},
{
"detected_spam_suspect": 4
},
{
"blocked_dmarc": 1
},
{
"total_threat_recipients": 1383
},
{
"total_recipients": 1567
},
{
"verif_decrypt_fail": 0
},
{
"detected_amp": 0
},
{
"bulk_mail": 1
},
{
"social_mail": 0
},
{
"total_clean_recipients": 179
},
{
"detected_virus_per_msg": 0
},
{
"failed_spf": 0
},
{
"blocked_reputation": 1345
}
],
"type": "mail_incoming_traffic_summary",
"uuid": "6535f7b3-0d35-411b-ab76-42e27ea661ce"
}
}
}
Human Readable Output
Report type: mail_incoming_traffic_summary
Report UUID: 6535f7b3-0d35-411b-ab76-42e27ea661ce
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 1 12 1345 0 1 0 19 15 4 0 0 0 0 0 3 4 0 4 179 5 0 1567 1 1383 0 0
cisco-esa-dictionary-add
Add a new dictionary.
Base Command
cisco-esa-dictionary-add
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | The cluster mode of the email gateway determines its configuration. If the cluster mode is set to ‘group’, specify a group_name. If the cluster mode is set to ‘machine’, specify a host_name. Possible values are: cluster, group, machine. Default is cluster. | Optional |
| host_name | Required when cluster mode is ‘machine’. | Optional |
| group_name | Required when cluster mode is ‘group’. | Optional |
| dictionary_name | The name of the dictionary for which to get information. This argument is optional. | Optional |
| whole_words | Indicates if the words need to be matched completely. Possible values are: True, False. Default value is True. | Required |
| words | A list of terms to add to a dictionary. The term can have a weight of (0-10) associated with it. If no weight is given, the default weight is taken as “1”. A smart identifier can have an additional parameter - “prefix” associated with it. If no value is mentioned, no prefix is taken as default. Example: [‘credit’,2,’prefix’],[‘aba’],[‘À term 1’]. |
Required |
| ignore_case_sensitive | Indicates if the term that needs to be matched is case-sensitive. Possible values are: True, False. Default value is False. | Required |
Context Output
There is no context output for this command.
Command example
!cisco-esa-dictionary-add dictionary_name=testing1 ignore_case_sensitive=False whole_words=False mode=cluster words=['*credit',2,'prefix'],['test2']
!cisco-esa-dictionary-add dictionary_name=testing2 words=['*credit',2,'prefix'],['test2']
Human Readable Output
test_dictionary was added successfully.
cisco-esa-dictionary-edit
Edit a dictionary.
Base Command
cisco-esa-dictionary-edit
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | The cluster mode of the email gateway determines its configuration. If the cluster mode is set to ‘group’, specify a group_name. If the cluster mode is set to ‘machine’, specify a host_name. Possible values are: cluster, group, machine. Default is cluster. | Optional |
| host_name | Required when cluster mode is ‘machine’. | Optional |
| group_name | Required when cluster mode is ‘group’. | Optional |
| dictionary_name | The name of the dictionary for which to get information. This argument is optional. | Optional |
| updated_name | Specifies a new name for the dictionary to modify. | Optional |
| whole_words | Indicates if the words need to be matched completely. Possible values are: True, False. Default value is True. | Optional |
| words | A list of terms to add to a dictionary. The term can have a weight of (0-10) associated with it. If no weight is given, the default weight is taken as “1”. A smart identifier can have an additional parameter - “prefix” associated with it. If no value is mentioned, no prefix is taken as default. Example: [‘credit’,2,’prefix’],[‘aba’],[‘À term 1’]. |
Required |
| ignore_case_sensitive | Indicates if the term that needs to be matched is case-sensitive. Possible values are: True, False. Default value is False. | Required |
Context Output
There is no context output for this command.
Command example
!cisco-esa-dictionary-edit dictionary_name=testing1 words=['*credit',6,'prefix'],['test2']
Human Readable Output
test_dictionary has been successfully updated.
cisco-esa-dictionary-list
Retrieve information of all dictionaries or a specific configured dictionary and their list of words.
Base Command
cisco-esa-dictionary-list
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | The cluster mode of the email gateway determines its configuration. If the cluster mode is set to ‘group’, please a group_name. If the cluster mode is set to ‘machine’, specify a host_name. Possible values are: cluster, group, machine. Default is cluster. | Optional |
| host_name | Required when cluster mode is ‘machine’. | Optional |
| group_name | Required when cluster mode is ‘group’. | Optional |
| dictionary_name | The name of the dictionary for which to get information. This argument is optional. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoESA.Dictionary.name | String | The name of the dictionary. |
| CiscoESA.Dictionary.encoding | String | The encoding format used for the dictionary. |
| CiscoESA.Dictionary.ignorecase | Number | Indicates whether the dictionary ignores case sensitivity (1 for true, 0 for false). |
| CiscoESA.Dictionary.words | List | The words in the dictionary. |
| CiscoESA.Dictionary.words_count.term_count | Number | The count of individual terms in the dictionary. |
| CiscoESA.Dictionary.words_count.smart_identifier_count | Number | The count of smart identifiers in the dictionary (special terms with additional metadata). |
| CiscoESA.Dictionary.wholewords | Number | Indicates whether the dictionary considers whole words only (1 for true, 0 for false). |
Command example
!cisco-esa-dictionary-list mode=cluster dictionary_name=test
Human Readable Output
Information for Dictionary: testing
Name Words Ignore Case Whole Words Words Count Smart Identifier Count Encoding testing [‘test6’, 1], [‘testing7’, 1], [‘noy’, 1] 1 1 term_count: 4 0 utf-8
cisco-esa-dictionary-words-delete
Delete existing words from a specific dictionary.
Base Command
cisco-esa-dictionary-words-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | The cluster mode of the email gateway determines its configuration. If the cluster mode is set to ‘group’, specify a group_name. If the cluster mode is set to ‘machine’, specify a host_name. Possible values are: cluster, group, machine. Default is cluster. | Optional |
| host_name | Required when cluster mode is ‘machine’. | Optional |
| group_name | Required when cluster mode is ‘group’. | Optional |
| dictionary_name | The name of the dictionary for which to get information. This argument is optional. | Optional |
| words | A list of terms that need to be deleted. Example: *credit,aba,term. |
Required |
Context Output
There is no context output for this command.
Command example
!cisco-esa-dictionary-words-delete dictionary_name=testing mode=cluster words=*credit
!cisco-esa-dictionary-words-delete dictionary_name=testing words=test1,test2
Human Readable Output
Words deleted successfully from test_dictionary.
cisco-esa-dictionary-words-add
Add words to a specific dictionary.
Base Command
cisco-esa-dictionary-words-add
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | The cluster mode of the email gateway determines its configuration. If the cluster mode is set to ‘group’, specify a group_name. If the cluster mode is set to ‘machine’, specify a host_name. Possible values are: cluster, group, machine. Default is cluster. | Optional |
| host_name | Required when cluster mode is ‘machine’. | Optional |
| group_name | Required when cluster mode is ‘group’. | Optional |
| dictionary_name | The name of the dictionary for which to get information. This argument is optional. | Optional |
| words | A list of terms to add to a dictionary. The term can have a weight of (0-10) associated with it. If no weight is given, the default weight is taken as “1”. A smart identifier can have an additional parameter - “prefix” associated with it. If no value is mentioned, no prefix is taken as default. Example: [‘credit’,2,’prefix’],[‘aba’],[‘À term 1’]. |
Required |
Context Output
There is no context output for this command.
Command example
!cisco-esa-dictionary-words-add dictionary_name=testing words=['*ssn',2,'prefix'],['test3']
!cisco-esa-dictionary-words-add dictionary_name=testing1 mode=cluster words=['test1'],['testing2']
Human Readable Output
Added successfully to test_dictionary.
cisco-esa-dictionary-delete
Delete a dictionary.
Base Command
cisco-esa-dictionary-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | The cluster mode of the email gateway determines its configuration. If the cluster mode is set to ‘group’, specify a group_name. If the cluster mode is set to ‘machine’, specify a host_name. Possible values are: cluster, group, machine. Default is cluster. | Optional |
| host_name | Required when cluster mode is ‘machine’. | Optional |
| group_name | Required when cluster mode is ‘group’. | Optional |
| dictionary_name | The name of the dictionary for which to get information. This argument is optional. | Optional |
Context Output
There is no context output for this command.
Command example
!cisco-esa-dictionary-delete dictionary_name=test mode=cluster
Human Readable Output
test_dictionary deleted successfully.
cisco-esa-dictionary-words-update
Modify words in a specified content dictionary. Unlike cisco-esa-dictionary-edit, which overrides the entire dictionary, this command adds new terms or updates existing ones without removing existing terms.
Base Command
cisco-esa-dictionary-words-update
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | Defines the configuration level for applying changes on the email gateway. Set to ‘cluster’ to update the entire cluster, group to target a specific group (requires group_name), or ‘machine’ to update a single machine (requires host_name). Possible values are: cluster, group, machine. Default is cluster. |
Optional |
| group_name | The name of the group to target when ‘mode’ is set to group. This value is required only if mode is group. |
Optional |
| host_name | The hostname of the machine to target when ‘mode’ is set to ‘machine’. This value is required only if mode is ‘machine’. | Optional |
| dictionary_name | The name of the dictionary to update with the specified words. | Required |
| words | A list of terms to update in the dictionary. The term can have a weight of (0-10) associated with it. If no weight is given, the default weight is taken as “1”. A smart identifier can have an additional parameter - “prefix” associated with it. If no value is mentioned, no prefix is taken as default. Example: [‘credit’,2,’prefix’],[‘aba’],[‘À term 1’]. |
Required |
Context Output
There is no context output for this command.
Command example
!cisco-esa-dictionary-words-update dictionary_name=test words=['a1',1]
Human Readable Output
Added successfully to test.
cisco-esa-url-list-delete
Delete one or more URL lists. You cannot delete lists that are in use.
Base Command
cisco-esa-url-list-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | Defines the configuration level for applying changes on the email gateway. Set to ‘cluster’ to update the entire cluster, group to target a specific group (requires group_name), or ‘machine’ to update a single machine (requires host_name). Possible values are: cluster, group, machine. Default is cluster. |
Optional |
| group_name | The name of the group to target when ‘mode’ is set to group. This value is required only if mode is group. |
Optional |
| host_name | The hostname of the machine to target when ‘mode’ is set to ‘machine’. This value is required only if mode is ‘machine’. | Optional |
| url_list_names | A comma-separated list of URL List names to delete. | Required |
Context Output
There is no context output for this command.
Command example
!cisco-esa-url-list-delete url_list_names=testurllist
Human Readable Output
URL List(s)
testurllistwere successfully deleted.
cisco-esa-url-list-create
Create a new URL list.
Base Command
cisco-esa-url-list-create
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | Defines the configuration level for applying changes on the email gateway. Set to ‘cluster’ to update the entire cluster, group to target a specific group (requires group_name), or ‘machine’ to update a single machine (requires host_name). Possible values are: cluster, group, machine. Default is cluster. |
Optional |
| group_name | The name of the group to target when ‘mode’ is set to group. This value is required only if mode is group. |
Optional |
| host_name | The hostname of the machine to target when ‘mode’ is set to ‘machine’. This value is required only if mode is ‘machine’. | Optional |
| url_list_name | The URL List name to create. | Required |
| urls | A comma-separated list of URLs to add to the list. For example, malicious.com,phishing.com. | Required |
Context Output
There is no context output for this command.
Command example
!cisco-esa-url-list-create url_list_name=testurllist urls=test.com
Human Readable Output
testurllistwas successfully created.
cisco-esa-pvo-quarantine-message-release
Release messages associated with a specific PVO quarantine rule. This command releases all messages that match the specified rule from quarantine.
Base Command
cisco-esa-pvo-quarantine-message-release
Input
| Argument Name | Description | Required |
|---|---|---|
| rule_ids | Comma-separated list of rule IDs to release messages from. | Required |
| quarantine_type | The quarantine rule type. Default is pvo. | Optional |
Context Output
There is no context output for this command.
Command example
!cisco-esa-pvo-quarantine-message-release rule_ids=12
Human Readable Output
Messages were successfully released from rule(s): 12
cisco-esa-pvo-quarantine-list
List all PVO quarantine rules or retrieve a specific rule by ID. PVO rules determine how messages are quarantined based on policy violations, detected viruses, or outbreak conditions.
Base Command
cisco-esa-pvo-quarantine-list
Input
| Argument Name | Description | Required |
|---|---|---|
| type | The rule type to return. Default is pvo. | Optional |
| limit | The maximum number of records to return. Default is 50. | Optional |
| all_results | Whether to retrieve all the results by overriding the default limit. Default is false. | Optional |
| rule_id | The rule ID to retrieve. | Optional |
| offset | Specify an offset value to retrieve a subset of records starting with the offset value. Offset works with limit, which determines how many records to retrieve starting from the offset. Relevant with using rule_id and required when using limit. |
Optional |
| order_by | The order of the results. | Optional |
| order_direction | The direction of the results. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoESA.QuarantineRule.number_of_messages | Number | The number of messages matching the rule. |
| CiscoESA.QuarantineRule.capacity | String | The storage capacity used by messages matching the rule, represented as a percentage. |
| CiscoESA.QuarantineRule.rule_id | String | The unique identifier or label for the quarantine rule. |
| CiscoESA.QuarantineRule.total_size | String | The total size of all messages matching the rule. |
| CiscoESA.QuarantineRule.rule_description | String | Description of the quarantine rule. |
| CiscoESA.QuarantineRule.average_message_size | String | The average size of the quarantined messages. |
| CiscoESA.QuarantineRule.rid | Number | The rule identifier associated with the quarantine entry. |
Command example
!cisco-esa-pvo-quarantine-list limit=1
Context Example
{
"CiscoESA": {
"QuarantineRule": {
"average_message_size": "320KB",
"capacity": "0.0%",
"number_of_messages": 6,
"rid": 1,
"rule_description": "N/A",
"rule_id": "Malware: Malware",
"total_size": "1.9MB"
}
}
}
Human Readable Output
PVO Quarantine Rule List
Rule Id Rule Description Number Of Messages Capacity Average Message Size Malware: Malware N/A 6 0.0% 320KB
cisco-esa-incoming-policy-user-list
Retrieve user-defined sender/recipient entries from an incoming mail policy.
Base Command
cisco-esa-incoming-policy-user-list
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | Defines the configuration level for applying changes on the email gateway. Set to ‘cluster’ to update the entire cluster, group to target a specific group (requires group_name), or ‘machine’ to update a single machine (requires host_name). Possible values are: cluster, group, machine. Default is cluster. |
Optional |
| group_name | The name of the group to target when ‘mode’ is set to group. This value is required only if mode is group. |
Optional |
| host_name | The hostname of the machine to target when ‘mode’ is set to ‘machine’. This value is required only if mode is ‘machine’. | Optional |
| policy_name | The name of the policy to retrieve user entries. No helper command exists to retrieve policy names; you must provide this manually. | Required |
| limit | The maximum number of records to return. Default is 50. | Optional |
| all_results | Whether to retrieve all the results by overriding the default limit. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoESA.IncomingMailPolicyUser.sender_config.sender.domain_entries | String | List of sender domain entries. Messages from these senders will match the policy. |
| CiscoESA.IncomingMailPolicyUser.receiver_config.operation | String | Logical operator used to evaluate receiver and receiver_not entries. Valid values are ‘and’ or ‘or’. |
| CiscoESA.IncomingMailPolicyUser.receiver_config.receiver.domain_entries | String | List of recipient domain entries. Messages sent to these recipients will match the policy. |
| CiscoESA.IncomingMailPolicyUser.receiver_config.receiver_not.domain_entries | String | List of recipient domain entries to exclude. Messages NOT sent to these recipients will match the policy. Only valid with the ‘and’ operator. |
cisco-esa-url-list
Retrieve all URL lists or a specific list by name. URL lists define allowed or blocked domains for email content scanning and can be used in URL filtering configurations within mail policies.
Base Command
cisco-esa-url-list
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | Defines the configuration level for applying changes on the email gateway. Set to ‘cluster’ to update the entire cluster, group to target a specific group (requires group_name), or ‘machine’ to update a single machine (requires host_name). Possible values are: cluster, group, machine. Default is cluster. |
Optional |
| group_name | The name of the group to target when ‘mode’ is set to group. This value is required only if mode is group. |
Optional |
| host_name | The hostname of the machine to target when ‘mode’ is set to ‘machine’. This value is required only if mode is ‘machine’. | Optional |
| url_list_name | The name of the URL list to retrieve. | Optional |
| limit | The maximum number of records to return. Default is 50. | Optional |
| all_results | Whether to retrieve all the results by overriding the default limit. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoESA.URLList.used_by | String | The policy names that using the list. |
| CiscoESA.URLList.urls_count | Number | The number of urls in the list. |
| CiscoESA.URLList.name | String | The name of the list. |
| CiscoESA.URLList.urls | String | The URLs in the list. |
Command example
!cisco-esa-url-list limit=1
Context Example
{
"CiscoESA": {
"URLList": {
"name": "test",
"urls": [
"blabla.com"
],
"urls_count": 1,
"used_by": "Incoming Content Filters"
}
}
}
Human Readable Output
URL List
Name Urls Urls Count Used By test blabla.com 1 Incoming Content Filters
cisco-esa-message-remediation-details-get
Retrieve historical remediation actions taken on messages, such as message deletions or recalls. Includes batch initiator details, message status, delivery timestamps, and whether the message was read, supporting audit and compliance tracking for retroactive threat actions.
Base Command
cisco-esa-message-remediation-details-get
Input
| Argument Name | Description | Required |
|---|---|---|
| injection_connection_id | An Injection Connection ID (ICID). A numerical identifier for an individual SMTP connection to the system. Use cisco-esa-message-search to get message Injection Connection IDs. Consider to insert this parameter in case you don’t achive any results. |
Optional |
| message_ids | Comma-separated list of message IDs. Use cisco-esa-message-search to get message IDs. |
Required |
| serial_number | The unique serial number assigned to an email message. Use cisco-esa-message-search to get the message serial numer. |
Required |
| start_date | Start date for the messages. Timestamp in ISO format or <number> <time unit>, e.g., 2022-01-01T00:00:00.000Z, 12 hours, 7 days, 3 months, now. Default is 1 month. | Optional |
| end_date | The end date for the messages. Timestamp in ISO format or , for example, 2022-01-01T00:00:00.000Z, 12 hours, 7 days, 3 months, now.. Timestamp in ISO format or <number> <time unit>, e.g., 2022-01-01T00:00:00.000Z, 12 hours, 7 days, 3 months, now. Default is now. | Optional |
| limit | The maximum number of records to return. Default is 50. | Optional |
| all_results | Whether to retrieve all the results by overriding the default limit. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoESA.MessageRemediation.batch_details.b_init_username | String | Username that initiated the remediation batch. |
| CiscoESA.MessageRemediation.batch_details.mor_action | String | The remediation action type (e.g., Delete). |
| CiscoESA.MessageRemediation.batch_details.b_init_time | Number | Timestamp when the remediation batch was initiated (UNIX time). |
| CiscoESA.MessageRemediation.batch_details.batch_name | String | The name assigned to the remediation batch. |
| CiscoESA.MessageRemediation.batch_details.batch_desc | String | The description of the remediation batch. |
| CiscoESA.MessageRemediation.batch_details.b_init_source | String | The source that initiated the batch (e.g., ESA device name). |
| CiscoESA.MessageRemediation.message_details.delivered_at | Number | Timestamp when the message was delivered (UNIX time). |
| CiscoESA.MessageRemediation.message_details.mid | String | The message ID of the remediated email. |
| CiscoESA.MessageRemediation.message_details.from_email | String | Sender email address of the remediated message. |
| CiscoESA.MessageRemediation.message_details.recipient_email | String | Recipient email address of the remediated message. |
| CiscoESA.MessageRemediation.message_details.mor_status | String | The status of the remediation operation (for example, Success, Failed). |
| CiscoESA.MessageRemediation.message_details.msg_read | String | Indicates whether the message was read (0 = unread, 1 = read, or N/A). |
Command example
!cisco-esa-message-remediation-details-get message_ids=123 injection_connection_id=123 serial_number=123 limit=1
Context Example
{
"CiscoESA": {
"MessageRemediation": {
"batch_details": {
"b_init_source": "ESA 117",
"b_init_time": 1590646987,
"b_init_username": "admin",
"batch_desc": "N/A",
"batch_name": "Re7",
"mor_action": "Delete"
},
"message_details": [
{
"delivered_at": 1584574165,
"from_email": "test@test.com",
"mid": "3",
"mor_status": "Success",
"msg_read": "0",
"recipient_email": "test@test.com"
},
{
"delivered_at": 1584574165,
"from_email": "test@test.com",
"mid": "3",
"mor_status": "Success",
"msg_read": "0",
"recipient_email": "test@test.com"
}
]
}
}
}
Human Readable Output
Message Remediation Report Details Summary
Delivered _ At Mid From _ Email Recipient _ Email Mor _ Status Msg _ Read 1584574165 3 test@test.com test@test.com Success 0 1584574165 3 test@test.com test@test.com Success 0
cisco-esa-url-list-update
Update URLs in an existing URL list. This command overrides all the URL entries in the list.
Base Command
cisco-esa-url-list-update
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | Defines the configuration level for applying changes on the email gateway. Set to ‘cluster’ to update the entire cluster, group to target a specific group (requires group_name), or ‘machine’ to update a single machine (requires host_name). Possible values are: cluster, group, machine. Default is cluster. |
Optional |
| group_name | The name of the group to target when ‘mode’ is set to group. This value is required only if mode is group. |
Optional |
| host_name | The hostname of the machine to target when ‘mode’ is set to ‘machine’. This value is required only if mode is ‘machine’. | Optional |
| url_list_name | The URL List name to edit. | Required |
| urls | A comma-separated list of URLs to add to the list. | Optional |
Context Output
There is no context output for this command.
Command example
!cisco-esa-url-list-update url_list_name=testurllist urls=test2.com
Human Readable Output
testurllistwas successfully updated.
cisco-esa-file-hash-list
Retrieve all file hash lists or the contents of a specific list. File hash lists define allowed or blocked file signatures and can be used in Incoming Content Filter configurations to control file-based threats.
Base Command
cisco-esa-file-hash-list
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | Defines the configuration level for applying changes on the email gateway. Set to ‘cluster’ to update the entire cluster, group to target a specific group (requires group_name), or ‘machine’ to update a single machine (requires host_name). Possible values are: cluster, group, machine. Default is cluster. |
Optional |
| group_name | The name of the group to target when ‘mode’ is set to group. This value is required only if mode is group. |
Optional |
| host_name | The hostname of the machine to target when ‘mode’ is set to ‘machine’. This value is required only if mode is ‘machine’. | Optional |
| file_hash_list_name | The file hash list name to retrieve. | Optional |
| limit | The maximum number of records to return. Default is 50. | Optional |
| all_results | Whether to retrieve all the results by overriding the default limit. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoESA.FileHashList.filehashes | String | The hashes in the file hash List |
| CiscoESA.FileHashList.description | String | The description of the file hash List |
| CiscoESA.FileHashList.list_type | String | The file hash list type. |
| CiscoESA.FileHashList.name | String | The file hash list name. |
| CiscoESA.FileHashList.filehashes_count | String | The number of hashes in the list. |
Command example
!cisco-esa-file-hash-list limit=1
Context Example
{
"CiscoESA": {
"FileHashList": {
"description": "",
"filehashes": [
"44444444444444444444444444444443",
"44444444444444444444444444444444",
"44444444444444444444444444444445"
],
"filehashes_count": 3,
"list_type": "any",
"name": "test2"
}
}
}
Human Readable Output
File Hash List
Name Filehashes Filehashes Count List Type test2 44444444444444444444444444444443,
44444444444444444444444444444444,
444444444444444444444444444444453 any
cisco-esa-incoming-policy-user-add
Add sender and recipient entries to an incoming mail policy.
Base Command
cisco-esa-incoming-policy-user-add
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | Defines the configuration level for applying changes on the email gateway. Set to ‘cluster’ to update the entire cluster, group to target a specific group (requires group_name), or ‘machine’ to update a single machine (requires host_name). Possible values are: cluster, group, machine. Default is cluster. |
Optional |
| group_name | The name of the group to target when ‘mode’ is set to group. This value is required only if mode is group. |
Optional |
| host_name | The hostname of the machine to target when ‘mode’ is set to ‘machine’. This value is required only if mode is ‘machine’. | Optional |
| policy_name | The name of the policy to add sender and recipient entry. | Required |
| sender_domain_entries | Comma-separated sender domain entries (for example, user@example.com, @example.com) used to match messages from these senders. Required only if sender_non_domain_entries is not provided. Cannot be used together with sender_non_domain_entries. |
Optional |
| sender_non_domain_entries | Comma-separated sender domain entries to exclude. Used to match messages not from these senders. Required only if sender_domain_entries is not provided. Cannot be used together with sender_domain_entries. |
Optional |
| receiver_operation | Specifies how to combine receiver matching conditions. Use and if receiver_not_domain_entries is provided. Use or if using ANY as a domain. Possible values are: and, or. |
Required |
| receiver_domain_entries | Comma-separated recipient domain entries (for example, user@example.com, @example.com) used to match messages sent to these recipients. | Required |
| receiver_not_domain_entries | Comma-separated recipient domain entries to exclude. Used to match messages not sent to these recipients. Only allowed when receiver_operation is set to and. | Optional |
Context Output
There is no context output for this command.
cisco-esa-file-hash-update
Updates the provided file hash list. This command overrides all existing hash entries in the list.
Base Command
cisco-esa-file-hash-update
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | Defines the configuration level for applying changes on the email gateway. Set to ‘cluster’ to update the entire cluster, group to target a specific group (requires group_name), or ‘machine’ to update a single machine (requires host_name). Possible values are: cluster, group, machine. Default is cluster. |
Optional |
| group_name | The name of the group to target when ‘mode’ is set to group. This value is required only if mode is group. |
Optional |
| host_name | The hostname of the machine to target when ‘mode’ is set to ‘machine’. This value is required only if mode is ‘machine’. | Optional |
| file_hash_list_name | The name of the file hash list to update. . | Required |
| filehashes | A comma-separated string of file hash values to be added to the specified fle hash list. Each hash must have a valid format (for example, SHA256). | Required |
Context Output
There is no context output for this command.
Command example
!cisco-esa-file-hash-update file_hash_list_name=testfilehash filehashes=2286f6ffea7d0e58dcb3ecfd874041b2
Human Readable Output
testfilehashwas successfully updated.
cisco-esa-pvo-quarantine-message-delete
Delete messages associated with a specific PVO quarantine rule. This command deletes all messages that match the specified rule from quarantine.
Base Command
cisco-esa-pvo-quarantine-message-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| rule_ids | A comma-separated list of rule IDs to release message from. | Required |
| quarantine_type | The quarantine rule type. Default is pvo. | Optional |
Context Output
There is no context output for this command.
Command example
!cisco-esa-pvo-quarantine-message-delete rule_ids=12
Human Readable Output
Messages were successfully deleted from rule(s): 12
cisco-esa-file-hash-create
Create a new file hash list with specified hash entries.
Base Command
cisco-esa-file-hash-create
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | Defines the configuration level for applying changes on the email gateway. Set to ‘cluster’ to update the entire cluster, group to target a specific group (requires group_name), or ‘machine’ to update a single machine (requires host_name). Possible values are: cluster, group, machine. Default is cluster. |
Optional |
| group_name | The name of the group to target when ‘mode’ is set to group. This value is required only if mode is group. |
Optional |
| host_name | The hostname of the machine to target when ‘mode’ is set to ‘machine’. This value is required only if mode is ‘machine’. | Optional |
| file_hash_list_name | The file hash list name to create. | Required |
| filehashes | A comma-separated list of hashes to add to the list. | Required |
| description | Short description for the hash list. | Required |
| list_type | The type of the hashes in the list. Possible values are: md5, sha256, any. Default is any. | Required |
Context Output
There is no context output for this command.
cisco-esa-incoming-policy-user-update
Update sender and recipient entries in an existing incoming mail policy. This command overrides all existing sender and recipient entries with the provided values.
Base Command
cisco-esa-incoming-policy-user-update
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | Defines the configuration level for applying changes on the email gateway. Set to ‘cluster’ to update the entire cluster, group to target a specific group (requires group_name), or ‘machine’ to update a single machine (requires host_name). Possible values are: cluster, group, machine. Default is cluster. |
Optional |
| group_name | The name of the group to target when ‘mode’ is set to group. This value is required only if mode is group. |
Optional |
| host_name | The hostname of the machine to target when ‘mode’ is set to ‘machine’. This value is required only if mode is ‘machine’. | Optional |
| policy_name | The name of the policy to edit all the sender and recipient entries. | Required |
| sender_domain_entries | Comma-separated sender domain entries (for example, user@example.com, @example.com) used to match messages from these senders. Required only if sender_non_domain_entries is not provided. Cannot be used together with sender_non_domain_entries. |
Optional |
| sender_non_domain_entries | Comma-separated sender domain entries to exclude. Used to match messages not from these senders. Required only if sender_domain_entries is not provided. Cannot be used together with sender_domain_entries. |
Optional |
| receiver_operation | Specifies how to combine receiver matching conditions. Use and if receiver_not_domain_entries is provided. Use or if using ANY as a domain. Possible values are: and, or. |
Required |
| receiver_domain_entries | Comma-separated recipient domain entries (for example, user@example.com, @example.com) used to match messages sent to these recipients. | Required |
| receiver_not_domain_entries | Comma-separated recipient domain entries to exclude. Used to match messages not sent to these recipients. Only allowed when receiver_operation is set to and. | Optional |
Context Output
There is no context output for this command.
cisco-esa-message-connection-details-get
Retrieve metadata about the SMTP connection and transmission behavior of specified messages. Returns details such as SBRS (Sender Base Reputation Score), connection summary logs, and sender group classification to help understand how messages were handled at the connection layer.
Base Command
cisco-esa-message-connection-details-get
Input
| Argument Name | Description | Required |
|---|---|---|
| injection_connection_id | An Injection Connection ID (ICID). A numerical identifier for an individual SMTP connection to the system. Use cisco-esa-message-search to get message Injection Connection IDs. Consider to insert this parameter in case you don’t achive any results. |
Optional |
| message_ids | Comma-separated list of message IDs. Use cisco-esa-message-search to get message IDs. |
Required |
| serial_number | The unique serial number assigned to an email message. Use cisco-esa-message-search to get the message serial numer. |
Required |
| start_date | Start date for the messages. Timestamp in ISO format or <number> <time unit>, e.g., 2022-01-01T00:00:00.000Z, 12 hours, 7 days, 3 months, now. Default is 1 month. | Optional |
| end_date | The end date for the messages. Timestamp in ISO format or <number> <time unit>, e.g., 2022-01-01T00:00:00.000Z, 12 hours, 7 days, 3 months, now. Default is now. | Optional |
| limit | The maximum number of records to return. Default is 50. | Optional |
| all_results | Whether to retrieve all the results by overriding the default limit. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoESA.MessageConnection.sender_group | String | The sender group assigned to the connection (for example, RELAYLIST). |
| CiscoESA.MessageConnection.Message.timestamp | String | Timestamp of the connection summary event. |
| CiscoESA.MessageConnection.Message.description | String | Description of the connection summary event. |
| CiscoESA.MessageConnection.Message.last_event | Boolean | Indicates whether this is the final summary event. |
| CiscoESA.MessageConnection.sbrs | String | Sender Base Reputation Score (SBRS) of the sender IP. |
Command example
!cisco-esa-message-connection-details-get message_ids=123 injection_connection_id=123 serial_number=123 limit=1
Context Example
{
"CiscoESA": {
"MessageConnection": {
"Message": [
{
"description": "ICID 19213 sender_group: RELAYLIST sender_ip: 1.11.11.1, \n sbrs: not enabled",
"last_event": false,
"timestamp": "16 Nov 2018 11:01:08 (GMT)"
},
{
"description": "Protocol SMTP interface Management (IP 10.76.71.196) on \n incoming connection (ICID 19213) from sender IP 1.11.11.1. Reverse DNS\n host vm30bsd0199.com verified yes.",
"last_event": false,
"timestamp": "16 Nov 2018 11:01:08 (GMT)"
}
],
"sbrs": "not enabled",
"sender_group": "RELAYLIST"
}
}
}
Human Readable Output
Message Connection Report Details Summary: Sender group: RELAYLIST
Timestamp Description 16 Nov 2018 11:01:08 (GMT) ICID 19213 sender_group: RELAYLIST sender_ip: 1.11.11.1,
sbrs: not enabled16 Nov 2018 11:01:08 (GMT) Protocol SMTP interface Management (IP 10.76.71.196) on
incoming connection (ICID 19213) from sender IP 1.11.11.1. Reverse DNS
host vm30bsd0199.com verified yes.
cisco-esa-message-filter-list
Retrieve all message filters or a specific message filter by name. Message filters are evaluated early in the Work Queue, before security engines. This command manages Message Filters only. For more granular, per-policy control over message handling, use Content Filters in the Cisco AsyncOS web UI.
Base Command
cisco-esa-message-filter-list
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | The configuration level for applying changes on the email gateway. Set to ‘cluster’ to update the entire cluster, ‘group’ to target a specific group (requires group_name), or ‘machine’ to update a single machine (requires host_name). Possible values are: cluster, group, machine. Default is cluster. |
Optional |
| group_name | The name of the group to target when ‘mode’ is set to group. This value is required only if mode is group. |
Optional |
| host_name | The hostname of the machine to target when ‘mode’ is set to ‘machine’. This value is required only if mode is ‘machine’. | Optional |
| filter_name | The name of a specific message filter to retrieve. When omitted, all filters in scope are returned. | Optional |
| active | Whether to return only active or only inactive filters. Ignored when filter_name is supplied. Possible values are: true, false. |
Optional |
| limit | The maximum number of filters to return. Ignored when filter_name is supplied. Default is 50. |
Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoESA.MessageFilter.name | String | The filter name. |
| CiscoESA.MessageFilter.active | String | Whether the filter is active (`“true”` / `“false”`). |
| CiscoESA.MessageFilter.valid | String | Whether Cisco AsyncOS parsed the filter as valid (`“true”` / `“false”`). |
| CiscoESA.MessageFilter.order | Number | The 1-based position in the execution order. |
| CiscoESA.MessageFilter.rules_and_actions | String | The full Cisco filter DSL body. |
| CiscoESA.MessageFilter.invalid_reason | String | The reason the filter is marked as invalid. Present only when `valid` is `“false”`. |
Command example
Human Readable Output
Cisco ESA — Message Filters (mode: cluster)
Name Active Order Rules And Actions Validation Warning URL_QUARANTINE_MALICIOUS true 1 if (recv-listener == “MailFlow”) AND (url-reputation(-10.00, -6.00 , “bypass_urls”, 1, 1)) { quarantine(“URL_MALICIOUS”); } URL_REWRITE_SUSPICIOUS true 2 if (recv-listener == “MailFlow”) AND (url-reputation(-6.00, -5.60 , “bypass_urls”, 0, 1)) { url-reputation-proxy-redirect(-6.00, -5.60,”“,0); } BLOCKED_LIST_QUARANTINE false 3 if recv-listener == “MailFlow” { quarantine(“BLOCKED_LIST”); }
Command example
!cisco-esa-message-filter-list active=true limit=5
Context Example
{
"CiscoESA": {
"MessageFilter": [
{
"active": "true",
"name": "URL_QUARANTINE_MALICIOUS",
"order": 1,
"rules_and_actions": "if (recv-listener == \"MailFlow\") AND (url-reputation(-10.00, -6.00 , \"bypass_urls\", 1, 1)) { quarantine(\"URL_MALICIOUS\"); }",
"valid": "true"
},
{
"active": "true",
"name": "URL_REWRITE_SUSPICIOUS",
"order": 2,
"rules_and_actions": "if (recv-listener == \"MailFlow\") AND (url-reputation(-6.00, -5.60 , \"bypass_urls\", 0, 1)) { url-reputation-proxy-redirect(-6.00, -5.60,\"\",0); }",
"valid": "true"
}
]
}
}
Human Readable Output
Cisco ESA — Message Filters (mode: cluster)
Name Active Order Rules And Actions URL_QUARANTINE_MALICIOUS true 1 if (recv-listener == “MailFlow”) AND (url-reputation(-10.00, -6.00 , “bypass_urls”, 1, 1)) { quarantine(“URL_MALICIOUS”); } URL_REWRITE_SUSPICIOUS true 2 if (recv-listener == “MailFlow”) AND (url-reputation(-6.00, -5.60 , “bypass_urls”, 0, 1)) { url-reputation-proxy-redirect(-6.00, -5.60,”“,0); }
cisco-esa-message-filter-create
Create a new message filter. If the appliance accepts the filter but flags it as invalid (e.g. unknown listener/interface), the command returns success and surfaces the appliance warning in the human-readable output. For details on Cisco’s filter rule language, see “Using Message Filters to Enforce Email Policies” in the Cisco Secure Email Gateway 16.0 Admin Guide: https://www.cisco.com/c/en/us/td/docs/security/esa/esa16-0/user_guide/b_ESA_Admin_Guide_16-0/b_ESA_Admin_Guide_12_1_chapter_01000.html. This command manages Message Filters only. For more granular, per-policy control over message handling, use Content Filters in the Cisco AsyncOS web UI.
Base Command
cisco-esa-message-filter-create
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | The configuration level for applying changes on the email gateway. Set to ‘cluster’ to update the entire cluster, ‘group’ to target a specific group (requires group_name), or ‘machine’ to update a single machine (requires host_name). Possible values are: cluster, group, machine. Default is cluster. |
Optional |
| group_name | The name of the group to target when ‘mode’ is set to group. This value is required only if mode is group. |
Optional |
| host_name | The hostname of the machine to target when ‘mode’ is set to ‘machine’. This value is required only if mode is ‘machine’. | Optional |
| filter_name | The name for the new filter. | Required |
| rules_and_actions | The full Cisco filter DSL: if (<conditions>) { <actions>; }. See the Cisco AsyncOS for Email Security Admin Guide for the DSL reference. |
Required |
| active | Whether the filter should be active on creation. Possible values are: true, false. Default is true. | Optional |
| order | The 1-based position in the filter list. If omitted, or if the value exceeds the current number of filters, the filter is appended to the end of the list. | Optional |
Context Output
There is no context output for this command.
cisco-esa-message-filter-update
Update an existing message filter. Only the supplied fields (active, order) are sent — at least one must be provided. This command manages Message Filters only. For more granular, per-policy control over message handling, use Content Filters in the Cisco AsyncOS web UI.
Base Command
cisco-esa-message-filter-update
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | The configuration level for applying changes on the email gateway. Set to ‘cluster’ to update the entire cluster, ‘group’ to target a specific group (requires group_name), or ‘machine’ to update a single machine (requires host_name). Possible values are: cluster, group, machine. Default is cluster. |
Optional |
| group_name | The name of the group to target when ‘mode’ is set to group. This value is required only if mode is group. |
Optional |
| host_name | The hostname of the machine to target when ‘mode’ is set to ‘machine’. This value is required only if mode is ‘machine’. | Optional |
| filter_name | The name of the filter to update. | Required |
| active | Whether to enable or disable the filter. Possible values are: true, false. | Optional |
| order | The new 1-based position in the filter list. Must be within the range of existing filter positions (1 to the current filter count). | Optional |
Context Output
There is no context output for this command.
Command example
!cisco-esa-message-filter-update filter_name=example_filter active=false
Human Readable Output
Filter example_filter was successfully updated.
Command example
!cisco-esa-message-filter-update filter_name=example_filter order=2
Human Readable Output
Filter example_filter was successfully updated.
cisco-esa-message-filter-delete
Delete a message filter. This command manages Message Filters only. For more granular, per-policy control over message handling, use Content Filters in the Cisco AsyncOS web UI.
Base Command
cisco-esa-message-filter-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| mode | The configuration level for applying changes on the email gateway. Set to ‘cluster’ to update the entire cluster, ‘group’ to target a specific group (requires group_name), or ‘machine’ to update a single machine (requires host_name). Possible values are: cluster, group, machine. Default is cluster. |
Optional |
| group_name | The name of the group to target when ‘mode’ is set to group. This value is required only if mode is group. |
Optional |
| host_name | The hostname of the machine to target when ‘mode’ is set to ‘machine’. This value is required only if mode is ‘machine’. | Optional |
| filter_name | The name of the filter to delete. | Required |
Context Output
There is no context output for this command.
Command example
!cisco-esa-message-filter-delete filter_name=example_filter
Human Readable Output
Filter example_filter was deleted successfully.
Troubleshooting
Filter created but marked invalid (unknown Listener)
Symptom
A cisco-esa-message-filter-create (or cisco-esa-message-filter-update) call completes without raising an error, but the human-readable output includes a warning from the appliance similar to:
Filter
<FILTER_NAME>has been marked invalid for these reasons: Listener ‘<LISTENER_NAME>’ unknown;.
On the Cisco Email Security Appliance the filter exists, but it is flagged as invalid and will not run against mail flow.
Cause
The rules_and_actions value passed to the command references a Listener name (for example, recv-listener == "InboundMail") that does not exist on the target appliance. The appliance accepts the filter definition but refuses to activate it because it cannot resolve the Listener.
How to find the correct Listener name
The Listener is configured on the Cisco Email Security Appliance itself — not in Cortex XSOAR. Use either of the following on the appliance:
- Appliance web UI: Navigate to Network → IP Interfaces and look at the Listener column to see the Listener names bound to each interface. Common values are
IncomingMail,Default,Inbound, orPublic. - Appliance CLI: Run
listenerconfig, then useSETUPorDISPLAYto list the configured Listeners.
How to fix
-
Delete the invalid filter:
!cisco-esa-message-filter-delete filter_name=<FILTER_NAME> -
Re-create the filter using a Listener name that exists on the appliance. For example:
!cisco-esa-message-filter-create filter_name=URL_QUARANTINE_MALICIOUS \ rules_and_actions="if (recv-listener == \"MailFlow\") and (url-reputation(-10.00, -6.00, \"bypass_urls\", 1, 1)) { quarantine(\"URL_MALICIOUS\"); }" \ active=true
For details on Cisco’s filter rule language, see Using Message Filters to Enforce Email Policies in the Cisco Secure Email Gateway 16.0 Admin Guide.
Configuration parameters
base_url— Server URL (required)credentials— Username (required)max_fetch— Maximum incidents per fetchfirst_fetch— First fetch timestampfilter_by— Filter byfilter_operator— Filter operatorfilter_value— Filter valuerecipient_filter_operator— Recipient filter operatorrecipient_filter_value— Recipient filter valuejwt_token_expiration_period— Time to live for JWT session token (in minutes).proxy— Use system proxy settingsinsecure— Trust any certificate (not secure)incidentType— Incident typeincidentFetchInterval— Incidents Fetch IntervalisFetch— Fetch incidents
Commands (41)
-
cisco-esa-dictionary-addAdd a new dictionary.
-
cisco-esa-dictionary-deleteDelete a dictionary.
-
cisco-esa-dictionary-editEdit a dictionary.
-
cisco-esa-dictionary-listRetrieve information of all dictionaries or a specific configured dictionary and their list of words.
-
cisco-esa-dictionary-words-addAdd words to a specific dictionary.
-
cisco-esa-dictionary-words-deleteDelete existing words from specific dictionary.
-
cisco-esa-dictionary-words-updateModify words in a specified content dictionary. Unlike `cisco-esa-dictionary-edit`, which overrides the entire dictionary, this command adds new terms or updates existing ones without removing existing terms.
-
cisco-esa-file-hash-createCreate a new file hash list with specified hash entries.
-
cisco-esa-file-hash-listRetrieve all file hash lists or the contents of a specific list. File hash lists define allowed or blocked file signatures and can be used in Incoming Content Filter configurations to control file-based threats.
-
cisco-esa-file-hash-updateUpdates the provided file hash list. This command overrides all existing hash entries in the list.
-
cisco-esa-incoming-policy-user-addAdd sender and recipient entries to an incoming mail policy.
-
cisco-esa-incoming-policy-user-listRetrieve user-defined sender/recipient entries from an incoming mail policy.
-
cisco-esa-incoming-policy-user-updateUpdate sender and recipient entries in an existing incoming mail policy. This command overrides all existing sender and recipient entries with the provided values.
-
cisco-esa-list-entry-addAdd spam quarantine blocklist/safelist entry.
-
cisco-esa-list-entry-appendAppend spam quarantine blocklist/safelist entry.
-
cisco-esa-list-entry-deleteDelete spam quarantine blocklist/safelist entry.
-
cisco-esa-list-entry-editEdit spam quarantine blocklist/safelist entry. Using this command will override the existing value.
-
cisco-esa-list-entry-getGet spam quarantine blocklist/safelist entry.
-
cisco-esa-message-amp-details-getRetrieve AMP (Advanced Malware Protection) summary for specified email messages. Provides insight into file analysis, disposition changes, malware detection, and retrospective verdicts triggered by Cisco's Threat Grid or AMP engine for attachments in the email.
-
cisco-esa-message-connection-details-getRetrieve metadata about the SMTP connection and transmission behavior of specified messages. Returns details such as SBRS (Sender Base Reputation Score), connection summary logs, and sender group classification to help understand how messages were handled at the connection layer.
-
cisco-esa-message-details-getRetrieves metadata and tracking information for email messages processed by the ESA. Includes sender/recipient details, timestamps, message status for example, delivered, dropped), message size, AMP and DLP visibility flags, and applied mail policies. Useful for auditing and threat tracking.
-
cisco-esa-message-dlp-details-getGet message DLP summary details.
-
cisco-esa-message-filter-createCreate a new message filter. If the appliance accepts the filter but flags it as invalid (e.g. unknown listener/interface), the command returns success and surfaces the appliance warning in the human-readable output. For details on Cisco's filter rule language, see "Using Message Filters to Enforce Email Policies" in the Cisco Secure Email Gateway 16.0 Admin Guide: https://www.cisco.com/c/en/us/td/docs/security/esa/esa16-0/user_guide/b_ESA_Admin_Guide_16-0/b_ESA_Admin_Guide_12_1_chapter_01000.html. This command manages Message Filters only. For more granular, per-policy control over message handling, use Content Filters in the Cisco AsyncOS web UI.
-
cisco-esa-message-filter-deleteDelete a message filter. This command manages Message Filters only. For more granular, per-policy control over message handling, use Content Filters in the Cisco AsyncOS web UI.
-
cisco-esa-message-filter-listRetrieve all message filters or a specific message filter by name. Message filters are evaluated early in the Work Queue, before security engines. This command manages Message Filters only. For more granular, per-policy control over message handling, use Content Filters in the Cisco AsyncOS web UI.
-
cisco-esa-message-filter-updateUpdate an existing message filter. Only the supplied fields (`active`, `order`) are sent — at least one must be provided. This command manages Message Filters only. For more granular, per-policy control over message handling, use Content Filters in the Cisco AsyncOS web UI.
-
cisco-esa-message-remediation-details-getRetrieve historical remediation actions taken on messages, such as message deletions or recalls. Includes batch initiator details, message status, delivery timestamps, and whether the message was read, supporting audit and compliance tracking for retroactive threat actions.
-
cisco-esa-message-searchSearch tracking messages.
-
cisco-esa-message-url-details-getRetrieve URL summary details for specific email messages. This includes information about all URLs found within each message, such as rewritten URLs, timestamped access logs, and verdicts assigned by the email security engine.
-
cisco-esa-pvo-quarantine-listList all PVO quarantine rules or retrieve a specific rule by ID. PVO rules determine how messages are quarantined based on policy violations, detected viruses, or outbreak conditions.
-
cisco-esa-pvo-quarantine-message-deleteDelete messages associated with a specific PVO quarantine rule. This command deletes all messages that match the specified rule from quarantine.
-
cisco-esa-pvo-quarantine-message-releaseRelease messages associated with a specific PVO quarantine rule. This command releases all messages that match the specified rule from quarantine.
-
cisco-esa-report-getGet statistics reports. Note that each report type is compatible with different arguments. Refer to Addendum for Cisco Secure Email Gateway ("Secure Email Reporting" sheet in the file), to view the dedicated arguments for each report type. https://www.cisco.com/c/dam/en/us/td/docs/security/esa/esa14-0/api/AsyncOS-14-0-API-Addendum.xlsx
-
cisco-esa-spam-quarantine-message-deleteDelete quarantine emails.
-
cisco-esa-spam-quarantine-message-getGet spam quarantine message details.
-
cisco-esa-spam-quarantine-message-releaseRelease quarantine emails.
-
cisco-esa-spam-quarantine-message-searchSearch messages in the spam quarantine.
-
cisco-esa-url-listRetrieve all URL lists or a specific list by name. URL lists define allowed or blocked domains for email content scanning and can be used in URL filtering configurations within mail policies.
-
cisco-esa-url-list-createCreate a new URL list.
-
cisco-esa-url-list-deleteDelete one or more URL lists. You cannot delete lists that are in use.
-
cisco-esa-url-list-updateUpdate URLs in an existing URL list. This command overrides all the URL entries in the list.
import json import os from typing import Any from unittest.mock import patch import pytest from freezegun import freeze_time """MOCK PARAMETERS""" CREDENTIALS = "credentials" """CONSTANTS""" BASE_URL = "https://example.com/esa/api/v2.0" USERNAME = "MOCK_USER" PASSWORD = "XXX" TOKEN = "XXX-XXXX" def load_mock_response(file_name: str) -> str: """ Load mock file that simulates an API response. Args: file_name (str): Name of the mock response JSON file to return. Returns: str: Mock file content. """ with open(os.path.join("test_data/outputs", file_name), encoding="utf-8") as mock_file: return json.loads(mock_file.read()) def mock_access_token(client): return TOKEN @pytest.fixture(autouse=True) @patch( "CiscoEmailSecurityApplianceIronPortV2.Client.handle_request_headers", mock_access_token, ) def mock_client(): """ Mock client """ from CiscoEmailSecurityApplianceIronPortV2 import Client return Client(BASE_URL, USERNAME, PASSWORD, verify=False, proxy=False) """ TESTING INTEGRATION COMMANDS""" @pytest.mark.parametrize( "response_file_name,command_arguments,expected_outputs_len,expected_message_id", [ ( "spam_quarantine_message_search.json", { "start_date": "1 day", "end_date": "now", "limit": "3", }, 3, 783, ), ( "spam_quarantine_message_search.json", { "start_date": "2 weeks", "end_date": "1 day", "page": "2", "page_size": "3", "filter_by": "subject", "filter_operator": "contains", "filter_value": "test", }, 3, 783, ), ], ) def test_spam_quarantine_message_search_command( response_file_name: str, command_arguments: dict[str, Any], expected_outputs_len: int, expected_message_id: int, requests_mock, mock_client, ): """ Scenario: Spam quarantine message search. Given: - User has provided valid credentials. - User may provided pagination args. - User may Provided filtering arguments. When: - cisco-esa-spam-quarantine-message-search command called. Then: - Ensure outputs prefix is correct. - Ensure number of items is correct. - Validate outputs' fields. """ from CiscoEmailSecurityApplianceIronPortV2 import ( spam_quarantine_message_search_command, ) mock_response = load_mock_response(response_file_name) url = f"{BASE_URL}/quarantine/messages" requests_mock.get(url=url, json=mock_response) result = spam_quarantine_message_search_command(mock_client, command_arguments) outputs = result.outputs assert result.outputs_prefix == "CiscoESA.SpamQuarantineMessage" assert len(outputs) == expected_outputs_len assert outputs[0]["mid"] == expected_message_id @pytest.mark.parametrize( "response_file_name,command_arguments,expected_message_id", [ ( "spam_quarantine_message_get.json", {"message_id": 620}, 620, ) ], ) def test_spam_quarantine_message_get_command( response_file_name: str, command_arguments: dict[str, Any], expected_message_id: int, requests_mock, mock_client, ): """ Scenario: Spam quarantine message get. Given: - User has provided valid credentials. - User may provided pagination args. - User may Provided filtering arguments. When: - cisco-esa-spam-quarantine-message-get command called. Then: - Ensure outputs prefix is correct. - Validate outputs' fields. """ from CiscoEmailSecurityApplianceIronPortV2 import ( spam_quarantine_message_get_command, ) mock_response = load_mock_response(response_file_name) url = f"{BASE_URL}/quarantine/messages/details" requests_mock.get(url=url, json=mock_response) result = spam_quarantine_message_get_command(mock_client, command_arguments) outputs = result.outputs assert result.outputs_prefix == "CiscoESA.SpamQuarantineMessage" assert outputs["mid"] == expected_message_id @pytest.mark.parametrize( "response_file_name,command_arguments,expected_message", [ ( "spam_quarantine_message_release.json", {"message_ids": [50]}, "Quarantined message 50 successfully released.", ) ], ) def test_spam_quarantine_message_release_command( response_file_name: str, command_arguments: dict[str, Any], expected_message: str, requests_mock, mock_client, ): """ Scenario: Spam quarantine message release. Given: - User has provided valid credentials. - User may provided pagination args. - User may Provided filtering arguments. When: - cisco-esa-spam-quarantine-message-release command called. Then: - Ensure the human readable message is correct. """ from CiscoEmailSecurityApplianceIronPortV2 import ( spam_quarantine_message_release_command, ) mock_response = load_mock_response(response_file_name) url = f"{BASE_URL}/quarantine/messages" requests_mock.post(url=url, json=mock_response) result = spam_quarantine_message_release_command(mock_client, command_arguments) assert result[0].readable_output == expected_message @pytest.mark.parametrize( "response_file_name,command_arguments,expected_message_first_id,expected_message_second_id", [ ( "spam_quarantine_message_delete.json", {"message_ids": [100, 101]}, "Quarantined message 100 successfully deleted.", "Quarantined message 101 successfully deleted.", ), ( "spam_quarantine_message_delete_failed.json", {"message_ids": [120, 121]}, "Quarantined message 120 not found.", "Quarantined message 121 not found.", ), ], ) def test_spam_quarantine_message_delete_command( response_file_name: str, command_arguments: dict[str, Any], expected_message_first_id: str, expected_message_second_id: str, requests_mock, mock_client, ): """ Scenario: Spam quarantine message delete. Given: - User has provided valid credentials. - User may provided pagination args. - User may Provided filtering arguments. When: - cisco-esa-spam-quarantine-message-delete command called. Then: - Ensure the human readable message is correct. """ from CiscoEmailSecurityApplianceIronPortV2 import ( spam_quarantine_message_delete_command, ) mock_response = load_mock_response(response_file_name) url = f"{BASE_URL}/quarantine/messages" requests_mock.delete(url=url, json=mock_response) result = spam_quarantine_message_delete_command(mock_client, command_arguments) assert result[0].readable_output == expected_message_first_id assert result[1].readable_output == expected_message_second_id @pytest.mark.parametrize( "response_file_name,command_arguments,expected_outputs_len,expected_recipient_address", [ ( "list_entry_get_blocklist.json", { "entry_type": "blocklist", "limit": "2", }, 2, "test@test.com", ), ( "list_entry_get_safelist.json", { "entry_type": "safelist", "page": "2", "page_size": "1", }, 1, "test@test.com", ), ], ) def test_list_entry_get_command( response_file_name: str, command_arguments: dict[str, Any], expected_outputs_len: int, expected_recipient_address: str, requests_mock, mock_client, ): """ Scenario: List entry get. Given: - User has provided valid credentials. - User may provided pagination args. - User may Provided filtering arguments. When: - cisco-esa-list-entry-get command called. Then: - Ensure outputs prefix is correct. - Ensure number of items is correct. - Validate outputs' fields. """ from CiscoEmailSecurityApplianceIronPortV2 import list_entry_get_command mock_response = load_mock_response(response_file_name) entry_type = command_arguments.get("entry_type") url = f"{BASE_URL}/quarantine/{entry_type}" requests_mock.get(url=url, json=mock_response) result = list_entry_get_command(mock_client, command_arguments) outputs = result.outputs assert result.outputs_prefix == f"CiscoESA.ListEntry.{entry_type.title()}" assert len(outputs) == expected_outputs_len assert outputs[0]["recipientAddress"] == expected_recipient_address @pytest.mark.parametrize( "command_arguments,expected_message", [ ( { "entry_type": "blocklist", "view_by": "recipient", "recipient_addresses": ["test@test.com"], "sender_list": ["t1@test.com", "t2@test.com"], }, "Successfully added t1@test.com, t2@test.com senders to test@test.com recipients in blocklist.", ) ], ) def test_list_entry_add_command(command_arguments: dict[str, Any], expected_message: str, requests_mock, mock_client): """ Scenario: List entry add. Given: - User has provided valid credentials. - User may provided pagination args. - User may Provided filtering arguments. When: - cisco-esa-list-entry-add command called. Then: - Ensure the human readable message is correct. """ from CiscoEmailSecurityApplianceIronPortV2 import list_entry_add_command entry_type = command_arguments.get("entry_type") url = f"{BASE_URL}/quarantine/{entry_type}" requests_mock.post(url=url, json={}) result = list_entry_add_command(mock_client, command_arguments) assert result.readable_output == expected_message @pytest.mark.parametrize( "command_arguments,expected_message", [ ( { "entry_type": "safelist", "view_by": "sender", "sender_addresses": ["test@test.com", "test2@test.com"], "recipient_list": ["t3@test.com", "t4@test.com"], }, "Successfully appended t3@test.com, t4@test.com recipients to test@test.com, test2@test.com senders in safelist.", ) ], ) def test_list_entry_append_command(command_arguments: dict[str, Any], expected_message: str, requests_mock, mock_client): """ Scenario: List entry append. Given: - User has provided valid credentials. - User may provided pagination args. - User may Provided filtering arguments. When: - cisco-esa-list-entry-append command called. Then: - Ensure the human readable message is correct. """ from CiscoEmailSecurityApplianceIronPortV2 import list_entry_append_command entry_type = command_arguments.get("entry_type") url = f"{BASE_URL}/quarantine/{entry_type}" requests_mock.post(url=url, json={}) result = list_entry_append_command(mock_client, command_arguments) assert result.readable_output == expected_message @pytest.mark.parametrize( "command_arguments,expected_message", [ ( { "entry_type": "safelist", "view_by": "sender", "sender_addresses": ["test@test.com", "test2@test.com"], "recipient_list": ["t3@test.com", "t4@test.com"], }, "Successfully edited test@test.com, test2@test.com senders' recipients to t3@test.com, t4@test.com in safelist.", ) ], ) def test_list_entry_edit_command(command_arguments: dict[str, Any], expected_message: str, requests_mock, mock_client): """ Scenario: List entry edit. Given: - User has provided valid credentials. - User may provided pagination args. - User may Provided filtering arguments. When: - cisco-esa-list-entry-edit command called. Then: - Ensure the human readable message is correct. """ from CiscoEmailSecurityApplianceIronPortV2 import list_entry_edit_command entry_type = command_arguments.get("entry_type") url = f"{BASE_URL}/quarantine/{entry_type}" requests_mock.post(url=url, json={}) result = list_entry_edit_command(mock_client, command_arguments) assert result.readable_output == expected_message @pytest.mark.parametrize( "command_arguments,expected_message", [ ( { "entry_type": "blocklist", "view_by": "recipient", "recipient_list": ["test@test.com"], }, "Successfully deleted test@test.com recipients from blocklist.", ) ], ) def test_list_entry_delete_command(command_arguments: dict[str, Any], expected_message: str, requests_mock, mock_client): """ Scenario: List entry delete. Given: - User has provided valid credentials. - User may provided pagination args. - User may Provided filtering arguments. When: - cisco-esa-list-entry-delete command called. Then: - Ensure the human readable message is correct. """ from CiscoEmailSecurityApplianceIronPortV2 import list_entry_delete_command entry_type = command_arguments.get("entry_type") url = f"{BASE_URL}/quarantine/{entry_type}" requests_mock.delete(url=url, json={}) result = list_entry_delete_command(mock_client, command_arguments) assert result.readable_output == expected_message @pytest.mark.parametrize( "response_file_name,command_arguments,expected_outputs_len,expected_message_id,expected_recipients", [ ( "message_search.json", { "start_date": "1 week", "end_date": "now", "limit": "4", }, 4, [780], ["test@test.com"], ), ( "message_search.json", { "start_date": "2 weeks", "end_date": "1 day", "page": "2", "page_size": "4", "recipient_filter_operator": "is", "recipient_filter_value": "test@test.com", }, 4, [780], ["test@test.com"], ), ], ) def test_message_search_command( response_file_name: str, command_arguments: dict[str, Any], expected_outputs_len: int, expected_message_id: list[int], expected_recipients: list[str], requests_mock, mock_client, ): """ Scenario: Tracking message search. Given: - User has provided valid credentials. - User may provided pagination args. - User may Provided filtering arguments. When: - cisco-esa-message-search command called. Then: - Ensure outputs prefix is correct. - Ensure number of items is correct. - Validate outputs' fields. """ from CiscoEmailSecurityApplianceIronPortV2 import message_search_command mock_response = load_mock_response(response_file_name) url = f"{BASE_URL}/message-tracking/messages" requests_mock.get(url=url, json=mock_response) result = message_search_command(mock_client, command_arguments) outputs = result.outputs assert result.outputs_prefix == "CiscoESA.Message" assert len(outputs) == expected_outputs_len assert outputs[0]["mid"] == expected_message_id assert outputs[1]["recipient"] == expected_recipients @pytest.mark.parametrize( "response_file_name,command_arguments,expected_message_id,expected_recipients,expected_summary_len", [ ( "message_details_get.json", { "serial_number": "TESTAAA", "message_ids": [765, 766, 767], "injection_connection_id": 23092, }, [765, 766, 767], ["test@test.com"], 5, ) ], ) def test_message_details_get_command( response_file_name: str, command_arguments: dict[str, Any], expected_message_id: list[int], expected_recipients: list[str], expected_summary_len: int, requests_mock, mock_client, ): """ Scenario: Message detail get. Given: - User has provided valid credentials. - User may provided pagination args. - User may Provided filtering arguments. When: - cisco-esa-message-details-get command called. Then: - Ensure outputs prefix is correct. - Validate outputs' fields. """ from CiscoEmailSecurityApplianceIronPortV2 import message_details_get_command mock_response = load_mock_response(response_file_name) url = f"{BASE_URL}/message-tracking/details" requests_mock.get(url=url, json=mock_response) result = message_details_get_command(mock_client, command_arguments) outputs = result.outputs assert result.outputs_prefix == "CiscoESA.Message" assert outputs["mid"] == expected_message_id assert outputs["recipient"] == expected_recipients assert len(outputs["summary"]) == expected_summary_len @pytest.mark.parametrize( "response_file_name,command_arguments,expected_message_id,expected_recipients,expected_amp_summary_len", [ ( "message_amp_details_get.json", { "serial_number": "TESTAAA", "message_ids": [765, 766, 767], }, [765, 766, 767], ["test@test.com"], 3, ) ], ) def test_message_amp_details_get_command( response_file_name: str, command_arguments: dict[str, Any], expected_message_id: list[int], expected_recipients: list[str], expected_amp_summary_len: int, requests_mock, mock_client, ): """ Scenario: Message AMP details summary get. Given: - User has provided valid credentials. - User may provided pagination args. - User may Provided filtering arguments. When: - cisco-esa-message-amp-details-get command called. Then: - Ensure outputs prefix is correct. - Validate outputs' fields. """ from CiscoEmailSecurityApplianceIronPortV2 import message_amp_details_get_command mock_response = load_mock_response(response_file_name) url = f"{BASE_URL}/message-tracking/amp-details" requests_mock.get(url=url, json=mock_response) result = message_amp_details_get_command(mock_client, command_arguments) outputs = result.outputs assert result.outputs_prefix == "CiscoESA.AMPDetail" assert outputs["mid"] == expected_message_id assert outputs["recipient"] == expected_recipients assert len(outputs["ampDetails"]) == expected_amp_summary_len @pytest.mark.parametrize( "response_file_name,command_arguments,expected_message_id,expected_recipients,expected_dlp_policy", [ ( "message_dlp_details_get.json", { "serial_number": "TESTAAA", "message_ids": [1131], }, [1131], ["test@test.com"], "US HIPAA and HITECH (Low Threshold)", ) ], ) def test_message_dlp_details_get_command( response_file_name: str, command_arguments: dict[str, Any], expected_message_id: list[int], expected_recipients: list[str], expected_dlp_policy: str, requests_mock, mock_client, ): """ Scenario: Message dlp details summary get. Given: - User has provided valid credentials. - User may provided pagination args. - User may Provided filtering arguments. When: - cisco-esa-message-dlp-details-get command called. Then: - Ensure outputs prefix is correct. - Validate outputs' fields. """ from CiscoEmailSecurityApplianceIronPortV2 import message_dlp_details_get_command mock_response = load_mock_response(response_file_name) url = f"{BASE_URL}/message-tracking/dlp-details" requests_mock.get(url=url, json=mock_response) result = message_dlp_details_get_command(mock_client, command_arguments) outputs = result.outputs assert result.outputs_prefix == "CiscoESA.DLPDetail" assert outputs["mid"] == expected_message_id assert outputs["recipient"] == expected_recipients assert outputs["dlpDetails"]["dlpPolicy"] == expected_dlp_policy @pytest.mark.parametrize( "response_file_name,command_arguments,expected_message_id,expected_recipients,expected_url_summary_len", [ ( "message_url_details_get.json", { "serial_number": "TESTAAA", "message_ids": [222, 223, 224], }, [222, 223, 224], ["test@test.com"], 7, ) ], ) def test_message_url_details_get_command( response_file_name: str, command_arguments: dict[str, Any], expected_message_id: list[int], expected_recipients: list[str], expected_url_summary_len: int, requests_mock, mock_client, ): """ Scenario: Message url details summary get. Given: - User has provided valid credentials. - User may provided pagination args. - User may Provided filtering arguments. When: - cisco-esa-message-url-details-get command called. Then: - Ensure outputs prefix is correct. - Validate outputs' fields. """ from CiscoEmailSecurityApplianceIronPortV2 import message_url_details_get_command mock_response = load_mock_response(response_file_name) url = f"{BASE_URL}/message-tracking/url-details" requests_mock.get(url=url, json=mock_response) result = message_url_details_get_command(mock_client, command_arguments) outputs = result.outputs assert result.outputs_prefix == "CiscoESA.URLDetail" assert outputs["mid"] == expected_message_id assert outputs["recipient"] == expected_recipients assert len(outputs["urlDetails"]) == expected_url_summary_len @pytest.mark.parametrize( "response_file_name,command_arguments,expected_type,expected_results_len", [ ( "report_get.json", { "report_type": "mail_incoming_traffic_summary", "start_date": "1 week", "end_date": "now", }, "mail_incoming_traffic_summary", 26, ) ], ) def test_message_report_get_command( response_file_name: str, command_arguments: dict[str, Any], expected_type: str, expected_results_len: int, requests_mock, mock_client, ): """ Scenario: Report get. Given: - User has provided valid credentials. - User may provided pagination args. - User may Provided filtering arguments. When: - cisco-esa-report-get command called. Then: - Ensure outputs prefix is correct. - Validate outputs' fields. """ from CiscoEmailSecurityApplianceIronPortV2 import report_get_command mock_response = load_mock_response(response_file_name) url = f'{BASE_URL}/reporting/{command_arguments.get("report_type")}' requests_mock.get(url=url, json=mock_response) result = report_get_command(mock_client, command_arguments) outputs = result.outputs assert result.outputs_prefix == "CiscoESA.Report" assert outputs["type"] == expected_type assert len(outputs["resultSet"]) == expected_results_len """ TESTING HELPER FUNCTIONS""" @pytest.mark.parametrize( "number_list_argument,expected_result", [ ( "10,20,30", [10, 20, 30], ) ], ) def test_format_number_list_argument(number_list_argument: str, expected_result: list[int]): """ Scenario: Format number list argument. Given: - User has provided number list argument. When: - format_number_list_argument function called. Then: - Ensure result is correct. """ from CiscoEmailSecurityApplianceIronPortV2 import format_number_list_argument result = format_number_list_argument(number_list_argument) assert result == expected_result @pytest.mark.parametrize( "custom_query_argument,expected_result", [ ( "test_key1=test_value1;test_key2=test_value2", {"test_key1": "test_value1", "test_key2": "test_value2"}, ) ], ) def test_format_custom_query_args(custom_query_argument: str, expected_result: dict[str, Any]): """ Scenario: Format custom query arguments for tracking message advanced filters. Given: - User has provided custom query argument. When: - format_custom_query_args function called. Then: - Ensure result is correct. """ from CiscoEmailSecurityApplianceIronPortV2 import format_custom_query_args result = format_custom_query_args(custom_query_argument) assert result == expected_result @pytest.mark.parametrize( "timestamp,output_format,expected_result", [ ("07 Sep 2022 09:08:03 (GMT)", "%Y-%m-%dT%H:%M:%SZ", "2022-09-07T09:08:03Z"), ( "24 Apr 2023 10:14:50 (GMT -05:00)", "%Y-%m-%dT%H:%M:00.000Z", "2023-04-24T15:14:00.000Z", ), ( "24 Apr 2023 10:14:50 (GMT-06:00)", "%Y-%m-%dT%H:%M:%SZ", "2023-04-24T16:14:50Z", ), ( "24 Apr 2023 10:14:50 (GMT +01:00)", "%Y-%m-%dT%H:%M:%SZ", "2023-04-24T09:14:50Z", ), (None, "%Y-%m-%dT%H:%M:%SZ", None), ], ) def test_format_timestamp(timestamp, output_format, expected_result): """ Given: - timestamps strings. When: - format_timestamp function called. Then: - Ensure result is correct. """ from CiscoEmailSecurityApplianceIronPortV2 import format_timestamp result = format_timestamp(timestamp, output_format) assert result == expected_result data_test_fetch_incidents = [ ({}, 0, {}), ({}, 1, {"last_minute_incident_ids": [1], "start_time": "2023-06-29T00:00:00Z"}), ({}, 2, {"last_minute_incident_ids": [1, 2], "start_time": "2023-06-29T00:00:00Z"}), ( {"last_minute_incident_ids": [1, 2]}, 2, {"offset": 2, "last_minute_incident_ids": [1, 2]}, ), ( {"last_minute_incident_ids": [1, 2], "offset": 2}, 2, {"last_minute_incident_ids": [1, 2], "offset": 4}, ), ( {"last_minute_incident_ids": [3, 2], "offset": 2}, 1, {"last_minute_incident_ids": [3, 2, 1], "start_time": "2023-06-29T00:00:00Z"}, ), ] @pytest.mark.parametrize("previous_run, fetch_size, expected_last_run", data_test_fetch_incidents) @freeze_time("2023-06-29T00:00:00Z") def test_fetch_incidents(mock_client, mocker, previous_run, fetch_size, expected_last_run): from CiscoEmailSecurityApplianceIronPortV2 import fetch_incidents mocker.patch.object( mock_client, "spam_quarantine_message_search_request", return_value={"data": [{"attributes": {"date": "now"}, "mid": i + 1} for i in range(fetch_size)]}, ) incidents = [{"mid": i + 1} for i in range(fetch_size)] mocker.patch.object( mock_client, "spam_quarantine_message_get_request", new=lambda *_a, **_b: {"data": incidents.pop(0)}, ) _, last_run = fetch_incidents( mock_client, max_fetch=2, first_fetch="1 day", last_run=previous_run, ) assert last_run == expected_last_run def test_check_dictionary_mode_args(): """ Given: - A mode type ("group" or "machine") and respective arguments (`host_name` and `group_name`). When: - The check_dictionary_mode_args function is called with these arguments. Then: - Ensure the function correctly returns a tuple with the appropriate host name and group name based on the mode. """ from CiscoEmailSecurityApplianceIronPortV2 import ( check_dictionary_mode_args, ) assert check_dictionary_mode_args("group", host_name="", group_name="group1") == (None, "group1") assert check_dictionary_mode_args("machine", host_name="host1", group_name="") == ("host1", None) def test_convert_words_to_list(): """ Given: - A string representing a list of lists containing words, numbers, or both. When: - The convert_words_to_list function is called with the input string. Then: - Ensure the function correctly converts the input string to a list of lists, preserving the order and data types. """ from CiscoEmailSecurityApplianceIronPortV2 import ( convert_words_to_list, ) assert convert_words_to_list("['test']") == [["test"]] assert convert_words_to_list("['test1'],['test2']") == [["test1"], ["test2"]] assert convert_words_to_list("['test1',5],['test2',7]") == [["test1", 5], ["test2", 7]] assert convert_words_to_list("['test1',5,'prefix'],['test2',7]") == [["test1", 5, "prefix"], ["test2", 7]] def test_dictionary_list_command(mocker, mock_client): """ Given: - A dictionary name as input. When: - The dictionary_list_command is called. Then: - Ensure the command returns the correct information about the dictionary. """ from CiscoEmailSecurityApplianceIronPortV2 import ( dictionary_list_command, ) mock_response = { "data": [ { "name": "example_dictionary", "encoding": "UTF-8", "ignorecase": 1, "words": ["example", "test", "demo"], "words_count": { "term_count": 3, "smart_identifier_count": 1, }, "wholewords": 0, } ] } mocker.patch("CiscoEmailSecurityApplianceIronPortV2.Client.dictionary_list_request", return_value=mock_response) args = {"dictionary_name": "example_dictionary"} result = dictionary_list_command(mock_client, args) assert "Information for Dictionary: example_dictionary" in result.readable_output outputs = result.outputs assert outputs == mock_response["data"] dictionary_output = outputs[0] assert dictionary_output["name"] == "example_dictionary" assert dictionary_output["encoding"] == "UTF-8" assert dictionary_output["ignorecase"] == 1 assert dictionary_output["words"] == ["example", "test", "demo"] assert dictionary_output["words_count"]["term_count"] == 3 assert dictionary_output["words_count"]["smart_identifier_count"] == 1 assert dictionary_output["wholewords"] == 0 def test_dictionary_add_command(mocker, mock_client): """ Given: - A dictionary name and words to add. When: - The dictionary_add_command is called. Then: - Ensure the dictionary is added successfully with the correct output message. """ from CiscoEmailSecurityApplianceIronPortV2 import ( dictionary_add_command, ) mocker.patch("CiscoEmailSecurityApplianceIronPortV2.Client.dictionary_add_request", return_value={"status": "success"}) args = {"dictionary_name": "TestDict", "words": "[['word1'],['word2']]"} result = dictionary_add_command(mock_client, args) assert "TestDict was added successfully." in result.readable_output def test_dictionary_edit_command(mocker, mock_client): """ Given: - A dictionary name, updated name, and new words. When: - The dictionary_edit_command is called. Then: - Ensure the dictionary is updated successfully with the correct output message. """ from CiscoEmailSecurityApplianceIronPortV2 import ( dictionary_edit_command, ) mocker.patch("CiscoEmailSecurityApplianceIronPortV2.Client.dictionary_edit_request", return_value={"status": "success"}) args = {"dictionary_name": "TestDict", "updated_name": "NewTestDict", "words": "[['word1'],['word2']]"} result = dictionary_edit_command(mock_client, args) assert "TestDict has been successfully updated." in result.readable_output def test_dictionary_delete_command(mocker, mock_client): """ Given: - A dictionary name to delete. When: - The dictionary_delete_command is called. Then: - Ensure the dictionary is deleted successfully with the correct output message. """ from CiscoEmailSecurityApplianceIronPortV2 import ( dictionary_delete_command, ) mocker.patch("CiscoEmailSecurityApplianceIronPortV2.Client.dictionary_delete_request", return_value={"status": "success"}) args = {"dictionary_name": "TestDict"} result = dictionary_delete_command(mock_client, args) assert "TestDict deleted successfully." in result.readable_output def test_dictionary_words_add_command(mocker, mock_client): """ Given: - A dictionary name and words to add to it. When: - The dictionary_words_add_command is called. Then: - Ensure the words are added successfully with the correct output message. """ from CiscoEmailSecurityApplianceIronPortV2 import ( dictionary_words_add_command, ) mocker.patch("CiscoEmailSecurityApplianceIronPortV2.Client.dictionary_words_add_request", return_value={"status": "success"}) args = {"dictionary_name": "TestDict", "words": "['word1', 'word2']"} result = dictionary_words_add_command(mock_client, args) assert "Added successfully to TestDict." in result.readable_output def test_dictionary_words_delete_command(mocker, mock_client): """ Given: - A dictionary name and words to delete from it. When: - The dictionary_words_delete_command is called. Then: - Ensure the words are deleted successfully with the correct output message and result type. """ from CiscoEmailSecurityApplianceIronPortV2 import ( dictionary_words_delete_command, ) mocker.patch( "CiscoEmailSecurityApplianceIronPortV2.Client.dictionary_words_delete_request", return_value={"status": "success"} ) args = {"dictionary_name": "TestDict", "words": "['word1', 'word2']"} result = dictionary_words_delete_command(mock_client, args) assert "Words deleted successfully from TestDict." in result.readable_output def test_dictionary_words_update_command(mock_client, requests_mock): """ Scenario: Retrieve all URL lists. """ from CiscoEmailSecurityApplianceIronPortV2 import dictionary_words_update_command args = {"dictionary_name": "TestDict", "words": "['*credit',6,'prefix'],['test2']"} url = f"{BASE_URL}/config/dictionaries/TestDict/words?device_type=esa&mode=cluster" mock_response = load_mock_response("updated_successfully.json") requests_mock.put(url=url, json=mock_response) result = dictionary_words_update_command(mock_client, args) assert "Added successfully to TestDict." in result.readable_output def test_url_list_all_command(mock_client, requests_mock): """ Scenario: Retrieve all URL lists. """ from CiscoEmailSecurityApplianceIronPortV2 import url_list_command args = {"mode": "cluster", "limit": "50", "all_results": False} url = f"{BASE_URL}/config/url_lists" mock_response = load_mock_response("url_list.json") requests_mock.get(url=url, json=mock_response) result = url_list_command(mock_client, args) assert result.outputs_prefix == "CiscoESA.URLList" assert isinstance(result.outputs, list) assert len(result.outputs) == 3 assert result.outputs[0]["name"] == "urllisttest" def test_url_list_single_command(mock_client, requests_mock): """ Scenario: Retrieve a specific URL list by name. """ from CiscoEmailSecurityApplianceIronPortV2 import url_list_command args = {"mode": "cluster", "url_list_name": "BlockUrls"} url = f"{BASE_URL}/config/url_lists/BlockUrls" mock_response = load_mock_response("url_list_single.json") requests_mock.get(url=url, json=mock_response) result = url_list_command(mock_client, args) assert result.outputs_prefix == "CiscoESA.URLList" assert isinstance(result.outputs, dict) assert result.outputs["name"] == "urllisttest_single" def test_url_list_create_command(mock_client, requests_mock): from CiscoEmailSecurityApplianceIronPortV2 import url_list_create_command args = {"url_list_name": "TestList", "urls": "http://malicious.com,https://evil.com"} url = f"{BASE_URL}/config/url_lists/TestList" requests_mock.post( url=url, json=load_mock_response("added_successfully.json"), ) result = url_list_create_command(mock_client, args) assert "TestList" in result.readable_output def test_url_list_update_command(mock_client, requests_mock): from CiscoEmailSecurityApplianceIronPortV2 import url_list_update_command args = {"url_list_name": "TestList", "urls": "https://update.com"} url = f"{BASE_URL}/config/url_lists/TestList" requests_mock.put(url=url, json=load_mock_response("updated_successfully.json")) result = url_list_update_command(mock_client, args) assert "TestList" in result.readable_output def test_url_list_delete_command(mock_client, requests_mock): from CiscoEmailSecurityApplianceIronPortV2 import url_list_delete_command args = {"url_list_names": "TestList1,TestList2"} url = f"{BASE_URL}/config/url_lists" requests_mock.delete(url=url, json={"data": {"message": "Deleted Successfully"}}) result = url_list_delete_command(mock_client, args) assert "TestList1" in result.readable_output assert "TestList2" in result.readable_output def test_file_hash_list_all_command(mock_client, requests_mock): """ Scenario: Retrieve all File Hash lists. """ from CiscoEmailSecurityApplianceIronPortV2 import file_hash_list_command args = {"mode": "cluster"} url = f"{BASE_URL}/config/file_hash_lists" mock_response = load_mock_response("file_hash_list.json") requests_mock.get(url=url, json=mock_response) result = file_hash_list_command(mock_client, args) assert result.outputs_prefix == "CiscoESA.FileHashList" assert isinstance(result.outputs, list) assert len(result.outputs) == 2 assert result.outputs[0]["name"] == "test" def test_file_hash_list_single_command(mock_client, requests_mock): """ Scenario: Retrieve a specific File Hash list by name. """ from CiscoEmailSecurityApplianceIronPortV2 import file_hash_list_command args = {"mode": "cluster", "file_hash_list_name": "MyList"} url = f"{BASE_URL}/config/file_hash_lists/MyList" mock_response = load_mock_response("file_hash_list_single.json") requests_mock.get(url=url, json=mock_response) result = file_hash_list_command(mock_client, args) assert result.outputs_prefix == "CiscoESA.FileHashList" assert isinstance(result.outputs, dict) assert result.outputs["name"] == "test" def test_file_hash_create_command(mock_client, requests_mock): from CiscoEmailSecurityApplianceIronPortV2 import file_hash_create_command args = { "file_hash_list_name": "MalwareHashes", "filehashes": "abcd1234,abcd5678", "description": "Test hash list", "list_type": "sha256", } url = f"{BASE_URL}/config/file_hash_lists/MalwareHashes" requests_mock.post(url=url, json=load_mock_response("added_successfully.json")) result = file_hash_create_command(mock_client, args) assert "MalwareHashes" in result.readable_output def test_file_hash_update_command(mock_client, requests_mock): from CiscoEmailSecurityApplianceIronPortV2 import file_hash_update_command args = {"file_hash_list_name": "MalwareHashes", "filehashes": "updated1234"} url = f"{BASE_URL}/config/file_hash_lists/MalwareHashes" requests_mock.put(url=url, json=load_mock_response("updated_successfully.json")) result = file_hash_update_command(mock_client, args) assert "MalwareHashes" in result.readable_output @pytest.mark.parametrize( "response_file_name, args, expected_rule_id", [ ("pvo_quarantine_list.json", {"type": "pvo"}, "Malware: Malware"), ], ) def test_pvo_quarantine_list_command(response_file_name, args, expected_rule_id, mock_client, requests_mock): from CiscoEmailSecurityApplianceIronPortV2 import pvo_quarantine_list_command url = f"{BASE_URL}/quarantine/rules" mock_response = load_mock_response(response_file_name) requests_mock.get(url=url, json=mock_response) result = pvo_quarantine_list_command(mock_client, args) assert result.outputs_prefix == "CiscoESA.QuarantineRule" assert any(entry["rule_id"] == expected_rule_id for entry in result.outputs) def test_pvo_quarantine_release_command(mock_client, requests_mock): from CiscoEmailSecurityApplianceIronPortV2 import pvo_quarantine_release_command args = {"rule_ids": "pvo_123", "quarantine_type": "pvo"} url = f"{BASE_URL}/quarantine/rules" requests_mock.post(url=url, json={}) result = pvo_quarantine_release_command(mock_client, args) assert "pvo_123" in result.readable_output def test_pvo_quarantine_delete_command(mock_client, requests_mock): from CiscoEmailSecurityApplianceIronPortV2 import pvo_quarantine_delete_command args = {"rule_ids": "pvo_123", "quarantine_type": "pvo"} url = f"{BASE_URL}/quarantine/rules" requests_mock.delete(url=url, json={}) result = pvo_quarantine_delete_command(mock_client, args) assert "pvo_123" in result.readable_output @pytest.mark.parametrize( "response_file_name, args, expected_sender", [ ( "user_entry_list.json", {"mode": "cluster", "policy_name": "Inbound Policy"}, "yyo@[1.11.11.1]", ) ], ) def test_user_entry_list_command(response_file_name, args, expected_sender, mock_client, requests_mock): """ Scenario: Retrieve user entry list for a given mail policy. """ from CiscoEmailSecurityApplianceIronPortV2 import user_entry_list_command url = f"{BASE_URL}/config/incoming_mail_policies/{args['policy_name']}/senders_and_recipients" mock_response = load_mock_response(response_file_name) requests_mock.get(url=url, json=mock_response) result = user_entry_list_command(mock_client, args) assert result.outputs_prefix == "CiscoESA.IncomingMailPolicyUser" # Look through sender domain entries explicitly found = any( expected_sender in entry.get("sender_config", {}).get("sender", {}).get("domain_entries", []) for entry in result.outputs ) assert found, f"Expected sender {expected_sender} not found in outputs" def test_user_entry_add_command(mock_client, requests_mock): """ Scenario: Add sender/receiver entries to a mail policy. """ from CiscoEmailSecurityApplianceIronPortV2 import user_entry_add_command args = { "mode": "cluster", "policy_name": "Inbound Policy", "sender_domain_entries": "user@example.com", "receiver_operation": "and", "receiver_domain_entries": "target@example.com", } url = f"{BASE_URL}/config/incoming_mail_policies/{args['policy_name']}/senders_and_recipients" requests_mock.post(url=url, json=load_mock_response("added_successfully.json")) result = user_entry_add_command(mock_client, args) assert "Inbound Policy" in result.readable_output def test_user_entry_update_command(mock_client, requests_mock): """ Scenario: Update sender/receiver entries in a mail policy. """ from CiscoEmailSecurityApplianceIronPortV2 import user_entry_update_command args = { "mode": "cluster", "policy_name": "Inbound Policy", "sender_domain_entries": "updated@example.com", "receiver_operation": "or", "receiver_domain_entries": "any@example.com", } url = f"{BASE_URL}/config/incoming_mail_policies/{args['policy_name']}/senders_and_recipients" requests_mock.get(url=url, json=load_mock_response("user_entry_list.json")) requests_mock.put(url=url, json=load_mock_response("updated_successfully.json")) result = user_entry_update_command(mock_client, args) assert "Inbound Policy" in result.readable_output def test_message_connection_details_get_command(mock_client, requests_mock): from CiscoEmailSecurityApplianceIronPortV2 import message_connection_details_get_command args = { "serial_number": "TEST_SERIAL", "message_ids": "123,456", "injection_connection_id": "789", } url = f"{BASE_URL}/message-tracking/connection-details" mock_response = load_mock_response("message_connection_details_get.json") requests_mock.get(url, json=mock_response) result = message_connection_details_get_command(mock_client, args) assert result.outputs_prefix == "CiscoESA.MessageConnection" assert isinstance(result.outputs, dict) assert "Message" in result.outputs def test_message_remediation_details_get_command(mock_client, requests_mock): from CiscoEmailSecurityApplianceIronPortV2 import message_remediation_details_get_command args = {"serial_number": "TEST_SERIAL", "message_ids": "999", "injection_connection_id": "555"} url = f"{BASE_URL}/message-tracking/remediation-details" mock_response = load_mock_response("message_remediation_details_get.json") requests_mock.get(url, json=mock_response) result = message_remediation_details_get_command(mock_client, args) assert result.outputs_prefix == "CiscoESA.MessageRemediation" assert isinstance(result.outputs, dict) assert "batch_details" in result.outputs assert "message_details" in result.outputs def test_message_filter_list_command_all(requests_mock, mock_client): """ Scenario: List all message filters (no filter_name). Given: - A valid client. - No filter_name argument. When: - cisco-esa-message-filter-list is called. Then: - Outputs prefix is CiscoESA.MessageFilter with replace_existing=True (full-array overwrite semantics; deleted filters drop out). - All rows from the fixture's data array are returned. - device_type=esa is passed in the underlying request. """ from CiscoEmailSecurityApplianceIronPortV2 import message_filter_list_command mock_response = load_mock_response("message_filter_list_all.json") url = f"{BASE_URL}/config/message_filters" requests_mock.get(url=url, json=mock_response) result = message_filter_list_command(mock_client, {}) assert result.outputs_prefix == "CiscoESA.MessageFilter" assert result.replace_existing is True assert result.outputs == mock_response["data"] assert len(result.outputs) == 3 assert {row["name"] for row in result.outputs} == {"F1", "F2", "F3"} assert requests_mock.last_request.qs.get("device_type") == ["esa"] def test_message_filter_list_command_specific(requests_mock, mock_client): """ Scenario: List a specific filter by name. Given: - filter_name argument. When: - cisco-esa-message-filter-list is called. Then: - Endpoint includes the filter name. - Outputs prefix is CiscoESA.MessageFilter; replace_existing is False (single-row lookup must not wipe the collection). - Outputs contain the single returned row (no extra wrapping). - Title in HR mentions the filter name. """ from CiscoEmailSecurityApplianceIronPortV2 import message_filter_list_command mock_response = load_mock_response("message_filter_list_specific.json") url = f"{BASE_URL}/config/message_filters/F1" requests_mock.get(url=url, json=mock_response) result = message_filter_list_command(mock_client, {"filter_name": "F1"}) assert result.outputs_prefix == "CiscoESA.MessageFilter" assert result.replace_existing is False assert result.outputs == mock_response["data"] assert len(result.outputs) == 1 assert result.outputs[0]["name"] == "F1" assert "F1" in result.readable_output def test_message_filter_list_command_emits_overwrite_dt_form(requests_mock, mock_client): """ Scenario: List-all emits the parent-level DT-predicate context shape so the server overwrites only the MessageFilter sub-key, preserving CiscoESA siblings. """ from CiscoEmailSecurityApplianceIronPortV2 import message_filter_list_command mock_response = load_mock_response("message_filter_list_all.json") url = f"{BASE_URL}/config/message_filters" requests_mock.get(url=url, json=mock_response) result = message_filter_list_command(mock_client, {}) entry_context = result.to_context()["EntryContext"] assert "CiscoESA(true)" in entry_context assert list(entry_context["CiscoESA(true)"].keys()) == ["MessageFilter"] assert entry_context["CiscoESA(true)"]["MessageFilter"] == mock_response["data"] assert "CiscoESA.MessageFilter(true)" not in entry_context def test_message_filter_list_command_with_active_true_filter(requests_mock, mock_client): """ Scenario: List filters with active=true filter applied client-side. Given: - Mixed-active fixture (2 active, 2 inactive rows). - active='true' argument. When: - cisco-esa-message-filter-list is called. Then: - Only rows where active == 'true' are returned in outputs. """ from CiscoEmailSecurityApplianceIronPortV2 import message_filter_list_command mock_response = load_mock_response("message_filter_list_mixed_active.json") url = f"{BASE_URL}/config/message_filters" requests_mock.get(url=url, json=mock_response) result = message_filter_list_command(mock_client, {"active": "true"}) assert len(result.outputs) == 2 assert all(row["active"] == "true" for row in result.outputs) assert {row["name"] for row in result.outputs} == {"F1", "F3"} def test_message_filter_list_command_with_active_false_filter(requests_mock, mock_client): """ Scenario: List filters with active=false filter applied client-side. Given: - Mixed-active fixture (2 active, 2 inactive rows). - active='false' argument. When: - cisco-esa-message-filter-list is called. Then: - Only rows where active == 'false' are returned in outputs. """ from CiscoEmailSecurityApplianceIronPortV2 import message_filter_list_command mock_response = load_mock_response("message_filter_list_mixed_active.json") url = f"{BASE_URL}/config/message_filters" requests_mock.get(url=url, json=mock_response) result = message_filter_list_command(mock_client, {"active": "false"}) assert len(result.outputs) == 2 assert all(row["active"] == "false" for row in result.outputs) assert {row["name"] for row in result.outputs} == {"F2", "F4"} def test_message_filter_list_command_with_limit(requests_mock, mock_client): """ Scenario: Truncate the list to the requested limit. Given: - A fixture with 3 rows. - limit=1 argument. When: - cisco-esa-message-filter-list is called. Then: - Only the first row is returned. """ from CiscoEmailSecurityApplianceIronPortV2 import message_filter_list_command mock_response = load_mock_response("message_filter_list_all.json") url = f"{BASE_URL}/config/message_filters" requests_mock.get(url=url, json=mock_response) result = message_filter_list_command(mock_client, {"limit": "1"}) assert len(result.outputs) == 1 assert result.outputs[0]["name"] == "F1" def test_message_filter_list_command_hr_includes_invalid_reason_column(requests_mock, mock_client): """ Scenario: HR table includes the 'Validation Warning' column when at least one row has invalid_reason. Given: - A fixture where some rows include the invalid_reason key. When: - cisco-esa-message-filter-list is called. Then: - The 'Validation Warning' column appears in the readable output. """ from CiscoEmailSecurityApplianceIronPortV2 import message_filter_list_command mock_response = load_mock_response("message_filter_list_all.json") url = f"{BASE_URL}/config/message_filters" requests_mock.get(url=url, json=mock_response) result = message_filter_list_command(mock_client, {}) assert "Validation Warning" in result.readable_output def test_message_filter_list_command_hr_omits_invalid_reason_column(requests_mock, mock_client): """ Scenario: HR table omits the 'Validation Warning' column when no row has invalid_reason. Given: - A fixture where no rows include the invalid_reason key. When: - cisco-esa-message-filter-list is called. Then: - The 'Validation Warning' column does NOT appear in the readable output. """ from CiscoEmailSecurityApplianceIronPortV2 import message_filter_list_command mock_response = load_mock_response("message_filter_list_no_invalid.json") url = f"{BASE_URL}/config/message_filters" requests_mock.get(url=url, json=mock_response) result = message_filter_list_command(mock_client, {}) assert "Validation Warning" not in result.readable_output def test_message_filter_create_command_happy_path(requests_mock, mock_client): """ Scenario: Create a new message filter — success without warning. Given: - filter_name, rules_and_actions, active, order arguments. When: - cisco-esa-message-filter-create is called. Then: - HR confirms the filter name was added successfully. - No 'Warning:' segment appears in HR. - The request body includes rules_and_actions, active, and order (no None values). - device_type=esa is passed in the underlying request. """ from CiscoEmailSecurityApplianceIronPortV2 import message_filter_create_command mock_response = load_mock_response("message_filter_create_response.json") url = f"{BASE_URL}/config/message_filters/my_filter" requests_mock.post(url=url, json=mock_response) args = { "filter_name": "my_filter", "rules_and_actions": "if (true) { skip-filters(); }", "active": "true", "order": "2", } result = message_filter_create_command(mock_client, args) assert "my_filter" in result.readable_output assert "added successfully" in result.readable_output.lower() assert "Warning:" not in result.readable_output sent_body = requests_mock.last_request.json()["data"] assert sent_body == { "rules_and_actions": "if (true) { skip-filters(); }", "active": "true", "order": 2, } assert requests_mock.last_request.qs.get("device_type") == ["esa"] def test_message_filter_create_command_with_warning(requests_mock, mock_client): """ Scenario: Create succeeds but the appliance returns meta.warning. Given: - filter_name and rules_and_actions arguments. - The API returns meta.warning. When: - cisco-esa-message-filter-create is called. Then: - The command does not raise. - HR contains both the success line and the warning text. """ from CiscoEmailSecurityApplianceIronPortV2 import message_filter_create_command mock_response = load_mock_response("message_filter_create_warning.json") url = f"{BASE_URL}/config/message_filters/f3" requests_mock.post(url=url, json=mock_response) args = { "filter_name": "f3", "rules_and_actions": "if (true) { skip-filters(); }", } result = message_filter_create_command(mock_client, args) assert "f3 was added successfully" in result.readable_output assert "Warning:" in result.readable_output assert mock_response["meta"]["warning"] in result.readable_output def test_message_filter_create_command_body_drops_none_order(requests_mock, mock_client): """ Scenario: Optional `order` is omitted by the user. Given: - filter_name + rules_and_actions only (no order). When: - cisco-esa-message-filter-create is called. Then: - The request body contains rules_and_actions and active but NOT 'order' (None dropped by assign_params). """ from CiscoEmailSecurityApplianceIronPortV2 import message_filter_create_command mock_response = load_mock_response("message_filter_create_response.json") url = f"{BASE_URL}/config/message_filters/my_filter" requests_mock.post(url=url, json=mock_response) args = { "filter_name": "my_filter", "rules_and_actions": "if (true) { skip-filters(); }", } message_filter_create_command(mock_client, args) sent_body = requests_mock.last_request.json()["data"] assert "order" not in sent_body assert sent_body.get("rules_and_actions") == "if (true) { skip-filters(); }" assert sent_body.get("active") == "true" def test_message_filter_update_command_happy_path_only_active(requests_mock, mock_client): """ Scenario: Update a filter providing only `active` (no rules_and_actions, no order). Given: - filter_name and active arguments only. When: - cisco-esa-message-filter-update is called. Then: - HR confirms the filter was successfully updated. - The request body contains only the 'active' key. """ from CiscoEmailSecurityApplianceIronPortV2 import message_filter_update_command mock_response = load_mock_response("message_filter_update_response.json") url = f"{BASE_URL}/config/message_filters/my_filter" requests_mock.put(url=url, json=mock_response) args = {"filter_name": "my_filter", "active": "false"} result = message_filter_update_command(mock_client, args) assert "my_filter was successfully updated" in result.readable_output sent_body = requests_mock.last_request.json()["data"] assert sent_body == {"active": "false"} def test_message_filter_update_command_no_updatable_fields_raises(mock_client): """ Scenario: Update is called without any of active/order/rules_and_actions. Given: - filter_name only. When: - cisco-esa-message-filter-update is called. Then: - DemistoException is raised. """ from CommonServerPython import DemistoException from CiscoEmailSecurityApplianceIronPortV2 import message_filter_update_command with pytest.raises(DemistoException): message_filter_update_command(mock_client, {"filter_name": "my_filter"}) def test_message_filter_delete_command_happy_path(requests_mock, mock_client): """ Scenario: Delete a message filter. Given: - filter_name argument. When: - cisco-esa-message-filter-delete is called. Then: - HR confirms deletion of the named filter. - device_type=esa is passed in the underlying request. """ from CiscoEmailSecurityApplianceIronPortV2 import message_filter_delete_command mock_response = load_mock_response("message_filter_delete_response.json") url = f"{BASE_URL}/config/message_filters/F1" requests_mock.delete(url=url, json=mock_response) result = message_filter_delete_command(mock_client, {"filter_name": "F1"}) assert "F1 was deleted successfully" in result.readable_output assert requests_mock.last_request.qs.get("device_type") == ["esa"]