Python报错:AttributeError: <unknown>.DeliveryStore 获取Outlook邮箱时报错
目录
报错提示:
现象描述
代码解释:
原因分析:
报错提示:
in get_outlook_email
return account.DeliveryStore.DisplayName
line 106, in <module>
email_address = get_outlook_email()
现象描述
获取outlook本地邮箱地址时,出现AttributeError,这是原代码:
def get_outlook_email():"""Get the user's Outlook email address"""outlook = win32.Dispatch('Outlook.Application')namespace = outlook.GetNamespace('MAPI')inbox = namespace.GetDefaultFolder(6) # 6 represents the inbox folderaccount = inbox.Parentreturn account.DeliveryStore.DisplayName
代码解释:
代码创建了Outlook应用程序实例和MAPI命名空间
获取默认收件箱文件夹(GetDefaultFolder(6),6代表收件箱)。
从这个收件箱的Parent属性获取关联的账户对象
原因分析:
inbox = namespace.GetDefaultFolder(6) # 6 represents the inbox folder
因为
GetDefaultFolder
方法是从MAPI命名空间获取当前登录用户的默认文件夹,例如收件箱、发件箱、删除邮件等。
如果用户只有一个普通的电子邮件账户,那么可以正常工作,因为默认收件箱的父级(Parent)就是这个电子邮件账户对象。
如果用户配置了多个电子邮件账户,或者有一些特殊类型的邮箱(如共享邮箱、公共文件夹等),那么可能会失败。
因为如果Parent返回的不是一个有效的电子邮件账户对象,那么当代码尝试访问这个对象的DeliveryStore属性时,就会引发AttributeError异常,因为这个对象根本没有DeliveryStore属性。
举个例子,假设用户的Outlook中配置了一个普通的工作邮箱account1@company.com,和一个共享邮箱shared@company.com。
如果获取的是account1@company.com账户对应的收件箱,那么它可以正常工作。但如果获取的是shared@company.com共享邮箱的收件箱,由于共享邮箱没有关联有效的电子邮件账户对象,所以会引发AttributeError异常。
综上所述,第二种方法的失败原因不是由于获取到了共享邮箱,而是它只考虑了当前登录用户的默认收件箱,而没有处理其他情况下的账户类型。
解决方案:
判断一个账户对象是否为有效电子邮件账户的关键在于检查该账户对象是否有
DeliveryStore
属性。
if account.DeliveryStore:
就是在检查当前账户对象
account
是否有DeliveryStore
属性。如果有,则说明这是一个有效的电子邮件账户。
DeliveryStore
属性代表着该账户对应的电子邮件传输存储。只有真正的电子邮件账户才会有这个属性,而像共享邮箱、公共文件夹等特殊类型的账户则没有DeliveryStore
属性。所以,通过检查
DeliveryStore
属性的存在与否,代码可以有效地区分出哪些账户对象是有效的电子邮件账户。如果
account.DeliveryStore
存在,那么代码就从这个DeliveryStore
对象的DisplayName
属性中获取邮箱地址:
return account.DeliveryStore.DisplayName
这样就能够获取到该有效电子邮件账户的邮箱地址。
相反,如果
account.DeliveryStore
不存在,那么代码就会跳过该账户对象,继续检查下一个账户对象。通过这种方式,第一种方法可以遍历所有的账户对象,只处理有效的电子邮件账户,从而可靠地获取用户的邮箱地址。
总的来说,利用
DeliveryStore
属性的存在与否作为判断标准,是这种方法能够正确识别有效电子邮件账户的关键所在。
修改后代码:
def get_outlook_email():"""Get the user's Outlook email address"""outlook = win32.Dispatch('Outlook.Application').GetNamespace('MAPI')for account in outlook.Accounts:if account.DeliveryStore:return account.DeliveryStore.DisplayNamereturn None