Python win32com读取Outlook邮件仅到2024/05/31问题求助
问题描述
我用Python的win32com库编写了读取Outlook指定文件夹邮件的代码,可实现匹配主题下载附件并解压文件功能。但运行时发现,无论选择哪个文件夹,代码仅能扫描处理2024年5月31日及之前的邮件,无法处理该日期之后的邮件,请求帮忙排查代码中的问题。
原代码
from logging import root import os import win32com.client from datetime import datetime, timedelta import zipfile date_format = "%m/%d/%Y %H:%M" def recursively_find_folder(folder, target_name): if folder.Name == target_name: return folder for subfolder in folder.Folders: found_folder = recursively_find_folder(subfolder, target_name) if found_folder: return found_folder #function to check the emails mentioned in outlook folder and down load the attachements based on email subject def download_attachments(folder_name, output_folder, start_time, end_time, target_subject): outlook_app = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI") #root_folder = outlook_app.Folders.Item(3) # Assume the first folder is the mailbox root_folder = outlook_app.GetDefaultFolder(6) # Assume the first folder is the mailbox target_folder = recursively_find_folder(root_folder, folder_name) if target_folder: print(f"Found folder: {target_folder.Name}") # Iterate through items in the folder items = target_folder.Items items.sort("[ReceivedTime]", True) for item in items: print("Item:: ", item) print(" Subject:: ", item.Subject.lower()) print(" Recevied Time: ", item.ReceivedTime) # Check if the email matches the criteria for subject in target_subject: print(subject) print("Email Received Time: ", datetime.strptime(item.ReceivedTime.strftime('%m/%d/%Y %H:%M'), date_format)) if ( start_time <= datetime.strptime(item.ReceivedTime.strftime('%m/%d/%Y %H:%M'), date_format) <= end_time and subject.lower().strip() in item.Subject.lower().strip() and item.Attachments.Count > 0 ): print(f"Processing email: {item.Subject}") for attachment in item.Attachments: # Save attachments to the output folder attachment.SaveAsFile(os.path.join(output_folder, attachment.FileName)) print(f"Downloaded attachment: {attachment.FileName}") else: print("Nothing Happened!!!") else: print(f"Folder '{folder_name}' not found.") #-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- #function to find zip folder and unzip it def find_and_unzip_report_file(folder_path, extraction_path): # Check if the folder exists if not os.path.exists(folder_path): print(f"Error: Folder '{folder_path}' not found.") return # Get a list of all files in the folder files = os.listdir(folder_path) # Find the report file based on the name pattern report_file = next((file for file in files if file.lower().startswith('report') and file.lower().endswith('.zip')), None) if report_file: # Construct the full path to the zip file zip_file_path = os.path.join(folder_path, report_file) # Create the extraction path if it doesn't exist os.makedirs(extraction_path, exist_ok=True) # Unzip the contents of the zip file with zipfile.ZipFile(zip_file_path, 'r') as zip_ref: zip_ref.extractall(extraction_path) os.rename(folder_path + 'CC CM Provisioning - INC SLA - ALL.csv', folder_path + 'CC CM Provisioning - INC SLA - ALL' + '-' + report_file[7:24] + '.csv') os.remove(zip_file_path) print(f"Successfully unzipped '{zip_file_path}' to '{extraction_path}'.") else: print("Error: Report file not found in the specified folder.") if __name__ == "__main__": folder_to_download = "service_tickets" output_directory = "//prod_drive/meta/downloads/" # Get the first day of the current month start_date_time = (datetime.today().replace(day=1, hour=23, minute=0, second=0, microsecond=0) - timedelta(days=1)).strftime('%m/%d/%Y %H:%M') end_date_time = (datetime.today().replace(day=1, hour=23, minute=10, second=0, microsecond=0) - timedelta(days=1)).strftime('%m/%d/%Y %H:%M') date_format = "%m/%d/%Y %H:%M" start_time = datetime.strptime(start_date_time, date_format) print("Start Time:", start_time) end_time = datetime.strptime(end_date_time, date_format) print("End Time: ", end_time) target_subject = ['CC CM Provisioning - INC SLA - ALL','CC CM Provisioning - SCTASK SLA - All','CC CM Provisioning - SCTASK - All'] download_attachments(folder_to_download, output_directory, start_time, end_time, target_subject) find_and_unzip_report_file(output_directory, output_directory)
问题排查与修复方案
1. Outlook Items集合的加载限制
Outlook的Items集合默认不会一次性加载所有邮件,通常只会加载最近的一批旧数据(比如前250条),直接遍历无法获取未加载的新邮件。解决方法是使用**Restrict方法先过滤时间范围**,让Outlook直接返回符合条件的所有邮件,而非遍历全部已加载项。
2. 日期时间转换的精度丢失
代码中把item.ReceivedTime转成字符串再转回datetime,会丢失秒和微秒信息,可能导致新邮件的时间判断逻辑出错。应该直接从ReceivedTime的属性中提取年、月、日等信息构建datetime对象,跳过字符串中转步骤。
3. 修改后的核心代码
替换download_attachments函数中的邮件遍历部分为以下代码:
if target_folder: print(f"Found folder: {target_folder.Name}") items = target_folder.Items items.Sort("[ReceivedTime]", True) # 构建Outlook兼容的时间过滤条件(Jet语法,日期需用单引号包裹) start_filter = start_time.strftime('%Y-%m-%d %H:%M') end_filter = end_time.strftime('%Y-%m-%d %H:%M') filter_str = f"[ReceivedTime] >= '{start_filter}' AND [ReceivedTime] <= '{end_filter}'" # 过滤出符合时间范围的邮件 filtered_items = items.Restrict(filter_str) for item in filtered_items: # 直接从ReceivedTime属性构建datetime对象,避免精度丢失 received_dt = datetime( item.ReceivedTime.year, item.ReceivedTime.month, item.ReceivedTime.day, item.ReceivedTime.hour, item.ReceivedTime.minute, item.ReceivedTime.second ) print(" Subject:: ", item.Subject.lower()) print(" Received Time: ", received_dt) # 匹配主题并处理附件 for subject in target_subject: if (subject.lower().strip() in item.Subject.lower().strip() and item.Attachments.Count > 0): print(f"Processing email: {item.Subject}") for attachment in item.Attachments: save_path = os.path.join(output_folder, attachment.FileName) attachment.SaveAsFile(save_path) print(f"Downloaded attachment: {attachment.FileName}")
额外注意事项
- 确保
root_folder指向正确的邮箱根目录:当前代码用GetDefaultFolder(6)获取的是收件箱,如果目标文件夹不在收件箱下,需要修改为对应的根邮箱(比如outlook_app.Folders.Item("你的邮箱地址"))。 Restrict方法的过滤语法需严格遵循Outlook的Jet查询语法,日期格式必须为yyyy-mm-dd hh:mm。
内容的提问来源于stack exchange,提问作者Nikhil Ravindran
相关产品推荐
相关产品推荐

