python win32com:在Outlook中删除多封电子邮件

时间:2018-11-28 16:24:42

标签: python api outlook com win32com

我需要通过win32com模块从python中删除Outlook中的多封电子邮件。

我知道有一个VBA方法MailItem.Delete()可通过COM用于win32com,并且可以工作;但是删除多个电子邮件时非常慢,因为必须依次删除电子邮件,即遍历电子邮件的MailItem集合。

是否可以立即删除选定的mailItem集合,例如MailItemCollection.DeleteAll()?

此外,如果不可能的话;是否有可能通过多线程方法删除许多电子邮件,即将mailItems的集合分为4个子集;有4个线程在这些线程上运行?

我认为,因为可以通过Outlook的GUI快速删除Outlook中的多封电子邮件,所以必须有一种方法可以通过COM API进行相同的操作。

5 个答案:

答案 0 :(得分:2)

不在OOM中-仅获得the_post_thumbnail( 'large','style=max-width:100%;height:auto;'); MailItem.Delete

在扩展MAPI级别(C ++或Delphi,但不是Python)上,可以使用IMAPIFolder.DeleteMessages(带有条目ID列表)删除多条消息。或者,您可以使用IMAPIFolder.EmptyFolder(删除文件夹中的所有邮件)。

如果可以选择使用Redemption(任何语言;我是它的作者),则可以使用RDOFolder2Items.Remove(Index)RDOFolderItemsEmptyFolder。如果您将Outlook的RemoveMultiple对象作为参数传递,则可以从RDOSession中检索RDOFolderGetRDOObjectFromOutlookObject

答案 1 :(得分:2)

在@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

答案 2 :(得分:1)

上面的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

您可能不需要两个“ trys”,但我发现将脚本应用于长时间使用且频繁使用的收件箱时,它更加稳定。通常,我将其与脚本结合使用,该脚本将message = inbox.Items限制在一周之内,因此不会处理整个收件箱。

答案 3 :(得分:1)

对我来说,它是通过反向迭代这些项来工作的。

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()

希望这对某人有帮助。

答案 4 :(得分:0)

我想念什么吗?尽管Dedalus指出的其余部分是正确的,但Application和NameSpace对象似乎都没有GetEntryByID方法。

命名空间对象具有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()