通过 MAPI 使用 Python 从 Outlook 读取电子邮件
Posted
技术标签:
【中文标题】通过 MAPI 使用 Python 从 Outlook 读取电子邮件【英文标题】:Reading e-mails from Outlook with Python through MAPI 【发布时间】:2011-07-01 22:44:55 【问题描述】:我正在尝试编写一个简短的程序,该程序将读取我的 Exchange/Outlook 配置文件中文件夹内的电子邮件内容,以便我可以操作数据。但是,我在查找有关 python 和交换/Outlook 集成的大量信息时遇到问题。很多东西要么很旧/没有文档/没有解释。我已经尝试了几个 sn-ps,但似乎遇到了同样的错误。我试过 Tim Golden 的代码:
import win32com.client
session = win32com.client.gencache.EnsureDispatch ("MAPI.Session")
#
# Leave blank to be prompted for a session, or use
# your own profile name if not "Outlook". It is also
# possible to pull the default profile from the registry.
#
session.Logon ("Outlook")
messages = session.Inbox.Messages
#
# Although the inbox_messages collection can be accessed
# via getitem-style calls (inbox_messages[1] etc.) this
# is the recommended approach from Microsoft since the
# Inbox can mutate while you're iterating.
#
message = messages.GetFirst ()
while message:
print message.Subject
message = messages.GetNext ()
但是我得到一个错误:
pywintypes.com_error: (-2147221005, 'Invalid class string', None, None)
不确定我的个人资料名称是什么,所以我尝试了:
session.Logon()
得到提示,但这也不起作用(同样的错误)。还尝试了打开和关闭 Outlook,但都没有改变任何东西。
【问题讨论】:
您是否考虑过对服务器使用 IMAP 而不是依赖 Outlook 客户端?根据您的用例,IMAP 可能被证明是可行的并且更便携(客户端和服务器)。 @Jason IMAP 看起来不错,但遗憾的是我使用的帐户没有启用。 【参考方案1】:我遇到了与您相同的问题 - 没有发现很多有效的方法。然而,下面的代码就像一个魅力。
import win32com.client
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder(6) # "6" refers to the index of a folder - in this case,
# the inbox. You can change that number to reference
# any other folder
messages = inbox.Items
message = messages.GetLast()
body_content = message.body
print body_content
【讨论】:
有没有办法查看其他消息属性?我想使用您的示例来获取收到消息的日期和时间。 找到了解决方案:message.CreationTime
出于某种原因,当我使用 dir() 时属性没有出现
@sequoia - 使用 Microsoft 的 MailItems 的 COM 属性列表(例如:Outlook 邮件)是我找到所有邮件属性的方法(例如,message.SenderEmailAddress):msdn.microsoft.com/en-us/library/…
GetDefaultFolder-Params 可以在msdn.microsoft.com/de-de/library/office/ff861868.aspx找到
"6" 是指收件箱文件夹。其他文件夹呢?如果你新建一个文件夹,你怎么知道它得到的是哪个序号?【参考方案2】:
我创建了自己的迭代器来通过 python 迭代 Outlook 对象。问题是 python 尝试从 Index[0] 开始迭代,但 Outlook 期望第一项 Index[1] ... 方法:
.items() - 产生一个元组(index, Item)...
.prop() - 帮助内省暴露可用属性(方法和属性)的 Outlook 对象
from win32com.client import constants
from win32com.client.gencache import EnsureDispatch as Dispatch
outlook = Dispatch("Outlook.Application")
mapi = outlook.GetNamespace("MAPI")
class Oli():
def __init__(self, outlook_object):
self._obj = outlook_object
def items(self):
array_size = self._obj.Count
for item_index in xrange(1,array_size+1):
yield (item_index, self._obj[item_index])
def prop(self):
return sorted( self._obj._prop_map_get_.keys() )
for inx, folder in Oli(mapi.Folders).items():
# iterate all Outlook folders (top level)
print "-"*70
print folder.Name
for inx,subfolder in Oli(folder.Folders).items():
print "(%i)" % inx, subfolder.Name,"=> ", subfolder
【讨论】:
它们是否以任何特定方式排序?喜欢从最近到最旧?【参考方案3】:我有同样的问题。结合互联网(及以上)的各种方法得出以下方法(checkEmails.py)
class CheckMailer:
def __init__(self, filename="LOG1.txt", mailbox="Mailbox - Another User Mailbox", folderindex=3):
self.f = FileWriter(filename)
self.outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI").Folders(mailbox)
self.inbox = self.outlook.Folders(folderindex)
def check(self):
#===============================================================================
# for i in xrange(1,100): #Uncomment this section if index 3 does not work for you
# try:
# self.inbox = self.outlook.Folders(i) # "6" refers to the index of inbox for Default User Mailbox
# print "%i %s" % (i,self.inbox) # "3" refers to the index of inbox for Another user's mailbox
# except:
# print "%i does not work"%i
#===============================================================================
self.f.pl(time.strftime("%H:%M:%S"))
tot = 0
messages = self.inbox.Items
message = messages.GetFirst()
while message:
self.f.pl (message.Subject)
message = messages.GetNext()
tot += 1
self.f.pl("Total Messages found: %i" % tot)
self.f.pl("-" * 80)
self.f.flush()
if __name__ == "__main__":
mail = CheckMailer()
for i in xrange(320): # this is 10.6 hours approximately
mail.check()
time.sleep(120.00)
为了保持一致性,我还包含了 FileWriter 类的代码(在 FileWrapper.py 中找到)。我需要这个,因为 尝试将 UTF8 传输到 Windows 中的文件不起作用。
class FileWriter(object):
'''
convenient file wrapper for writing to files
'''
def __init__(self, filename):
'''
Constructor
'''
self.file = open(filename, "w")
def pl(self, a_string):
str_uni = a_string.encode('utf-8')
self.file.write(str_uni)
self.file.write("\n")
def flush(self):
self.file.flush()
【讨论】:
【参考方案4】:对不起,我的英语不好。 使用带有 MAPI 的 Python 检查邮件更容易,
outlook =win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
folder = outlook.Folders[5]
Subfldr = folder.Folders[5]
messages_REACH = Subfldr.Items
message = messages_REACH.GetFirst()
在这里,我们可以将第一封邮件放入邮箱或任何子文件夹。实际上,我们需要检查邮箱号码和方向。借助此分析,我们可以检查每个邮箱及其子邮箱文件夹。
同样请找到以下代码,我们可以在其中看到最后/较早的邮件。我们需要如何检查。
`outlook =win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
folder = outlook.Folders[5]
Subfldr = folder.Folders[5]
messages_REACH = Subfldr.Items
message = messages_REACH.GetLast()`
这样,我们可以将最近的电子邮件放入邮箱。 根据上面提到的代码,我们可以检查我们所有的邮箱,以及它的子文件夹。
【讨论】:
以上是关于通过 MAPI 使用 Python 从 Outlook 读取电子邮件的主要内容,如果未能解决你的问题,请参考以下文章
从 C# 中的 MailItem 获取命名的 MAPI 属性
Outlook.MailItem.EntryID 和 Mapi32.dll MessageID 之间的区别
当 Delphi 32 位应用程序的相同代码工作时,从 Delphi 64 位应用程序调用 MAPI 电子邮件不起作用?