Python发票自动发送脚本故障排查求助
PDF邮件自动发送脚本错误排查与修复
问题描述
网络从业者修改Stack Exchange代码实现以下功能:遍历本地PDF文件夹(文件命名格式D1234-12345),通过Excel文件A列的经销商编号匹配C列邮箱,自动发送带PDF附件的邮件。运行时出现两个问题:
- 开启错误检查时提示:
Error: Dealer_Number .DS_Store dosnt exist - 关闭错误检查时触发
IndexError: index 0 is out of bounds for axis 0 with size 0
错误原因分析
.DS_Store文件干扰:Mac系统会在文件夹自动生成.DS_Store隐藏文件,os.listdir()会遍历到它,提取的前缀是.DS_Store,自然在Excel里找不到对应经销商编号。- 索引越界错误:当找不到匹配的经销商编号时,
row是空DataFrame,此时强行访问row['Email_Address'].values[0]会触发索引越界。 - Excel读取逻辑问题:原脚本用
names参数指定列名,可能覆盖Excel原有表头,导致经销商编号匹配失败。 - Outlook对象重复初始化:每次循环都创建新的Outlook对象,效率低下且可能引发异常。
修复方案与修改后代码
import os import pandas as pd import win32com.client # Excel文件路径 excel_path = 'C:\\invoices\\invoices.xlsx' # PDF文件夹路径 pdf_folder = 'C:\\invoicesPDF' # 读取Excel,保留原有表头,只取A、C列 try: df = pd.read_excel(excel_path, usecols="A,C") # 重命名列确保统一(如果Excel表头不是Dealer_Number/Email_Address,这里要对应修改) df.columns = ['Dealer_Number', 'Email_Address'] except Exception as e: print(f"读取Excel失败: {e}") exit() # 检查Excel数据是否为空 if df.empty: print("Error: Excel文件无有效数据,请检查文件内容。") exit() # 提前初始化Outlook对象,避免重复创建 try: outlook = win32com.client.Dispatch("Outlook.Application") except Exception as e: print(f"初始化Outlook失败: {e}") exit() # 遍历PDF文件夹,过滤非PDF和隐藏文件 for filename in os.listdir(pdf_folder): # 跳过隐藏文件(比如.DS_Store)和非PDF文件 if filename.startswith('.') or not filename.lower().endswith('.pdf'): continue pdf_path = os.path.join(pdf_folder, filename) # 提取经销商编号(分割符'-'前的部分) try: dealer_num = filename.split('-')[0] except IndexError: print(f"文件名格式错误: {filename},跳过该文件") continue # 匹配对应的邮箱 matched_row = df.loc[df['Dealer_Number'] == dealer_num] if matched_row.empty: print(f"警告: 经销商编号 {dealer_num} 在Excel中不存在,跳过文件 {filename}") continue # 获取邮箱地址(取第一个匹配结果) to_email = matched_row['Email_Address'].values[0] # 创建邮件 try: mail = outlook.CreateItem(0) mail.To = to_email mail.Subject = 'Yeti Invoice' mail.body = 'Hello, please find the attached invoice for your records.\n\nThank you.' mail.Attachments.Add(pdf_path) mail.Send() print(f"邮件已成功发送至 {to_email},附件: {filename}") except Exception as e: print(f"发送邮件失败(收件人: {to_email},文件: {filename}): {e}")
关键修复点说明
- 过滤无效文件:通过
filename.startswith('.')跳过隐藏文件,filename.lower().endswith('.pdf')确保只处理PDF文件。 - Excel读取优化:移除
names参数,读取后重命名列,避免覆盖原有表头导致匹配失败。 - 错误处理优化:遇到无效文件名或不匹配的经销商编号时,打印警告并跳过,而非直接退出程序。
- Outlook对象复用:提前初始化一次Outlook,提升运行效率。
内容的提问来源于stack exchange,提问作者Luke Shacter
相关产品推荐
相关产品推荐

