当 运行 作为使用 pyInstaller 构建的 exe 时,无法使用 win32com 读取 Outlook 邮件项目 - Python 代码有效

Unable to read Outlook Mail Items using win32com when run as exe build using pyInstaller - Python code works

我有以下代码,当 python 代码为 运行 使用 eclipse 时,它​​能够从 outlook 读取邮件项目并下载附件。但是,当使用 pyinstaller 将相同的代码编译为 exe 时,它​​无法读取邮件项目并出现错误:ComObject Unknown

以下代码读取文件夹中的电子邮件项目并从具有特定主题的邮件中下载 excel 附件。然后从下载的xls文件中剥离密码并保存为xlsx文件以供进一步处理。

下面的代码 运行 在 eclipse 环境中 运行 或在命令提示符下使用 python.exe 调用时很好。但是当 运行 使用 pyinstaller 编译的 exe 时无法识别电子邮件项目。 我在交换服务器上使用 Windows 10 和 outlook 2016 我在这里想念的是什么? 下面是代码块:

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!

根据 DS_London 上面的评论,我现在更改了我的代码如下:

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

在此之后,我遇到了缺少 win32timezone 导入的错误,我通过在构建 exe 时在 pyInstaller 中添加 hidden_import 参数来纠正这个错误 - 为此 post :