[英]How do I use ItemAdd Event to monitor a shared inbox in Python?
我想用 Python 制作一个 Outlook 监视器,并且一直在研究这个主题。
我正在使用 Python 3.6 尝试监视我的 Outlook 上共享收件箱中收到的电子邮件。 我有以下将运行的代码:
import win32com.client
import ctypes # for the VM_QUIT to stop PumpMessage()
import pythoncom
import re
import time
import psutil
import os
from os.path import join as join_path
from olefile import OleFileIO
class HandlerClass():
def __init__(self):
# First action to do when using the class in the DispatchWithEvents
messages = self # Getting All Messages in the Inbox Folder
#headers_schema = "http://schemas.microsoft.com/mapi/proptag/0x007D001E"
# Check for unread emails when starting the event
for message in messages:
if message.UnRead:
self.check_email(message)
else:
print("No Unread Emails")
break
def check_email(self, message):
attachments = message.Attachments # Get attachments
if attachments.Count > 0: # If one or more attachments
attachment = attachments.Item(1) # Get the first attachment
attachment_fname = join_path(os.getcwd(), attachment.FileName)
attachment.SaveAsFile(attachment_fname) # Saves to the attachment to current folded
try:
IHDict = extract_headers(attachment_fname)
except MessageHeadersError as err:
print("Could not extract headers. Is this an email?", err)
return
finally:
os.remove(attachment_fname) # Delete saved attachment
def check_header(h: str) -> bool:
hval = IHDict.get(h, None)
if hval is not None:
print("%s: %s" % (h, hval))
else:
print("'%s' not available." % h)
return hval
# Pull out headers of interest
rp = check_header('Return-Path')
sp = check_header('X-Env-Sender')
check_header('X-Originating-Ip')
check_header('Authentication-Results')
print() # Formatting
# Compare Return Path to X-Env-Sender to check for Phish.
if rp is not None and sp is not None and rp.strip("<>") == sp:
print("Email is safe.")
print() # Formatitng
else:
print("Email is suspicious.")
print() # Formatting
else:
print("Email Contains No Attachment Message")
def OnQuit(self):
# To stop PumpMessages() when Outlook Quit
# Note: Not sure it works when disconnecting!!
ctypes.windll.user32.PostQuitMessage(0)
def OnItemAdd(self, mail):
print("Working!")
#self.check_email(mail)
#Check if the item is of the MailItem type
if mail.Class==43:
print(mail.Subject, " - ", mail.Parent.FolderPath)
# Function to check if outlook is open
def check_outlook_open():
for pid in psutil.pids():
p = psutil.Process(pid)
if p.name().lower().strip() == 'outlook.exe':
return True
return False
class MessageHeadersError(Exception):
pass
class MessageHeadersMissing(MessageHeadersError):
pass
class MessageHeadersUnknownEncoding(MessageHeadersError):
pass
def extract_headers(cdfv2_filename: str) -> dict:
"""Extract headers from a CDFv2 email"""
try:
ole = OleFileIO(cdfv2_filename)
except Exception as exc:
raise MessageHeadersError("could not open OLE file") from exc
try:
for ent in ole.listdir(streams=True, storages=False):
if ent[-1].startswith("__substg1.0_007D"):
# message headers
break
else:
# no message header entry?
raise MessageHeadersMissing("missing")
olestream = ole.openstream(ent)
header_data = olestream.read()
olestream.close()
if ent[-1].endswith("001E"):
# ASCII encoding
header_string = header_data.decode("ascii")
elif ent[-1].endswith("001F"):
# UTF-16
header_string = header_data.decode("UTF-16")
else:
# dunno what this encoding is
raise MessageHeadersUnknownEncoding("Unknown OLE encoding " + ent[-4:])
return parse_headers(header_string)
finally:
ole.close()
def parse_headers(hstr: str) -> dict:
headers = {}
lastkey = None
for line in hstr.split("\n"):
#if line.strip() == " ": #skip empty lines - there shouldn't be any. continue
if line.startswith("\t") or line.startswith(" "): #headers can be continued with either whitespace or tabs.
key = lastkey
value = line.strip()
else:
key, _, value = line.partition(":")# e - mail headers are case insensitive, #so we normalise to title - case (the most common form).
key = key.strip().title()
value = value.strip()
lastkey = headers[key] = (headers.get(key, "") + " " + value).strip()
return headers
# Loop
Syscoms = win32com.client.DispatchEx("Outlook.Application").GetNamespace("MAPI").Folders["UK"].Folders["Inbox"].Items
while True:
# If outlook opened then it will start the DispatchWithEvents
if check_outlook_open():
win32com.client.DispatchWithEvents(Syscoms, HandlerClass)
pythoncom.PumpMessages()
# To not check all the time (should increase 10 depending on your needs)
time.sleep(1)
如何在新邮件到达收件箱时触发 OnItemAdd 事件?
尝试使用Dispatch
而不是DispatchEx
和GetSharedDefaultFolder
而不是Inbox
。 以下代码将收到的电子邮件正确注册到共享收件箱:
import ctypes # for the VM_QUIT to stop PumpMessage()
import pythoncom
import win32com.client
import sys
# outlook config
SHARED_MAILBOX = "Your Mailbox Name"
# get the outlook instance and inbox folder
session = win32com.client.Dispatch("Outlook.Application").Session
user = session.CreateRecipient(SHARED_MAILBOX)
shared_inbox = session.GetSharedDefaultFolder(user, 6).Items # 6 is Inbox
class HandlerClass(object):
def OnItemAdd(self, item):
print("New item added in shared mailbox")
if item.Class == 43:
print("The item is an email!")
outlook = win32com.client.DispatchWithEvents(shared_inbox, HandlerClass)
def main():
print("Starting up Outlook watcher")
pythoncom.PumpMessages()
if __name__ == "__main__":
try:
status = main()
sys.exit(status)
except KeyboardInterrupt:
print("Terminating program..")
ctypes.windll.user32.PostQuitMessage(0)
sys.exit()
我上面发布的代码中有一个错误,虽然它不是问题的一部分,但我不想就这样离开它。 程序不会像这样捕获KeyboardInterrupt
,因为PumpMessages
是一个阻塞主线程的无限循环。 使用threading
模块将它放入自己的threading
可以解决这个问题:
class OtlkThread(threading.Thread):
def run(self):
logger.info("Starting up Outlook watcher\n"
"To terminate the program, press 'Ctrl + C'")
pythoncom.PumpMessages()
def main():
win32com.client.DispatchWithEvents(shared_inbox, HandlerClass)
OtlkThread(daemon=True).start()
if __name__ == "__main__":
status = main()
while True:
try:
time.sleep(1)
except KeyboardInterrupt:
logger.info("Terminating program..")
ctypes.windll.user32.PostQuitMessage(0)
sys.exit(status)
我一直在用Python监视Outlook。从我的角度来看,我认为您不需要在while循环中创建回调对象
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.