Skip to content

Commit

Permalink
addEntries async call (#28658)
Browse files Browse the repository at this point in the history
  • Loading branch information
tkatzir committed Aug 9, 2023
1 parent 232377c commit f98110c
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 23 deletions.
12 changes: 12 additions & 0 deletions Packs/EmailCommunication/ReleaseNotes/2_0_12.md
@@ -0,0 +1,12 @@

#### Scripts

##### SendEmailReply
- Added support for the *reputation_calc_async* parameter, to prevent timeouts.
- Updated the Docker image to: *demisto/python3:3.10.12.68300*.


##### PreprocessEmail

- Added support for the *reputation_calc_async* parameter, to prevent timeouts.
- Updated the Docker image to: *demisto/python3:3.10.12.68300*.
Expand Up @@ -94,14 +94,15 @@ def get_entry_id_list(attachments, files):
return entry_id_list


def add_entries(email_reply, email_related_incident):
def add_entries(email_reply, email_related_incident, reputation_calc_async=False):
"""Add the entries to the related incident
Args:
email_reply: The email reply.
email_related_incident: The related incident.
"""
entries_str = json.dumps([{"Type": 1, "ContentsFormat": 'html', "Contents": email_reply, "tags": ['email-thread']}])
res = demisto.executeCommand("addEntries", {"entries": entries_str, 'id': email_related_incident})
res = demisto.executeCommand("addEntries", {"entries": entries_str,
'id': email_related_incident, 'reputationCalcAsync': reputation_calc_async})
if is_error(res):
demisto.error(ERROR_TEMPLATE.format('addEntries', res['Contents']))
raise DemistoException(ERROR_TEMPLATE.format('addEntries', res['Contents']))
Expand Down Expand Up @@ -287,6 +288,7 @@ def get_email_related_incident_id(email_related_incident_code, email_original_su
return str(incident.get('id'))
except Exception as e:
demisto.error(f'Exception while retrieving thread context: {e}')
return None


def get_unique_code():
Expand Down Expand Up @@ -325,7 +327,7 @@ def create_thread_context(email_code, email_cc, email_bcc, email_text, email_fro
incident_id: ID of the related incident
attachments: File attachments from the email
"""
thread_number = str()
thread_number = ''
thread_found = False
try:
# Get current email threads from context if any are present
Expand Down Expand Up @@ -380,6 +382,7 @@ def create_thread_context(email_code, email_cc, email_bcc, email_text, email_fro


def main():
args = demisto.args()
incident = demisto.incident()
attachments = incident.get('attachment', [])
custom_fields = incident.get('CustomFields')
Expand All @@ -394,6 +397,8 @@ def main():
email_replyto = custom_fields.get('emailreplyto', '')
email_latest_message = custom_fields.get('emaillatestmessage', '')

reputation_calc_async = argToBoolean(args.get('reputation_calc_async', False))

try:
email_related_incident_code = email_subject.split('<')[1].split('>')[0]
email_original_subject = email_subject.split('<')[-1].split('>')[1].strip()
Expand All @@ -419,7 +424,7 @@ def main():
"Incoming email related to Email Communication Incident"
f" {email_related_incident}. Appending a message there.")
email_reply = set_email_reply(email_from, email_to, email_cc, html_body, attachments)
add_entries(email_reply, email_related_incident)
add_entries(email_reply, email_related_incident, reputation_calc_async)
else:
# For all other incident types, add message details as context entry
demisto.debug(f"Incoming email related to Incident {email_related_incident}. Appending message there.")
Expand Down
Expand Up @@ -8,6 +8,13 @@ args:
- name: CreateIncidentUntaggedEmail
description: Allow the creation of an email for which we can't find an existing incident.
defaultValue: 'true'
- name: reputation_calc_async
auto: PREDEFINED
predefined:
- 'true'
- 'false'
description: Specify whether to calculate the reputation in an asynchronous way.
defaultValue: 'false'
comment: |-
Preprocessing script for email communication layout.
This script checks if the incoming email contains an Incident ID to link the mail to an existing incident, and tags the email as "email-thread".
Expand All @@ -26,7 +33,7 @@ tags:
- email
- preProcessing
type: python
dockerimage: demisto/python3:3.10.12.63474
dockerimage: demisto/python3:3.10.12.68300
runas: DBotRole
tests:
- No tests (auto formatted)
Expand Down
30 changes: 17 additions & 13 deletions Packs/EmailCommunication/Scripts/SendEmailReply/SendEmailReply.py
Expand Up @@ -157,7 +157,7 @@ def create_thread_context(email_code, email_cc, email_bcc, email_text, email_fro
incident_id: ID of the related incident
new_attachment_names: File attachments sent with the email
"""
thread_number = str()
thread_number = ''
thread_found = False
try:
incident_email_threads = get_email_threads(incident_id)
Expand Down Expand Up @@ -403,7 +403,7 @@ def create_file_data_json(attachment, field_name):
return json.dumps(file_data)


def get_reply_body(notes, incident_id, attachments):
def get_reply_body(notes, incident_id, attachments, reputation_calc_async=False):
""" Get the notes and the incident id and return the reply body
Args:
notes (list): The notes of the email.
Expand All @@ -429,7 +429,8 @@ def get_reply_body(notes, incident_id, attachments):

entry_note = json.dumps(
[{"Type": 1, "ContentsFormat": 'html', "Contents": reply_body, "tags": ['email-thread']}])
entry_tags_res = demisto.executeCommand("addEntries", {"entries": entry_note, 'id': incident_id})
entry_tags_res = demisto.executeCommand(
"addEntries", {"entries": entry_note, 'id': incident_id, 'reputationCalcAsync': reputation_calc_async})

entry_note_res = demisto.executeCommand("demisto-api-post", {"uri": "/entry/note", "body": json.dumps(
{"id": note.get('ID'), "version": -1, "investigationId": incident_id, "data": "false"})})
Expand Down Expand Up @@ -613,6 +614,7 @@ def resend_first_contact(email_selected_thread, email_thread, incident_id, new_e
else:
return_error(f'The selected Thread Number to respond to ({email_selected_thread}) '
f'does not exist. Please choose a valid Thread Number and re-try.')
return None


def format_body(new_email_body):
Expand All @@ -633,7 +635,7 @@ def format_body(new_email_body):

def single_thread_reply(email_code, incident_id, email_cc, add_cc, notes, attachments, files, email_subject,
subject_include_incident_id, email_to_str, service_mail, email_latest_message,
mail_sender_instance):
mail_sender_instance, reputation_calc_async=False):
"""
Retrieve all entries in the EmailThreads context key
Args:
Expand Down Expand Up @@ -662,7 +664,7 @@ def single_thread_reply(email_code, incident_id, email_cc, add_cc, notes, attach
'customFields': {'emailgeneratedcode': email_code}})
try:
final_email_cc = get_email_cc(email_cc, add_cc)
reply_body, reply_html_body = get_reply_body(notes, incident_id, attachments)
reply_body, reply_html_body = get_reply_body(notes, incident_id, attachments, reputation_calc_async)
entry_id_list = get_entry_id_list(incident_id, attachments, [], files)
result = validate_email_sent(incident_id, email_subject, subject_include_incident_id, email_to_str, reply_body,
service_mail, final_email_cc, '', reply_html_body, entry_id_list,
Expand Down Expand Up @@ -748,13 +750,13 @@ def collect_thread_details(incident_email_threads, email_selected_thread):
Tuple containing details of the selected email thread for re-use in creating reply message
"""
thread_found = False
reply_to_message_id = str()
reply_recipients = str()
reply_subject = str()
reply_mailbox = str()
thread_cc = str()
thread_bcc = str()
reply_code = str()
reply_to_message_id = ''
reply_recipients = ''
reply_subject = ''
reply_mailbox = ''
thread_cc = ''
thread_bcc = ''
reply_code = ''
outbound_only = True
last_thread_processed = 0

Expand Down Expand Up @@ -973,6 +975,8 @@ def main():
email_selected_thread = custom_fields.get('emailselectedthread')
subject_include_incident_id = argToBoolean(args.get('subject_include_incident_id', False))

argToBoolean(args.get('reputation_calc_async', False))

if new_email_attachments:
new_attachment_names = ', '.join([attachment.get('name', '') for attachment in new_email_attachments])
else:
Expand All @@ -982,7 +986,7 @@ def main():
# This case is run when replying to an email from the 'Email Communication' layout
single_thread_reply(email_code, incident_id, email_cc, add_cc, notes, attachments, files, email_subject,
subject_include_incident_id, email_to_str, service_mail, email_latest_message,
mail_sender_instance)
mail_sender_instance, reputation_calc_async=False)

elif new_thread == 'true':
# This case is run when using the 'Email Threads' layout to send a new first-contact email message
Expand Down
Expand Up @@ -24,6 +24,13 @@ args:
- name: subject_include_incident_id
description: Include the Incident ID within the email subject.
defaultValue: 'false'
- name: reputation_calc_async
auto: PREDEFINED
predefined:
- 'true'
- 'false'
description: Specify whether to calculate the reputation in an asynchronous way.
defaultValue: 'false'
comment: |-
Send email reply
This automation runs using the default Limited User role, unless you explicitly change the permissions.
Expand All @@ -39,7 +46,7 @@ subtype: python3
system: true
type: python
fromversion: 5.0.0
dockerimage: demisto/python3:3.10.12.63474
dockerimage: demisto/python3:3.10.12.68300
tests:
- No tests (auto formatted)
contentitemexportablefields:
Expand Down
Expand Up @@ -5,12 +5,12 @@


def util_open_file(path):
with open(path, mode='r') as f:
with open(path) as f:
return f.read()


def util_load_json(path):
with open(path, mode='r') as f:
with open(path) as f:
return json.loads(f.read())


Expand Down Expand Up @@ -531,7 +531,7 @@ def test_single_thread_reply(email_code, mocker):
- Validate that if no email_code is provided, 'get_unique_code' is called to generate one
"""

def get_reply_body_side_effect(notes, incident_id, attachments): # noqa
def get_reply_body_side_effect(notes, incident_id, attachments, reputation_calc_async): # noqa
return 'Email body.', '<html><body>Email body.</body></html>'

from SendEmailReply import single_thread_reply
Expand Down
2 changes: 1 addition & 1 deletion Packs/EmailCommunication/pack_metadata.json
Expand Up @@ -2,7 +2,7 @@
"name": "Email Communication",
"description": "Do you have to send multiple emails to end users? This content pack helps you streamline the process and automate updates, notifications and more.\n",
"support": "xsoar",
"currentVersion": "2.0.11",
"currentVersion": "2.0.12",
"author": "Cortex XSOAR",
"url": "https://www.paloaltonetworks.com/cortex",
"videos": [
Expand Down

0 comments on commit f98110c

Please sign in to comment.