Python/Outlook: 每次只提取一半的邮件

Python/Outlook: Only half of the emails picked up each time

背景是我在 Unix 上有一个预定的工作,这个工作一夜之间给我发送了数百封电子邮件。每天早上我都想保存这些邮件的附件。 我写了一个 python 片段来自动化这个过程。然而,似乎每次当我 运行 脚本时,只有一半的电子邮件(在我的目标目录中)会得到处理。 这就是我今天早上从日志中得到的:

2021-11-18 06:13:30,688 : INFO : utils.util : Before clean up. 335 items in total
2021-11-18 06:13:42,098 : INFO : utils.util : After clean up. 167 items remained
2021-11-18 06:14:17,968 : INFO : utils.util : Before clean up. 167 items in total
2021-11-18 06:14:25,660 : INFO : utils.util : After clean up. 83 items remained
2021-11-18 06:14:34,762 : INFO : utils.util : Before clean up. 83 items in total
2021-11-18 06:14:38,591 : INFO : utils.util : After clean up. 41 items remained
2021-11-18 06:14:47,633 : INFO : utils.util : Before clean up. 41 items in total
2021-11-18 06:14:49,745 : INFO : utils.util : After clean up. 20 items remained
2021-11-18 06:14:56,348 : INFO : utils.util : Before clean up. 20 items in total
2021-11-18 06:14:57,426 : INFO : utils.util : After clean up. 9 items remained
2021-11-18 06:15:15,807 : INFO : utils.util : Before clean up. 9 items in total
2021-11-18 06:15:16,260 : INFO : utils.util : After clean up. 4 items remained
2021-11-18 06:15:22,981 : INFO : utils.util : Before clean up. 4 items in total
2021-11-18 06:15:23,215 : INFO : utils.util : After clean up. 1 items remained
2021-11-18 06:15:36,117 : INFO : utils.util : Before clean up. 1 items in total
2021-11-18 06:15:36,164 : INFO : utils.util : After clean up. 0 items remained

335->167->83->41->20->9->4->1->0

关于潜在问题是什么,你能给我一些提示吗?

这是我的代码:

import os
import win32com.client

def get_target_folder(folder: str):
    outlook = win32com.client.Dispatch('outlook.application')
    mapi = outlook.GetNamespace("MAPI")
    target = mapi
    dir = folder.split("\")
    for d in dir:
        try:
            target = target.Folders(d)
        except:
            logger.error("Current folder path {}. The sub folder {} doesn't exist".format(target.FolderPath, d))
            target = None
            break

    return target


def save_job_status():
    mailfolder= config["OUTLOOK"]["JOBS"]
    keyword = config["OUTLOOK"]["KEYWORD"]
    destination = config["OUTLOOK"]["LOCALDATA"]
    criteria = f"@SQL=\"urn:schemas:httpmail:subject\" like '%{keyword}%'"

    folder = get_target_folder(folder=mailfolder)
    items = folder.items
    emails = items.restrict(criteria)
    logger.info("Before clean up. {} items in total".format(emails.count))

    for email in emails:
        try:
            attachments = email.attachments
            for attachment in attachments:
                filename = attachment.FileName
                attachment.SaveAsFile(os.path.join(destination, filename ))
            email.Delete()
        except:
            logger.error("Can't operate on the email {}".format(email.Subject))
    items = folder.items
    logger.info("After clean up. {} items remained".format(items.count))

因为我也设置了outlook规则,所以所有的邮件都进入那个“JOBS”文件夹,在我的outlook中,是那些满足条件并且应该被处理的。我设置一个“条件”只是为了避免操作错误。

提前致谢!

========================已确定解决方案============== ========= 参考了@Dmitry Streblechenko 的回答后,我明白了。 这是一个集合,我正在修改集合,同时我正在访问它。

我为解决这个问题所做的关键修改如下

  count = emails.count
        for i in range(count-1, -1, -1):
            print("{} {}".format(i, emails[i].subject))
            emails[i].Delete()

请注意这是一个反向索引访问,即从最大到最小,使用范围。当集合的底部被移除时,顶部的仍然可以使用原始索引访问。

如果您正在修改集合(通过调用 email.Delete()),请不要使用 for email in emails: 循环。使用从 emails.Count 向下循环到 1.