def call_api(self): outlook = Dispatch("Outlook.Application") mapi = outlook.GetNamespace("MAPI") Accounts = mapi.Folders #解析邮件内容 if self.mail_title != "": try: for Account in Accounts: if Account.Name == self.account_name: Folders = Account.Folders #读取该账户下的文件夹列表 for Folder in Folders: #第一层目录 if len(self.folder_name[0]) == 0: #输入文件夹为空 if Folder.Name == "收件箱": mail_info = self.save_attachments( Folder) #调用邮件解析和附件下载函数 elif len(self.folder_name) == 1: if Folder.Name == self.folder_name[0]: mail_info = self.save_attachments( Folder) #调用邮件解析和附件下载函数 else: if Folder.Name == self.folder_name[0]: for i in range(1, len(self.folder_name)): for Folder2 in Folder.Folders: if Folder2.Name == self.folder_name[ i]: Folder = Folder2 mail_info = self.save_attachments( Folder) #调用邮件解析和附件下载函数 return (mail_info) except: traceback.print_exc() sys.exit() else: return ("邮件title不能为空!~")
from win32com.client.gencache import EnsureDispatch as Dispatch import os import sys outlook = Dispatch("Outlook.Application") mapi = outlook.GetNamespace("MAPI") class Oli(): def __init__(self, outlook_object): self._obj = outlook_object def items(self): array_size = self._obj.Count for item_index in range(1,array_size+1): yield (item_index, self._obj[item_index]) def prop(self): return sorted( self._obj._prop_map_get_.keys() ) # for inx, folder in Oli(mapi.Folders).items(): # # iterate all Outlook folders (top level) # #print "-"*70 # print(folder.Name) # for inx,subfolder in Oli(folder.Folders).items(): # print("({}) {} => {}".format(inx, subfolder.Name, subfolder)) def mkdir_p(path): try: os.makedirs(path) except:
def scan_inbox(): ''' docstring ''' global CONFIG foldertree = CONFIG["foldertree"] outlook = Dispatch("Outlook.Application") mapi = outlook.GetNamespace("MAPI") cwd = os.getcwd() processed = [] matchfound = False class Oli(): def __init__(self, outlook_object): self._obj = outlook_object def items(self): array_size = self._obj.Count for item_index in xrange(1, array_size + 1): yield (item_index, self._obj[item_index]) def prop(self): return sorted(self._obj._prop_map_get_.keys()) rules = None def loadrules(): ''' docstring ''' rules = load_yara("rules") rulecount = 0 for r in rules: rulecount += 1 print("Loaded " + str(rulecount) + " YARA rules.") folderindex = 0 loadrules() loadioc() #this needs fixing :/ outlookfolder = mapi.Folders for inx, folder in Oli(outlookfolder).items(): if folder.Name == foldertree[0]: outlookfolder = folder print(">" + folder.Name + ":") break for currentfolder in foldertree[1:]: for inx, folder in Oli(outlookfolder.Folders).items(): if folder.Name == currentfolder: print("\t>> " + folder.Name) outlookfolder = folder folderindex = inx # break try: os.mkdir(cwd + "\\workdir") except Exception: pass # https://docs.microsoft.com/en-us/dotnet/api/microsoft.office.interop.outlook._mailitem?view = outlook-pia for msg in outlookfolder.Items: try: for attachment in msg.Attachments: if attachment.FileName.startswith( "Scan_results") and hashlib.sha256( msg.Body).hexdigest() not in processed: print("Removed Scan_results") msg.Attachments.Remove(attachment.Index) msg.Save() except Exception as e: print(e) #raw_input("Press any key to start scanning, Outlook will ask you for grant permission to access the Inbox...") while True: print( "[" + datetime.datetime.fromtimestamp( time.time()).strftime('%Y-%m-%d %H:%M:%S') + "] Inbox Scan started for " + "/".join(foldertree).strip("/")) print("Scanning folder: /".join(foldertree).strip("/")) for msg in outlookfolder.Items: try: msgsha256 = hashlib.sha256(msg.Body).hexdigest() if msgsha256 in processed: continue else: processed.append(msgsha256) yarascan = '' external_scan_result = '' msgmeta = '' yaramatches = None senderdomain = sendertxt = senderspf = '' try: msgmeta += "SenderEmailAddress:\t" + \ unidecode.unidecode(msg.SenderEmailAddress)+"\n" msgmeta += "To:\t" + unidecode.unidecode(msg.To) + "\n" msgmeta += "Subject:\t" + \ unidecode.unidecode(msg.Subject)+"\n" msgmeta += "CC:\t" + unidecode.unidecode(msg.CC) + "\n" msgmeta += "Categories:\t" + \ unidecode.unidecode(msg.Categories)+"\n" except AttributeError: pass print("-" * 80) print(msgmeta) if msg.Attachments.Count > 0: #print "." for attachment in msg.Attachments: # print attachment #print attachment.GetTemporaryFilePath() #print attachment.FileName if attachment.FileName: attachment.SaveAsFile(cwd + "\\workdir\\" + attachment.FileName) try: yaramatches = rules.match(cwd + "\\workdir\\" + attachment.FileName) except Exception as e: pass if yaramatches: matchfound = True yarascan += print_yara( yaramatches, context="Attachment match:" + str(attachment.FileName)[:40], msg=msgmeta) with open( cwd + "\\workdir\\" + attachment.FileName, "rb") as f: scan_result, matchfound = external_scans( f.read(), binary=True) external_scan_result += scan_result if attachment.FileName.lower().endswith(".msg"): msgdata = ExtractMsg.process_msg( cwd + "\\workdir\\" + attachment.FileName) m = "MSG found:"+cwd+"\\workdir\\"+attachment.FileName+"\n\tSubject:" + \ str(msgdata["subject"])+"\n\tTo:"+str(msgdata["to"])+"\n\tFrom:"+str( msgdata["from"])+"\n\tDate:"+str(msgdata["date"]) msgmeta += m + "\n" print("MSG attachment:") print(m) # print(msgdata["body"]) try: yaramatches = rules.match( data=msgdata["body"]) except Exception as e: pass # traceback.print_exc() if yaramatches: yarascan += print_yara( yaramatches, context="MSG attachment body match", msg=msgmeta) matchfound = True scan_result, matchfound = external_scans( msgdata["body"], vt=False) external_scan_result += scan_result if not None is msgdata: for msgattachment in msgdata[ 'attachments']: # print("Attachment:"+msgattachment["filename"]) with open( cwd + "\\workdir\\__" + attachment.FileName + "__" + msgattachment["filename"], "wb+") as f: f.write( base64.b64decode( msgattachment['data'])) try: yaramatches = rules.match( cwd + "\\workdir\\__" + attachment.FileName + "__" + msgattachment["filename"]) except Exception as e: pass if yaramatches: matchfound = True yarascan += print_yara( yaramatches, msg=msgmeta, context= "Attachment extracted from MSG attachment matched: " + str(attachment.FileName + "__" + msgattachment["filename"]) [:64]) with open( cwd + "\\workdir\\__" + attachment.FileName + "__" + msgattachment["filename"], "rb") as f: scan_result, matchfound = external_scans( f.read(), binary=True) external_scan_result += scan_result else: print("MSGdata is none") hbody = unidecode.unidecode(msg.HTMLBody) body = unidecode.unidecode(msg.Body) for line in hbody.splitlines(): if "x-originating-ip" in line.lower(): print line try: yaramatches = rules.match(data=hbody) yaramatches = rules.match(data=body) except Exception as e: pass if yaramatches: print '-' * 80 matchfound = True yarascan += print_yara(yaramatches, context="HTMLBody matched", msg=msgmeta, showstrings=True) print '-' * 80 # if yaramatches: # print '-'*80 #yarascan += print_yara(yaramatches,context = "Plain body matched",msg = msgmeta,showstrings = True) # print '-'*80 scan_result, matchfound = external_scans(hbody, vt=False) external_scan_result += scan_result #print (external_scan_result) header = ''' <html> <body> ''' footer = ''' </body> </html> ''' if senderspf: header += "<h1>SPF records</h1></b>" header += "<h3>Domain</h3>:" + senderdomain header += "</br>SPF records:" + senderspf if yarascan.strip(): yarascan = "<h1>Yara matches</h1></br><pre>" + yarascan + "</pre><hr>" scanres = header + yarascan + "</br>\n" + external_scan_result resfile = '' if matchfound: resfile = "Scan_results_matchfound.htm" else: resfile = "Scan_results_nomatches.htm" if scanres: with open(cwd + "\\" + resfile, "w+") as f: f.write(scanres) msg.Attachments.Add(cwd + "\\" + resfile, 1, 1, resfile) msg.Save() except Exception as e: print e traceback.print_exc() print( "[" + datetime.datetime.fromtimestamp( time.time()).strftime('%Y-%m-%d %H:%M:%S') + "] Done scanning,sleeping for " + str(CONFIG["scan_interval"]) + " seconds...") time.sleep(int(CONFIG["scan_interval"])) loadconfig() loadioc()
def read_email(date, my_account, sent_account): # 读取邮箱 outlook = Dispatch("Outlook.Application") mapi = outlook.GetNamespace("MAPI") Accounts = mapi.Folders # 读取的员工账号 names = [] # 短信内容 contents = [] # 读取邮件存入pandas c = ['Root_Directory_Name_1', 'Level_1_FolderName_1', 'Level_2_FolderName_1', 'ReceivedTime_1', 'SenderName_1', 'to_to_1', 'cc_cc_1', 'Subject_1', 'MessageID_1', 'ConversationTopic_1', 'ConversationID_1', 'ConversationIndex_1', 'EmailBody_1'] df = pd.DataFrame(columns=c) for Account_Name in Accounts: # 只查找需要的邮箱账号信息 if Account_Name.Name == my_account: print(' >> 正在查询的帐户名称:', Account_Name.Name, '\n') Level_1_Names = Account_Name.Folders for Level_1_Name in Level_1_Names: # 只需要收件箱的邮件 if Level_1_Name.Name == '收件箱': print(' - 正在查询一级目录:', Level_1_Name.Name) Mail_1_Messages = Level_1_Name.Items # 将邮件按日期排序,可减少遍历内容 Mail_1_Messages.Sort("[ReceivedTime]", True) for xx in Mail_1_Messages: # xx = 'mail' # 开始查看单个邮件的信息 print(xx.Subject) Root_Directory_Name_1 = Account_Name.Name Level_1_FolderName_1 = Level_1_Name.Name Level_2_FolderName_1 = '' ReceivedTime_1 = str(xx.ReceivedTime)[:10] # 接收日期 if ReceivedTime_1 != date: # 只要特定日期的邮件 continue SenderName_1 = xx.SenderName # 发件人 if SenderName_1 != sent_account: # 只要特定发件人的邮件 continue Subject_1 = xx.Subject # 主题 EmailBody_1 = xx.Body # 邮件内容 to_to_1 = xx.To # 收件人 cc_cc_1 = xx.CC # 抄送人 MessageID_1 = xx.EntryID # 邮件MessageID ConversationTopic_1 = xx.ConversationTopic # 会话主题 ConversationID_1 = xx.ConversationID # 会话ID ConversationIndex_1 = xx.ConversationIndex # 会话记录相对位置 data = [Root_Directory_Name_1, Level_1_FolderName_1, Level_2_FolderName_1, ReceivedTime_1, SenderName_1, to_to_1, cc_cc_1, Subject_1, MessageID_1, ConversationTopic_1, ConversationID_1, ConversationIndex_1, EmailBody_1] dataf = dict(zip(c, data)) df = df.append(dataf, ignore_index=True) return df