![](/img/trans.png)
[英]How authentication works while reading outlook emails with python and win32com
[英]python win32com: Delete multiple emails in Outlook
我需要通过 win32com 模块从 python 中删除 Outlook 中的多封电子邮件。
我知道有一个 VBA 方法 MailItem.Delete() 通过 COM 可用于 win32com 并且它有效; 但是当删除多于一封电子邮件时它非常非常慢,因为必须按顺序删除电子邮件,即循环遍历 MailItem 电子邮件集合。
有什么方法可以一次删除选定的 mailItems 集合,例如 MailItemCollection.DeleteAll()?
另外,如果以上是不可能的; 是否有可能通过多线程方法删除许多电子邮件,即将mailItems 的集合划分为4 个子集; 有4个线程在上面运行吗?
我想,因为我可以通过它的 GUI 非常快速地删除 Outlook 中的多封电子邮件,所以必须有一种方法可以让我通过 COM API 做同样的事情。
不在 OOM 中 - MailItem.Delete
或Items.Remove(Index)
就是你所得到的。
在扩展 MAPI 级别(C++ 或 Delphi,但不是 Python)上,您可以使用IMAPIFolder.DeleteMessages (它采用条目 ID 列表)删除多条消息。 或者您可以使用IMAPIFolder.EmptyFolder (删除文件夹中的所有邮件)。
如果使用Redemption (任何语言;我是它的作者)是一种选择,您可以使用RDOFolder2 。 EmptyFolder
或RDOFolder 。 项目。 RemoveMultiple
。 RDOFolder
可以从RDOSession 中检索。 如果您将 Outlook 的MAPIFolder
对象作为参数传递, GetRDOObjectFromOutlookObject
。
除了@Dimitry 的一个很好的答案之外,我将添加一条对您来说可能很重要的评论:如果您在迭代时开始从 Items 中删除,则可能会发生奇怪的事情。 例如在我的系统上有以下 Python 代码:
for mail in folder.Items:
mail.Delete()
也
for index, mail in enumerate(folder.Items, 1):
folder.Remove(index)
两者都只删除folder
中的一半项目! 原因似乎是 Items 在内部使用一系列索引来提供迭代器,因此每次删除一个元素时,列表的尾部都会移动一个......
要删除文件夹中的所有项目,请尝试:
for i in range(len(folder.Items)):
folder.Remove(1)
如果您需要按某个标准进行过滤,请考虑先收集 EntryID,然后删除对 ID 的搜索:
ids = []
for i in range(len(folder.Items), 1):
if to_be_deleted(folder.Items[index]):
ids.append(index)
for id in ids:
outlook.GetEntryByID(id).Delete()
我想象它的性能更糟,不过:c
上面 Dedalus 的精彩回答。 想要制作更简洁的代码版本:
import win32com.client
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
# Select main Inbox
inbox = outlook.GetDefaultFolder(6)
messages = inbox.Items
# Delete all messages from a specific sender
sender = 'myname@abc.com'
try:
for message in messages:
try:
s = message.sender
s = str(s)
if s == sender:
message.Delete()
except:
pass
except:
pass
您可能不需要两次“尝试”,但我发现将脚本应用于长时间且频繁使用的收件箱时它更稳定。 通常我将它与将 message = inbox.Items 限制在一周内的脚本结合起来,这样它就不会处理整个收件箱。
对我来说,它通过反向迭代项目来工作。
旧:
for mail in folder.Items:
if 'whatever' in mail.Subject: # just a condition (optional)
mail.Delete()
新代码:
for mail in reversed(folder.Items): # just tried deleting Items in reverse order
if 'whatever' in mail.Subject: # just a condition (optional)
mail.Delete()
希望这可以帮助某人。
我错过了什么吗? Application 和 NameSpace 对象似乎都没有 GetEntryByID 方法,尽管 Dedalus 指出的其余部分是正确的。
命名空间对象有一个 GetItemFromID 方法,而 MailItem 对象有一个 EntryID 属性,只要它们不被重新组织到不同的文件夹中,它就会唯一地标识它们。
文档: https : //docs.microsoft.com/en-us/office/vba/outlook/how-to/items-folders-and-stores/working-with-entryids-and-storeids
我的完整解决方案:
import win32com.client
outlook = win32com.client.gencache.EnsureDispatch("Outlook.Application")
folders = outlook.GetNamespace("MAPI")
inbox= folders.GetDefaultFolder(6)
messages=inbox.Items
email_ids = []
folder_id = inbox.StoreID
# Here create a function to isolate/exclude. Below is just an example of filtering by a subject line.
email_subjects = ['Subj1','Subj2','Subj3']
for i in range(len(messages)):
if any(header in inbox.Items[i].Subject for header in email_subjects):
email_ids.append(inbox.Items[i].EntryID)
for id in email_ids:
folders.GetItemFromID(id, folder_id).Delete()
我已经在本地 Outlook 中实现了一个替代解决方案,通过直接使用 VBA 代码或 Outlook 过滤规则将电子邮件项目从.inbox 文件夹移动到已删除项目文件夹或存档文件夹。 这样,我每周只需手动清空一次已删除的项目文件夹(当然这个周期性步骤也可以编程)。 我观察到这种策略可以更有效,而不是使用代码删除每个项目(你提到了 internal.indexes 问题)。
"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.