1
- import json
2
- import re
3
1
from datetime import datetime as dt
4
-
5
2
import demistomock as demisto # noqa: F401
6
3
from CommonServerPython import * # noqa: F401
7
4
from markdown import Extension , markdown
@@ -49,16 +46,17 @@ def append_email_signature(html_body):
49
46
Returns: (string) Original HTML body with HTML formatted email signature appended
50
47
"""
51
48
demisto .debug ("append_email_signature" )
52
- email_signature = demisto .executeCommand ("getList" , {"listName" : "XSOAR - Email Communication Signature" })
53
-
54
- if is_error (email_signature ):
55
- demisto .debug (
56
- "Error occurred while trying to load the `XSOAR - Email Communication Signature` list. No signature added to email"
57
- )
58
- else :
49
+ is_succeed , email_signature = execute_command (
50
+ "getList" , {"listName" : "XSOAR - Email Communication Signature" }, extract_contents = False , fail_on_error = False
51
+ )
52
+ if is_succeed :
59
53
# Find the position of the closing </html> tag and insert the signature there
60
54
if re .search ("(?i)</body>" , html_body ):
61
55
html_body = re .sub ("(?i)</body>" , f"\r \n { email_signature [0 ]['Contents' ]} \r \n </body>" , html_body )
56
+ else :
57
+ demisto .debug (
58
+ "Error occurred while trying to load the `XSOAR - Email Communication Signature` list. No signature added to email"
59
+ )
62
60
63
61
return html_body
64
62
@@ -99,7 +97,7 @@ def validate_email_sent(
99
97
Returns:
100
98
str: a message which indicates that the mail was sent successfully or an error message.
101
99
"""
102
- email_reply = execute_reply_mail (
100
+ execute_reply_mail (
103
101
incident_id ,
104
102
email_subject ,
105
103
subject_include_incident_id ,
@@ -116,9 +114,6 @@ def validate_email_sent(
116
114
mail_sender_instance ,
117
115
)
118
116
119
- if is_error (email_reply ):
120
- return_error (f"Error:\n { get_error (email_reply )} " )
121
-
122
117
msg = f"Mail sent successfully. To: { email_to } "
123
118
if email_cc :
124
119
msg += f" Cc: { email_cc } "
@@ -153,7 +148,9 @@ def execute_reply_mail(
153
148
# setting the email's subject for gmail adjustments
154
149
try :
155
150
demisto .debug (f"Setting incident { incident_id } email subject to { subject_with_id } " )
156
- demisto .executeCommand ("setIncident" , {"id" : incident_id , "customFields" : {"emailsubject" : f"{ subject_with_id } " }})
151
+ execute_command (
152
+ "setIncident" , {"id" : incident_id , "customFields" : {"emailsubject" : f"{ subject_with_id } " }}, extract_contents = False
153
+ )
157
154
except Exception :
158
155
return_error (
159
156
f"SetIncident Failed."
@@ -185,7 +182,10 @@ def execute_reply_mail(
185
182
if instances .get (mail_sender_instance , {}).get ("brand" ) == "Gmail Single User" :
186
183
mail_content ["references" ] = email_latest_message
187
184
demisto .debug (f"Sending email with the following subject: { subject_with_id } , and content: { mail_content } " )
188
- return demisto .executeCommand ("reply-mail" , mail_content )
185
+ is_succeed , email_reply = execute_command ("reply-mail" , mail_content , extract_contents = False , fail_on_error = False )
186
+ if is_succeed :
187
+ return email_reply
188
+ return_error (f"Error:\n { email_reply } " ) # noqa: RET503
189
189
190
190
191
191
def get_email_threads (incident_id ):
@@ -198,8 +198,11 @@ def get_email_threads(incident_id):
198
198
"""
199
199
# Get current email threads from context if any are present
200
200
demisto .debug (f"Getting email threads for incident { incident_id } " )
201
- incident_context = demisto .executeCommand ("getContext" , {"id" : incident_id })
201
+ is_succeed , incident_context = execute_command ("getContext" , {"id" : incident_id }, extract_contents = False , fail_on_error = False )
202
+ if not is_succeed :
203
+ demisto .debug (f"Failed to retrieve email threads for incident { incident_id } " )
202
204
incident_email_threads = dict_safe_get (incident_context [0 ], ["Contents" , "context" , "EmailThreads" ])
205
+
203
206
return incident_email_threads
204
207
205
208
@@ -330,7 +333,7 @@ def send_new_email(
330
333
# Get the custom email signature, if set, and append it to the message to be sent
331
334
email_html_body = append_email_signature (email_html_body )
332
335
333
- email_result = send_new_mail_request (
336
+ send_new_mail_request (
334
337
incident_id ,
335
338
email_subject ,
336
339
subject_include_incident_id ,
@@ -348,9 +351,6 @@ def send_new_email(
348
351
context_html_body ,
349
352
)
350
353
351
- if is_error (email_result ):
352
- return_error (f"Error:\n { get_error (email_result )} " )
353
-
354
354
msg = f"Mail sent successfully. To: { email_to } "
355
355
if email_cc :
356
356
msg += f" Cc: { email_cc } "
@@ -424,7 +424,9 @@ def send_new_mail_request(
424
424
demisto .debug (
425
425
f"Sending email for incident { incident_id } , with the following subject: { email_subject } , and content: { mail_content } "
426
426
)
427
- email_result = demisto .executeCommand ("send-mail" , mail_content )
427
+ is_succeed , email_result = execute_command ("send-mail" , mail_content , extract_contents = False , fail_on_error = False )
428
+ if not is_succeed :
429
+ return_error (f"Error:\n { email_result } " )
428
430
429
431
# Store message details in context entry
430
432
create_thread_context (
@@ -490,7 +492,15 @@ def get_entry_id_list(incident_id, attachments, new_email_attachments, files):
490
492
attachment_name = attachment .get ("name" , "" )
491
493
file_data = create_file_data_json (attachment , field_name )
492
494
demisto .debug (f"Removing attachment { attachment } from incident { incident_id } " )
493
- demisto .executeCommand ("core-api-post" , {"uri" : f"/incident/remove/{ incident_id } " , "body" : file_data })
495
+ is_succeed , _ = execute_command (
496
+ "core-api-post" ,
497
+ {"uri" : f"/incident/remove/{ incident_id } " , "body" : file_data },
498
+ extract_contents = False ,
499
+ fail_on_error = False ,
500
+ )
501
+ if not is_succeed :
502
+ demisto .debug ("Failed to remove attachment" )
503
+
494
504
if not isinstance (files , list ):
495
505
files = [files ]
496
506
for file in files :
@@ -552,7 +562,11 @@ def get_reply_body(notes, incident_id, attachments, reputation_calc_async=False)
552
562
for note in notes :
553
563
note_user = note ["Metadata" ]["user" ]
554
564
demisto .debug (f"Getting user data for user { note_user } in incident { incident_id } " )
555
- note_userdata = demisto .executeCommand ("getUserByUsername" , {"username" : note_user })
565
+ is_succeed , note_userdata = execute_command (
566
+ "getUserByUsername" , {"username" : note_user }, extract_contents = False , fail_on_error = False
567
+ )
568
+ if not is_succeed :
569
+ demisto .debug ("Failed to get user data" )
556
570
user_fullname = dict_safe_get (note_userdata [0 ], ["Contents" , "name" ]) or "DBot"
557
571
reply_body += f"{ user_fullname } : \n \n { note ['Contents' ]} \n \n "
558
572
@@ -565,21 +579,27 @@ def get_reply_body(notes, incident_id, attachments, reputation_calc_async=False)
565
579
566
580
entry_note = json .dumps ([{"Type" : 1 , "ContentsFormat" : "html" , "Contents" : reply_body , "tags" : ["email-thread" ]}])
567
581
demisto .debug (f"Adding note to incident { incident_id } " )
568
- entry_tags_res = demisto .executeCommand (
569
- "addEntries" , {"entries" : entry_note , "id" : incident_id , "reputationCalcAsync" : reputation_calc_async }
570
- )
571
- demisto .debug (f"Removing note:{ note .get ('ID' )} from incident { incident_id } " )
572
- entry_note_res = demisto .executeCommand (
582
+ is_succeed , entry_note_res = execute_command (
573
583
"core-api-post" ,
574
584
{
575
585
"uri" : "/entry/note" ,
576
586
"body" : json .dumps ({"id" : note .get ("ID" ), "version" : - 1 , "investigationId" : incident_id , "data" : "false" }),
577
587
},
588
+ extract_contents = False ,
589
+ fail_on_error = False ,
590
+ )
591
+ if not is_succeed :
592
+ return_error (entry_note_res )
593
+
594
+ is_succeed , entry_tags_res = execute_command (
595
+ "addEntries" ,
596
+ {"entries" : entry_note , "id" : incident_id , "reputationCalcAsync" : reputation_calc_async },
597
+ extract_contents = False ,
598
+ fail_on_error = False ,
578
599
)
579
- if is_error (entry_note_res ):
580
- return_error (get_error (entry_note_res ))
581
- if is_error (entry_tags_res ):
582
- return_error (get_error (entry_tags_res ))
600
+ if not is_succeed :
601
+ return_error (entry_tags_res )
602
+ demisto .debug (f"Removing note:{ note .get ('ID' )} from incident { incident_id } " )
583
603
584
604
else :
585
605
return_error ("Please add a note" )
@@ -623,7 +643,7 @@ def get_email_recipients(email_to, email_from, service_mail, mailbox):
623
643
return email_recipients
624
644
625
645
626
- def get_mailbox_from_incident_labels (labels ):
646
+ def get_mailbox_from_incident_labels (labels ): # pragma: no cover
627
647
"""
628
648
Gets the mailbox from which the incident was fetched from the incident labels.
629
649
Args:
@@ -644,8 +664,10 @@ def get_query_window():
644
664
to query back for related incidents. If yes, use this value, else use the default value of 60 days.
645
665
"""
646
666
demisto .debug ("Getting the number of days to query back for related incidents" )
647
- user_defined_time = demisto .executeCommand ("getList" , {"listName" : "XSOAR - Email Communication Days To Query" })
648
- if is_error (user_defined_time ):
667
+ is_succeed , user_defined_time = execute_command (
668
+ "getList" , {"listName" : "XSOAR - Email Communication Days To Query" }, extract_contents = False , fail_on_error = False
669
+ )
670
+ if not is_succeed :
649
671
demisto .debug (
650
672
"Error occurred while trying to load the `XSOAR - Email Communication Days To Query` list. Using"
651
673
" the default query time - 60 days"
@@ -681,14 +703,16 @@ def get_incident_by_query(query):
681
703
682
704
query += f' modified:>="{ query_from_date } "'
683
705
demisto .debug (f"Querying for incidents with the following query: { query } " )
684
- res = demisto .executeCommand ("getIncidents" , {"query" : query , "populateFields" : "id,status" })[0 ]
685
- if is_error (res ):
686
- return_results (ERROR_TEMPLATE .format ("getIncidents" , res ["Contents" ]))
687
- raise DemistoException (ERROR_TEMPLATE .format ("getIncidents" , res ["Contents" ]))
688
-
689
- incidents_details = res ["Contents" ]["data" ]
706
+ is_succeed , res = execute_command (
707
+ "getIncidents" , {"query" : query , "populateFields" : "id,status" }, extract_contents = False , fail_on_error = False
708
+ )
709
+ extracted_results = res [0 ]
710
+ if is_succeed :
711
+ incidents_details = extracted_results ["Contents" ]["data" ]
712
+ return incidents_details
690
713
691
- return incidents_details
714
+ return_results (ERROR_TEMPLATE .format ("getIncidents" , extracted_results ["Contents" ]))
715
+ raise DemistoException (ERROR_TEMPLATE .format ("getIncidents" , extracted_results ["Contents" ]))
692
716
693
717
694
718
def get_unique_code (incident_id , max_tries = 1000 ):
@@ -727,10 +751,14 @@ def reset_fields():
727
751
Args: None
728
752
"""
729
753
demisto .debug ("Resetting fields used to send the email message" )
730
- demisto . executeCommand (
754
+ is_succeed , _ = execute_command (
731
755
"setIncident" ,
732
756
{"emailnewrecipients" : "" , "emailnewsubject" : "" , "emailnewbody" : "" , "addcctoemail" : "" , "addbcctoemail" : "" },
757
+ extract_contents = False ,
758
+ fail_on_error = False ,
733
759
)
760
+ if not is_succeed :
761
+ demisto .debug ("Failed to reset fields used to send the email message" )
734
762
735
763
736
764
def resend_first_contact (
@@ -846,7 +874,9 @@ def convert_internal_url_to_base64(match):
846
874
str: The src attribute with the base64-encoded image.
847
875
"""
848
876
original_src = match .group (1 )
849
- result = demisto .executeCommand ("core-api-download" , {"uri" : original_src })
877
+ is_succeed , result = execute_command ("core-api-download" , {"uri" : original_src }, extract_contents = False , fail_on_error = False )
878
+ if not is_succeed :
879
+ demisto .debug (f"Failed to download image from { original_src } " )
850
880
with open (demisto .getFilePath (result [0 ]["FileID" ]).get ("path" ), "rb" ) as f :
851
881
base64_data_image = base64 .b64encode (f .read ()).decode ("utf-8" )
852
882
image_type = handle_image_type (base64_data_image )
@@ -919,7 +949,14 @@ def single_thread_reply(
919
949
# If a unique code is not set for this incident yet, generate and set it
920
950
email_code = get_unique_code (incident_id )
921
951
demisto .debug (f"Setting incident { incident_id } emailgeneratedcode to { email_code } " )
922
- demisto .executeCommand ("setIncident" , {"id" : incident_id , "customFields" : {"emailgeneratedcode" : email_code }})
952
+ is_succeed , _ = execute_command (
953
+ "setIncident" ,
954
+ {"id" : incident_id , "customFields" : {"emailgeneratedcode" : email_code }},
955
+ extract_contents = False ,
956
+ fail_on_error = False ,
957
+ )
958
+ if not is_succeed :
959
+ demisto .debug (f"Failed to set incident { incident_id } emailgeneratedcode" )
923
960
try :
924
961
final_email_cc = get_email_cc (email_cc , add_cc )
925
962
reply_body , context_html_body , reply_html_body = get_reply_body (notes , incident_id , attachments , reputation_calc_async )
@@ -1001,12 +1038,24 @@ def multi_thread_new(
1001
1038
# If there are already other values in 'emailgeneratedcodes', append the new code as a comma-separated list
1002
1039
if email_codes :
1003
1040
demisto .debug (f"Setting incident { incident_id } emailgeneratedcodes to { email_codes } ,{ thread_code } " )
1004
- demisto .executeCommand (
1005
- "setIncident" , {"id" : incident_id , "customFields" : {"emailgeneratedcodes" : f"{ email_codes } ,{ thread_code } " }}
1041
+ is_succeed , _ = execute_command (
1042
+ "setIncident" ,
1043
+ {"id" : incident_id , "customFields" : {"emailgeneratedcodes" : f"{ email_codes } ,{ thread_code } " }},
1044
+ extract_contents = False ,
1045
+ fail_on_error = False ,
1006
1046
)
1047
+ if not is_succeed :
1048
+ demisto .debug (f"failed to set incident { incident_id } emailgeneratedcode to { email_codes } ,{ thread_code } " )
1007
1049
else :
1008
1050
demisto .debug (f"Setting incident { incident_id } emailgeneratedcodes to { thread_code } " )
1009
- demisto .executeCommand ("setIncident" , {"id" : incident_id , "customFields" : {"emailgeneratedcodes" : f"{ thread_code } " }})
1051
+ is_succeed , _ = execute_command (
1052
+ "setIncident" ,
1053
+ {"id" : incident_id , "customFields" : {"emailgeneratedcodes" : f"{ thread_code } " }},
1054
+ extract_contents = False ,
1055
+ fail_on_error = False ,
1056
+ )
1057
+ if not is_succeed :
1058
+ demisto .debug (f"failed to set incident { incident_id } emailgeneratedcodes to { thread_code } " )
1010
1059
try :
1011
1060
entry_id_list = get_entry_id_list (incident_id , [], new_email_attachments , files )
1012
1061
@@ -1329,7 +1378,7 @@ def multi_thread_reply(
1329
1378
return True
1330
1379
1331
1380
1332
- def main ():
1381
+ def main (): # pragma: no cover
1333
1382
try :
1334
1383
demisto .debug ("Starting SendEmailReply script" )
1335
1384
args = demisto .args ()
@@ -1363,7 +1412,11 @@ def main():
1363
1412
body_type = args .get ("bodyType" ) or args .get ("body_type" ) or "html"
1364
1413
reputation_calc_async = argToBoolean (args .get ("reputation_calc_async" , False ))
1365
1414
demisto .debug ("Getting notes" )
1366
- notes = demisto .executeCommand ("getEntries" , {"filter" : {"categories" : ["notes" ]}})
1415
+ is_succeed , notes = execute_command (
1416
+ "getEntries" , {"filter" : {"categories" : ["notes" ]}}, extract_contents = False , fail_on_error = False
1417
+ )
1418
+ if not is_succeed :
1419
+ demisto .debug ("Failed to get notes" )
1367
1420
1368
1421
if new_email_attachments :
1369
1422
new_attachment_names = ", " .join ([attachment .get ("name" , "" ) for attachment in new_email_attachments ])
0 commit comments