Я хочу сделать что-то похожее на то, что спрашивается здесь , но с использованием threading
, как здесь .Используя также ответ из здесь , я получил свой код работающим, только то, что событие ItemAdd не распознается (на самом деле, я думаю, что это так, но в другом потоке, поэтому нет вывода).
"""Handler class that watches for incoming mails"""
import ctypes # for the WM_QUIT to stop PumpMessage()
import logging
import win32com.client
import sys
import threading
import time
import pythoncom
# outlook config
CENTRAL_MAILBOX = "My Mailbox"
# get the outlook instance and inbox folders
outlook = win32com.client.Dispatch("Outlook.Application")
marshalled_otlk = pythoncom.CoMarshalInterThreadInterfaceInStream(
pythoncom.IID_IDispatch, outlook)
class HandlerClass(object):
def OnItemAdd(self, item):
logger.info("New item added in central mailbox")
if item.Class == 43:
logger.info("The item is an email!")
class OtlkThread(threading.Thread):
def __init__(self, marshalled_otlk, *args, **kwargs):
super().__init__(*args, **kwargs)
self.marshalled_otlk = marshalled_otlk
self.logger = logging.getLogger("OLThread")
def run(self):
self.logger.info("Starting up Outlook watcher\n"
"To terminate the program, press 'Ctrl + C'")
pythoncom.CoInitialize()
outlook = win32com.client.Dispatch(
pythoncom.CoGetInterfaceAndReleaseStream(
self.marshalled_otlk,
pythoncom.IID_IDispatch
)
)
user = outlook.Session.CreateRecipient(CENTRAL_MAILBOX)
central_inbox = outlook.Session.GetSharedDefaultFolder(user, 6).Items
self.logger.info(f"{central_inbox.Count} messages in central inbox")
win32com.client.DispatchWithEvents(central_inbox, HandlerClass)
pythoncom.PumpMessages()
pythoncom.CoUninitialize() # this is prbly unnecessary as it will never be reached
def main():
# pythoncom.CoInitialize()
OtlkThread(marshalled_otlk, daemon=True).start()
if __name__ == "__main__":
status = main()
while True:
try:
# pythoncom.PumpWaitingMessages()
time.sleep(1)
except KeyboardInterrupt:
logger.info("Terminating program..")
ctypes.windll.user32.PostQuitMessage(0)
sys.exit(status)
Я пробовал разные вещи, например, ставил sys.coinit_flags=0
вверху, как предлагалось здесь ), вызывал PumpWaitingMessages()
в главном потоке и получал приложение Outlookв самой боковой нити, вместо прохождения маршаллированного объекта.Ничего из этого не сработало.
Когда я просто помещаю PumpMessages в основной поток (тот же HandlerClass
, но без отдельного потока), он работает, и электронные письма распознаются по прибытии, но, очевидно, поток блокируется, и даже неИсключение KeyboardInterrupt может быть перехвачено.
Итак, как мне заставить наблюдателя outlook работать в отдельном потоке для отправки сообщений в основной поток для вывода там?