【问题标题】:Unable to read Outlook Mail Items using win32com when run as exe build using pyInstaller - Python code works使用 pyInstaller 作为 exe 构建运行时,无法使用 win32com 读取 Outlook 邮件项目 - Python 代码有效
【发布时间】:2021-12-01 16:15:19
【问题描述】:

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

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

以下代码在 eclipse 环境中运行或在命令提示符下使用 python.exe 调用时运行良好。但使用 pyinstaller 编译的 exe 运行时无法识别电子邮件项目。 我在 Exchange 服务器上使用 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

打印邮件主题会出现以下错误:

Traceback(最近一次调用最后一次): 文件“ReadOutlook.py”,第 45 行,模块文件 >“win32com\client\dynamic.py”,第 279 行,getitem 文件 >“win32com\client\util.py”,第 37 行,在 getitem 文件 >"win32com\client\util.py",第 56 行,在 __GetIndex IndexError: list index >out of range

IndexError: 列表索引超出范围 由于未处理的异常,无法执行脚本“ReadOutlook”!

【问题讨论】:

  • 出现错误时mailitem 的值是多少?我最近在使用[] 索引时遇到了类似的奇怪行为:它似乎从从零开始切换到从1 开始。尝试重新安装 pywin32 包,然后使用 outlook = wc.gencache.EnsureDispatch("Outlook.Application") 而不是 Dispatch()。这应该会刷新 win32com 中的“胶水”代码,它将 [] 索引运算符转换为 getitem() 调用。
  • @DS_London 感谢您的回复。 mailitem 给出了正确的值 - 邮件项目的数量 - 这只是一个循环,以便我首先从最新访问数据。 outlook = wc.gencache.EnsureDispatch("Outlook.Application") 这解决了我的问题。添加上面之后,我得到了 win32timezone 的错误,我通过引用解决了这个错误:stackoverflow.com/questions/33212949/… 最后添加了 xcl=wc.gencache.EnsureDispatch("Excel.Application") 我的代码现在工作正常 - 谢谢。我如何接受这个作为答案?

标签: python outlook pyinstaller win32com mailitem


【解决方案1】:

从上面 DS_London 撤回的 cmets 中,我现在更改了我的代码如下:

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 参数进行了更正 - 请关注此帖子: ImportError: No module named win32timezone when i make a singleone exe from a python script with pyInstaller

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-26
    • 1970-01-01
    • 2018-10-07
    • 2022-11-16
    • 2022-01-14
    • 1970-01-01
    • 2016-02-12
    • 2023-01-26
    相关资源
    最近更新 更多