Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to connect to a running instance of Outlook from Python

Tags:

python

outlook

I'm trying to write a Python script to extract data from messages in Outlook 2013 folders. The method described everywhere to access Outlook is to first run:

import win32com.client
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")

This works fine if Outlook is NOT running. But if it is, this throws an error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Program Files\Python27\lib\site-packages\win32com\client\__init__.py", line 95, in Dispatch
    dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
  File "C:\Program Files\Python27\lib\site-packages\win32com\client\dynamic.py", line 114, in _GetGoodDispatchAndUserName
    return (_GetGoodDispatch(IDispatch, clsctx), userName)
  File "C:\Program Files\Python27\lib\site-packages\win32com\client\dynamic.py", line 91, in _GetGoodDispatch
    IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx, pythoncom.IID_IDispatch)
pywintypes.com_error: (-2146959355, 'Server execution failed', None, None)

Based on a similar issue reported for another application which does not support running multiple instances at the same time either, I tried adapting their solution:

try:
    app = win32com.client.Dispatch('Outlook.Application')
except:
    app = win32com.client.GetActiveObject('Outlook.Application')

But this does not work either. GetActiveObject now fails with error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Program Files\Python27\lib\site-packages\win32com\client\__init__.py", line 79, in GetActiveObject
    dispatch = pythoncom.GetActiveObject(resultCLSID)
pywintypes.com_error: (-2147221021, 'Operation unavailable', None, None)

So what would be the correct way to connect to a running instance of Outlook?

like image 629
Jean-François Larvoire Avatar asked Jan 12 '17 10:01

Jean-François Larvoire


2 Answers

Answering my own question:

The root cause was that I was running Python in a command window running as Administrator.
If I start cmd.exe as a normal user, things work without error.
I wish GetActiveObject() would return a more meaningful error message in this case!

Side note: Reversing the two alternatives works faster:

try:
    outlook = win32com.client.GetActiveObject('Outlook.Application')
except:
    outlook = win32com.client.Dispatch('Outlook.Application')
like image 200
Jean-François Larvoire Avatar answered Oct 17 '22 08:10

Jean-François Larvoire


Outlook is a singleton, so no matter what you do, it will always connect to the running instance. The only problem (as you have discovered) is that if is already running under a different security context, COM system will refuse to marshal COM objects between the two processes.

like image 1
Dmitry Streblechenko Avatar answered Oct 17 '22 08:10

Dmitry Streblechenko