I have following code which is able to read Mail Items from outlook and download the attachment when python code is run using eclipse. however, when the same code is compiled to an exe using pyinstaller, it fails to read the mail items with error: ComObject Unknown
The following code reads email item in a folder and downloads excel attachment from mail with specific subject. then strips off the password from the downloaded xls file and saves it as xlsx file for further processing.
The code below runs fine when run in eclipse environment or when called using python.exe from command prompt. but fails to recognize email item when run using exe compiled by pyinstaller. I am using Windows 10 and outlook 2016 over exchange server what is it that i am missing here? below is the code block:
import win32com.client as wc
from datetime import date
import os
import configparser
print('Reading Config file')
config=configparser.ConfigParser()
config.sections()
config.read('ReadOutlook.config')
configuration=config['DEFAULT']
mailboxname=configuration['mailboxname']
mailfolder_to_look_for=configuration['mailfolder_to_look_for']
downloadpath=configuration['downloadpath']
ULMISPath=configuration['ULMISPath']
CFMISPath=configuration['CFMISPath']
ulmis_password=configuration['ulmis_password']
cfmis_password=configuration['cfmis_password']
ulmisSubjectcontent=configuration['ulmisSubjectcontent']
cfmisSubjectcontent=configuration['cfmisSubjectcontent']
ulmisfilenamesearch=configuration['ulmisfilenamesearch']
cfmisfilenamesearch=configuration['cfmisfilenamesearch']
print (date.today())
outlook = wc.Dispatch("Outlook.Application")
namespace = outlook.GetNamespace("MAPI")
root = namespace.Folders.Item(mailboxname)
print(root.Name)
#print(root.Name)
MyMails=root.Folders.Item(mailfolder_to_look_for)
def Remove_password_xlsx(filename, pw_str,newfilename):
print('opening Excel Application')
xcl = wc.Dispatch("Excel.Application")
print('opening file:' ,filename)
wb = xcl.Workbooks.Open(filename, False, False, None, pw_str)
xcl.DisplayAlerts = False
print('Removing password for',filename)
wb.SaveAs(filename, None,'','')
print('Now saving as xlsx',newfilename)
wb=xcl.Workbooks.Open(filename,False,False,None)
wb.SaveAs(newfilename, FileFormat=wc.constants.xlOpenXMLWorkbook,CreateBackup=False)
xcl.Quit()
for mailitem in range(len(MyMails.Items),0,-1):
print(MyMails.Items[mailitem].Subject)
try:
if(MyMails.Items[mailitem].ReceivedTime.date()==date.today()
and ((MyMails.Items[mailitem].Subject.find(ulmisSubjectcontent)!=-1
and MyMails.Items[mailitem].Subject.find('With Collection')!=-1)
or MyMails.Items[mailitem].Subject.find(cfmisSubjectcontent)!=-1)):
print(MyMails.Items[mailitem].Subject)
# if i.Attachments:
for f in MyMails.Items[mailitem].Attachments:
if f.FileName.find(ulmisfilenamesearch)!=-1:
f.SaveAsFile(downloadpath + '\\ULMIS.xls')
Remove_password_xlsx(downloadpath+'\\ULMIS.xls'
, ulmis_password,ULMISPath)
print('removing ULMIS.xls')
os.remove(downloadpath+'\\ULMIS.xls')
break
else:
if f.FileName.find(cfmisfilenamesearch)!=-1:
f.SaveAsFile(downloadpath + '\\CFMIS.xls')
Remove_password_xlsx(downloadpath +'\\CFMIS.xls'
, cfmis_password,CFMISPath)
print('removing CFMIS.xls')
os.remove(downloadpath+'\\CFMIS.xls')
break
except:
print('an error occurred')
pass
Printing the Mail Subject gives error as:
Traceback (most recent call last): File "ReadOutlook.py", line 45, in module File >"win32com\client\dynamic.py", line 279, in getitem File >"win32com\client\util.py", line 37, in getitem File >"win32com\client\util.py", line 56, in __GetIndex IndexError: list index >out of range
IndexError: list index out of range Failed to execute script 'ReadOutlook' due to unhandled exception!
from the comments reced above by DS_London, i have now changed my code as follows:
import win32com.client as wc
from datetime import date
import os
import configparser
# while creating exe on pyinstaller use "win32timezone" in hidden import section
print('Reading Config file')
config=configparser.ConfigParser()
config.sections()
config.read('ReadOutlook.config')
configuration=config['DEFAULT']
mailboxname=configuration['mailboxname']
mailfolder_to_look_for=configuration['mailfolder_to_look_for']
downloadpath=configuration['downloadpath']
ULMISPath=configuration['ULMISPath']
CFMISPath=configuration['CFMISPath']
ulmis_password=configuration['ulmis_password']
cfmis_password=configuration['cfmis_password']
ulmisSubjectcontent=configuration['ulmisSubjectcontent']
cfmisSubjectcontent=configuration['cfmisSubjectcontent']
ulmisfilenamesearch=configuration['ulmisfilenamesearch']
cfmisfilenamesearch=configuration['cfmisfilenamesearch']
print (date.today())
# outlook = wc.Dispatch("Outlook.Application")
outlook = wc.gencache.EnsureDispatch("Outlook.Application")
namespace = outlook.GetNamespace("MAPI")
root = namespace.Folders.Item(mailboxname)
print(root.Name)
#print(root.Name)
MyMails=root.Folders.Item(mailfolder_to_look_for)
def Remove_password_xlsx(filename, pw_str,newfilename):
print('opening Excel Application')
xcl=wc.gencache.EnsureDispatch("Excel.Application")
# xcl = wc.Dispatch("Excel.Application")
print('opening file:' ,filename)
wb = xcl.Workbooks.Open(filename, False, False, None, pw_str)
xcl.DisplayAlerts = False
print('Removing password for',filename)
wb.SaveAs(filename, None,'','')
print('Now saving as xlsx',newfilename)
wb=xcl.Workbooks.Open(filename,False,False,None)
wb.SaveAs(newfilename, FileFormat=wc.constants.xlOpenXMLWorkbook,CreateBackup=False)
xcl.Quit()
for mailitem in range(len(MyMails.Items),0,-1):
# print(MyMails.Items[mailitem].ReceivedTime.date())
try:
if(MyMails.Items[mailitem].ReceivedTime.date()==date.today()
and ((MyMails.Items[mailitem].Subject.find(ulmisSubjectcontent)!=-1
and MyMails.Items[mailitem].Subject.find('With Collection')!=-1)
or MyMails.Items[mailitem].Subject.find(cfmisSubjectcontent)!=-1)):
print(MyMails.Items[mailitem].Subject)
# if i.Attachments:
for f in MyMails.Items[mailitem].Attachments:
if f.FileName.find(ulmisfilenamesearch)!=-1:
f.SaveAsFile(downloadpath + '\\ULMIS.xls')
Remove_password_xlsx(downloadpath+'\\ULMIS.xls'
, ulmis_password,ULMISPath)
print('removing ULMIS.xls')
os.remove(downloadpath+'\\ULMIS.xls')
break
else:
if f.FileName.find(cfmisfilenamesearch)!=-1:
f.SaveAsFile(downloadpath + '\\CFMIS.xls')
Remove_password_xlsx(downloadpath +'\\CFMIS.xls'
, cfmis_password,CFMISPath)
print('removing CFMIS.xls')
os.remove(downloadpath+'\\CFMIS.xls')
break
except:
# print('an error occurred')
pass
after this, I was getting error of missing import for win32timezone, which I corrected by adding hidden_import parameter in pyInstaller while building the exe - followed this post for it: ImportError: No module named win32timezone when i make a singleone exe from a python script with pyInstaller