IdentifyAttachedEmail
Identify whether the incident includes an email message attached as an eml or msg file and return the answer to playbook. Also saves the identified entry ID to context for use for later. Commonly used in automated playbooks that handle phishing reports sent to a special phishing mailbox set up by the security team.
python · Common Scripts
Details
| ID | IdentifyAttachedEmail |
|---|---|
| Language | python |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.13.10404775 |
| Tags | phishing email Condition |
README
Identify whether the incident includes an email message attached as an eml or msg file and return the answer to playbook.
Also saves the identified entry ID to context for use for later.
Commonly used in automated playbooks that handle phishing reports sent to a special phishing mailbox set up by the security team.
Script Data
| Name | Description |
|---|---|
| Script Type | python2 |
| Tags | phishing, email, Condition |
| Cortex XSOAR Version | 5.0.0 |
Used In
This script is used in the following playbooks and scripts.
- Process Email - Core
- Process Email - Core v2
- Process Email - Generic
- Process Email - Generic v2
Inputs
| Argument Name | Description |
|---|---|
| entryid | Specific entryid to check if it is an email attachment. If not specified will check all entries of the incident. |
Outputs
| Path | Description | Type |
|---|---|---|
| yes | If incident contains an email attachment. | Unknown |
| no | If incident does not contain an email attachment | Unknown |
| reportedemailentryid | The entry IDs of the email attachments found. | String |
import IdentifyAttachedEmail import pytest from IdentifyAttachedEmail import * def execute_command(command, args): if command == "getEntry": if args["id"] == "23@2": return [{"Type": entryTypes["note"], "FileMetadata": {"info": "koko"}, "ID": "23@2"}] elif args["id"] == "24@2": return [ { "Type": entryTypes["file"], "FileMetadata": {"info": "news or mail text, ASCII text", "type": "eml"}, "ID": "24@2", } ] if command == "getEntries": return {} return None def test_is_email(): # valid - type and info are present and valid assert is_email({"type": "eml}", "info": "SMTP mail, UTF-8 Unicode text"}, "test.txt") assert is_email({"type": "eml", "info": "SMTP mail, UTF-8 Unicode text"}, "test.txt") assert is_email({"type": "message/rfc822", "info": "SMTP mail, UTF-8 Unicode text"}, "test.txt") assert is_email({"info": "CDFV2 Microsoft Outlook Message", "type": "eml"}, "msg.test") assert is_email( {"info": "RFC 822 mail text, ISO-8859 text, with very long lines, with CRLF line terminator", "type": "eml"}, "test.bin" ) assert is_email({"info": "CDFV2 Microsoft Outlook Message", "type": "eml"}, "test.bin") assert is_email( { "info": 'multipart/signed; protocol="application/pkcs7-signature";, ASCII text, with CRLF line terminators', "type": "eml", }, "test.bin", ) assert is_email({"info": "CDFV2 Microsoft Outlook Message", "type": "msg"}, "test.msg") # invalid - info is missing with wrong type assert not is_email({"type": "invalid type"}, "test.txt") # valid - info is missing with valid type assert is_email({"type": "eml"}, "test.txt") assert is_email({"type": "eml}"}, "test.eml") assert is_email({"type": "message/rfc822"}, "test.msg") # invalid - info is missing with invalid type assert not is_email({"type": "invalid type"}, "test.txt") # valid - type is missing with valid info assert is_email({"info": "SMTP mail, UTF-8 Unicode text"}, "test.eml") # invalid - type is missing with invalid info assert not is_email({"info": "invalid info"}, "test.eml") # invalid - wrong type assert not is_email({"type": "invalid type", "info": "SMTP mail, UTF-8 Unicode text"}, "test.txt") assert not is_email({"type": "message/rfc822", "info": "vCalendar calendar file"}, "Workshop.eml") assert not is_email({"type": "eml", "info": "vCalendar calendar file"}, "Workshop.eml") # invalid - wrong info assert not is_email({"type": "eml", "info": "invalid info"}, "test.txt") # valid - .eml file with "text" or "data" in the info assert is_email({"info": "ASCII text, with CRLF line terminators"}, "msg.eml") assert is_email({"info": "data"}, "test.eml") assert is_email({"info": "UTF-8 Unicode text, with very long lines, with CRLF line terminators"}, "test.eml") # invalid - file is not .msg or .eml assert not is_email({"info": "data"}, "test.bin") assert not is_email({"info": "composite document file v2 document"}, "cv.doc") def test_get_email_entry_id(mocker): mocker.patch.object(IdentifyAttachedEmail, "is_email", return_value=True) assert not get_email_entry_id("") def test_identify_attached_mail(mocker): entry_ids = '["23@2","24@2"]' from CommonServerPython import demisto mocker.patch.object(demisto, "executeCommand", side_effect=execute_command) args = {"entryid": entry_ids} results = identify_attached_mail(args) assert results == ("yes", {"reportedemailentryid": ["24@2"]}) def test_identify_attached_mail_no_email_attached(mocker): entry_ids = """[\"23@2\"]""" from CommonServerPython import demisto mocker.patch.object(demisto, "executeCommand", side_effect=execute_command) args = {"entryid": entry_ids} results = identify_attached_mail(args) assert results == ("no", None) def test_identify_attached_mail_in_xsoar_saas_list_of_entries_passed(mocker): """ Given - two entries with ids 23@2 24@2 - the platform is xsoar saas When - running the script to get the entries Then - expect the getEntriesByIDs to be called """ entry_ids = """[\"23@2\",\"24@2\"]""" import CommonServerPython mocker.patch.object(CommonServerPython, "get_demisto_version", return_value={"version": "8.2.0", "buildNumber": "12345"}) def execute_command(command, args): if command == "getEntriesByIDs" and args.get("entryIDs") == "23@2,24@2": return [ {"File": "msg.eml", "FileMetadata": {"info": "ASCII text, with CRLF line terminators"}, "ID": "23@2"}, {"File": "foo.txt", "FileMetadata": {"info": "ASCII text, with CRLF line terminators"}, "ID": "24@2"}, ] else: pytest.fail() mocker.patch.object(demisto, "executeCommand", side_effect=execute_command) args = {"entryid": entry_ids} results = identify_attached_mail(args) assert results == ("yes", {"reportedemailentryid": ["23@2"]}) def test_identify_attached_mail_no_entries_passed(mocker): """ Given - no entries passed - the platform is xsoar saas When - running the script to get the entries Then - expect the getEntries to be called with filters """ import CommonServerPython mocker.patch.object(CommonServerPython, "get_demisto_version", return_value={"version": "8.2.0", "buildNumber": "12345"}) def execute_command(command, args): if command == "getEntries" and args == {"filter": {"categories": ["attachments"]}}: return [ {"File": "msg.eml", "FileMetadata": {"info": "ASCII text, with CRLF line terminators"}, "ID": "23@2"}, {"File": "foo.txt", "FileMetadata": {"info": "ASCII text, with CRLF line terminators"}, "ID": "24@2"}, ] else: pytest.fail() mocker.patch.object(demisto, "executeCommand", side_effect=execute_command) results = identify_attached_mail({}) assert results == ("yes", {"reportedemailentryid": ["23@2"]}) def test_identify_attached_mail_no_email_found(mocker): """ Given - no email entries in the warroom - the platform is xsoar saas When - running the script to get the entries Then - no entries to be found """ import CommonServerPython mocker.patch.object(CommonServerPython, "get_demisto_version", return_value={"version": "8.2.0", "buildNumber": "12345"}) def execute_command(command, args): if command == "getEntries" and args == {"filter": {"categories": ["attachments"]}}: return else: pytest.fail() mocker.patch.object(demisto, "executeCommand", side_effect=execute_command) results = identify_attached_mail({}) assert results == ("no", None) def test_list_of_entries_passed_in_xsoar_saas_but_no_file_entries(mocker): """ Given - two entries with ids 23@2 24@2 which are not file entries - the platform is xsoar saas When - running the script to get the entries Then - expect the getEntriesByIDs to be called - expect no email entries to be found """ entry_ids = """[\"23@2\",\"24@2\"]""" import CommonServerPython mocker.patch.object(CommonServerPython, "get_demisto_version", return_value={"version": "8.2.0", "buildNumber": "12345"}) def execute_command(command, args): if command == "getEntriesByIDs" and args.get("entryIDs") == "23@2,24@2": return [ {"File": "msg.txt", "FileMetadata": {"info": "ASCII text, with CRLF line terminators"}, "ID": "23@2"}, {"File": "foo.txt", "FileMetadata": {"info": "ASCII text, with CRLF line terminators"}, "ID": "24@2"}, ] else: pytest.fail() mocker.patch.object(demisto, "executeCommand", side_effect=execute_command) args = {"entryid": entry_ids} results = identify_attached_mail(args) assert results == ("no", None)