我有一个脚本,可以在共享邮件中移动/保存/分类电子邮件。当有时找不到邮件文件夹时,我会遇到错误。我正在使用下面的功能来检索邮件文件夹。有时有效,有时无效。一旦出现错误,我通常必须重新启动outlook才能使其工作。它有时找不到Inbox
中的子文件夹,并返回为空。
是否有任何方法可以确保始终找到子文件夹?
OUTLOOK = win32com.client.GetActiveObject('Outlook.Application') #This is how I dispatch outlook
Mapi - folders
['x', 'y', 'z',]
x - folders
['PersonMetadata', 'Yammer Root', 'Tasks', 'Sent Items', 'Outbox', 'Notes', 'Junk Email', 'Journal', 'Inbox', 'Files', 'ExternalContacts', 'Drafts', 'Deleted Items', 'Conversation History', 'Conversation Action Settings', 'Contacts', 'Calendar', 'Archive']
Inbox - folders
['a', 'b', 'c'] #THIS IS SOMETIMES EMPTY
FOLDERS = {"example": ["x", "Inbox", "a"]}
def get_folder(outlook_instance, *folders):
target_folder = outlook_instance
try:
for folder in folders:
print(folder_path)
print([f.Name for f in target_folder.Folders])
target_folder = target_folder.Folders[str(folder)]
except Exception:
raise ValueError("".join(f".Folders[{folder}]" for folder in folders))
return target_folder
def get_outlook_folder(folder, outlook):
mapi = outlook.GetNamespace("MAPI")
return get_folder(mapi, *FOLDERS.get(folder))
我在另一篇帖子上发现了这一点,我认为这与我的问题有关,但我真的不明白它在说什么stackoverlow.com/a/40850308/10833061
执行代码时,Outlook是否始终在系统上运行?
否则,您需要创建一个新的OutlookApplication
实例并登录到配置文件才能访问文件夹。我不是python开发人员,所以这里有一个C#示例代码,它为您说明了所需的工作流程:
Outlook.Application GetApplicationObject()
{
Outlook.Application application = null;
// Check whether there is an Outlook process running.
if (Process.GetProcessesByName("OUTLOOK").Count() > 0)
{
// If so, use the GetActiveObject method to obtain the process and cast it to an Application object.
application = Marshal.GetActiveObject("Outlook.Application") as Outlook.Application;
}
else
{
// If not, create a new instance of Outlook and sign in to the default profile.
application = new Outlook.Application();
Outlook.NameSpace nameSpace = application.GetNamespace("MAPI");
nameSpace.Logon("", "", Missing.Value, Missing.Value);
nameSpace = null;
}
// Return the Outlook Application object.
return application;
}
Outlook对象模型在所有编程语言中都很常见,所以我希望您在理解所需方法时不会遇到任何困难。请在MSDN中的获取并登录到Outlook文章的实例中了解更多信息。
最后,还不清楚什么是从哪里来的——我建议澄清发布的示例代码中的所有部分,这样我们就可以提出其他建议。
很长一段时间以来,我都遇到过类似的问题;当通过Outlook对象模型连接到Outlook时,它有时只是不显示任何现有的子文件夹;文件夹Folders.Count;显示为零。我在这两方面都经历过Python和VBA,并找到了Python解决方案!
尽管这是一个老问题,但这是谷歌上这个查询的最高结果,所以我希望这个答案能帮助未来的搜索者。
这是我的代码,只添加了一行似乎可以解决这个问题。
import win32com.client
import os
import json
import datetime as dt
def process_folder(folder, emails_list):
emailSearchDate = dt.datetime.now() - dt.timedelta(days=13)
emails = folder.Items
#True here means in descending order e.g. newest to oldest.
emails.Sort("[ReceivedTime]", True)
#We use the try/except pattern along with "while email", instead of e.g. "for email in emails", ref to https://stackoverflow.com/questions/42428770/how-to-go-through-outlook-emails-in-reverse-order-using-python/76569271#76569271 for reasons why
try:
email = emails.GetFirst()
except:
email = None
while email:
#Only process emails, not other types of items like calendar invites, contacts etc.
if email.Class == 43:
email_details = {
"Subject": str(email.Subject),
"Sender": str(email.SenderEmailAddress),
"SenderName": str(email.Sender),
"Received Time": str(email.ReceivedTime),
"Body": str(email.Body),
"Recipients": '',
"RecipientName": str(email.To)
}
for recipient in email.Recipients:
email_details['Recipients'] += recipient.Address + ';'
emails_list.append(email_details)
#Move on to the next item. If there aren't any more items, it'll set to None and break the loop
if email.Class == 43 and email.ReceivedTime.replace(tzinfo=None) < emailSearchDate:
email = None
else:
try:
email = emails.GetNext()
except:
email = None
#For this Stackoverflow query, the next line is the crucial one!
#My hypothesis is that printing folder.Folders forces Outlook to enumerate the folders instead of relying on a sometimes-empty cache?
#However, frankly, this is a guess only - I don't know the inner workings of the Outlook object model.
print(folder, folder.Folders)
#Without the above line, sometimes folder.Folders.Count is zero even though there are many subfolders.
if folder.Folders.Count > 0:
for subfolder in folder.Folders:
process_folder(subfolder, emails_list)
outlook = win32com.client.Dispatch("Outlook.Application")
namespace = outlook.GetNamespace("MAPI")
mailbox_folder = namespace.Folders.Item("EXAMPLE@EMAIL.COM").Folders("Inbox")
email_list = []
process_folder(mailbox_folder, email_list)
fileName = r'outputfile.json'
print("Saving data to " + fileName)
with open(fileName,"w") as write_file:
json.dump(email_list, write_file, default=str)