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.
背景是我在 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.