title: Pythoncom PumpMessages from different thread
body: <p>I want to do something similar to what is asked <a href="https://stackoverflow.com/questions/49695160/how-to-continuously-monitor-a-new-mail-in-outlook-and-unread-mails-of-a-specific">here</a>, but using <code>threading</code> like <a href="https://stackoverflow.com/questions/53822692/outlook-via-com-via-multi-thread-in-python">here</a>. Using also the answer from <a href="https://stackoverflow.com/questions/26764978/using-win32com-with-multithreading">here</a>, I got my code working, only that an ItemAdd event is not recognised (actually, I think it is, but in the other thread, which is why there is no output).</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 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)
  </code></pre>
  
  <p>I have tried various things, such as putting <code>sys.coinit_flags=0</code> at the top, as suggested <a href="http://python.6.x6.nabble.com/Is-it-possible-to-pump-messages-in-thread-td1949678.html" rel="nofollow noreferrer">here</a>), calling <code>PumpWaitingMessages()</code> in the main thread, and getting the Outlook application in the side thread itself, instead of passing the marshalled object. None of these have worked.</p>
  
  <p>When I just put PumpMessages in the main thread (same <code>HandlerClass</code> but no separate thread) it works and emails are recognised upon arrival, but obviously the thread is blocked and not even the KeyboardInterrupt exception can be caught.</p>
  
  <p>So, how do I get the outlook watcher running in the separate thread to send the messages to the main thread for output there?</p>