【问题标题】:win32com + outlook only capturing 50% of messages in inbox per execution?win32com + Outlook 每次执行只能捕获收件箱中 50% 的邮件?
【发布时间】:2021-01-07 10:15:55
【问题描述】:

我用 win32com 和 python3.x 创建了一个小代码,它简单地通过一个 Outlook 文件夹并对里面的消息进行处理(移动它们、阅读它们等)。

除了一个奇怪的小问题外,它完美无瑕……文件夹中只有 50% 的项目正在处理中!收件箱中有 500 件物品?分析了 250 个。 30? 15 留在收件箱中。 1?处理没有问题。

如果我使用“messages.Count”,我可以看到邮箱中有多少电子邮件 - 这个数字与我在 Outlook 中看到的相符。无论如何,当看到一半的项目时,程序就结束了。程序将倒计时 30、29、28... 在 15 处停止而不会抛出任何错误。

如果我稍微玩一下循环,执行while messages:,程序将倒计时到 15,然后给我一个“NoneType”异常,向我表明 Outlook 不再“给”python 任何消息尽管邮箱里有一些。

在这两种情况下再次运行程序将只处理剩余 50% 的消息。

知道这里发生了什么吗?这是前景吗?我什至不知道从哪里开始......这是代码的超级剥离版本。即使在这个级别,该错误仍然存​​在。 50% 的收件箱被移动,50% 仍然存在。在剩余的 50% 中,有一半在下次执行时处理。

    import win32com.client

    outlook = win32com.client.Dispatch("Outlook.Application")
    namespace = outlook.GetNamespace("MAPI")
    root_folder = namespace.Folders.Item(1) #choose account
    subfolder = root_folder.Folders['Inbox'] #choose folder, subfolder
    subfolderO = root_folder.Folders['Inbox'].Folders['Closed'] #choose                                                folder, subfolder
    messages = subfolder.Items
    message = messages.GetFirst()

    for message in messages:
        print("\n", message.Sender,"\n", message.To, "\n ", message.Subject',"\n", message.CreationTime, "\n_________")
        message.Move(subfolderO)
        message = messages.GetNext()

【问题讨论】:

    标签: python python-3.x outlook automation win32com


    【解决方案1】:

    主要问题是您在迭代 messages 时对其进行了修改:

    message.Move(subfolderO)
    

    这并不明显,但这会修改​​messages。循环将缩小一个,但您的迭代器不会向后移动,因此您会错过容器中的下一项。

    这是许多语言和容器实现中的常见问题。

    所以不要这样做。

    一种方法是制作容器的副本并对其进行迭代,随时修改原始容器。

    for message in list(messages):
        ...
        message.Move(subfolderO)
    

    另外,你不需要这样做:

        message = messages.GetNext()
    

    【讨论】:

    • 谢谢彼得。我一直在玩这个循环,我忘记了是什么......不幸的是,即使修复了迭代,问题仍然存在。盒中 10 件物品 = 5 件已处理,5 件未处理。 while message: 导致一半被处理。 while messages: 导致一半被处理,但在尝试获取第 51% 项时抛出 NoneType 错误。
    • 啊,pkay,这可能是因为您在迭代时修改了messages 容器。不要做message.Move(subfolderO),除非你已经复制了邮件。也许for message in list(messages): 就够了,但我不熟悉使用 COM 和 Outlook。
    • 就是这样。我从来没有考虑过这个......我认为消息移动揭示了这个错误,但实际上这个错误!我是堆栈交换的新手 - 我是否应该接受这个评论链作为答案,因为它导致了 cmets 中的解决方案?
    • 我会更新答案,如果你愿意,你可以投票甚至接受。尽管有时会出现更好的书面或更深入的答案,但请随时等待。
    【解决方案2】:

    我与完全相同的问题作斗争。迭代“.Move”只能通过一半的邮件。彼得伍德的解释有所帮助,尽管花了一段时间才弄清楚问题.. :) 我相信以下修改后的代码会起作用:

    import win32com.client
    
    outlook = win32com.client.Dispatch("Outlook.Application")
    namespace = outlook.GetNamespace("MAPI")
    root_folder = namespace.Folders.Item(1) #choose account
    subfolder = root_folder.Folders['Inbox'] #choose folder, subfolder
    subfolderO = root_folder.Folders['Inbox'].Folders['Closed'] #choose                                                folder, subfolder
    messages = subfolder.Items
    message = messages.GetFirst()
    
    for message in list(messages):
        print("\n", message.Sender,"\n", message.To, "\n ", message.Subject',"\n", message.CreationTime, "\n_________")
        message.Move(subfolderO)
        messages = subfolder.Items
        message = messages.GetFirst()
    

    迭代使其仅移动第一项,并通过每次迭代修改原始消息类。

    【讨论】:

      猜你喜欢
      • 2018-10-27
      • 1970-01-01
      • 2015-02-08
      • 1970-01-01
      • 2019-05-06
      • 2014-05-20
      • 2011-10-14
      • 2015-09-06
      • 2010-12-27
      相关资源
      最近更新 更多