<p>再次感谢您的回答,Michael,它让我找到了<a href="https://stackoverflow.com/a/33212475/5122246">this</a>答案,其中还包含一个<a href="https://vlasenkov.blogspot.com/2017/03/python-win32com-multithreading.html" rel="nofollow noreferrer">excellent example</a>的链接。这个答案和示例的主要收获是,不要将Outlook作为封送处理程序传递,而是将其作为客户端传递给处理程序。另外,使用<code>WithEvents</code>代替<code>DispatchWithEvents</code>,并在导入<code>pythoncom</code>之前设置{<cd3>}<em>。在</p>
<p>最终结果如下:</p>
<pre class="lang-py prettyprint-override"><code>"""Handler class that watches for incoming mails"""
import ctypes # for the WM_QUIT to stop PumpMessage()
import logging
import sys
import time
from threading import Thread
sys.coinit_flags = 0 # pythoncom.COINIT_MULTITHREADED == 0
from pythoncom import (CoInitializeEx, CoUninitialize,
COINIT_MULTITHREADED, PumpWaitingMessages)
from win32com.client import Dispatch, WithEvents
# outlook config
CENTRAL_MAILBOX = "My Mailbox"
# COM event handler
class IncomingMailHandler:
def OnItemAdd(self, item):
logger.info("New item added in central mailbox")
if item.Class == 43:
logger.info(f"The item is an email with subject {item.Subject}")
# main thread
def main():
# get the outlook instance and inbox folders
outlook = Dispatch("Outlook.Application")
user = outlook.Session.CreateRecipient(CENTRAL_MAILBOX)
central_inbox = outlook.Session.GetSharedDefaultFolder(user, 6).Items
logger.info(f"{central_inbox.Count} messages in central inbox")
# launch the second thread
thread = Thread(target=watcher, args=(central_inbox,), daemon=True)
thread.start()
# other thread worker function
def watcher(client):
logger = logging.getLogger("watcher")
CoInitializeEx(COINIT_MULTITHREADED)
WithEvents(client, IncomingMailHandler)
# event loop 2
_loop = 0
while True:
PumpWaitingMessages()
_loop += 1
if _loop % 20 == 0:
logger.info("Watcher is running..")
time.sleep(0.5)
CoUninitialize()
if __name__ == "__main__":
logger.info("Starting up Outlook watcher\n"
"To terminate the program, press 'Ctrl + C'")
status = main()
while True:
try:
time.sleep(0.5)
except KeyboardInterrupt:
logger.info("Terminating program..")
ctypes.windll.user32.PostQuitMessage(0)
sys.exit(status)
</code></pre>