求助:批量发送含对应txt与html附件对的邮件问题
问题分析与解决方案
问题根源
- 逻辑错误:原代码逐个遍历单个文件而非按编号配对处理文件组,导致每次邮件仅能附加一个文件,且硬编码附件名为
signal.html,无法匹配对应编号的文件。 - 作用域混乱:
sendmail函数定义在循环内部,变量捕获逻辑异常,且未动态传入当前处理的文件路径。 - 未定义变量:
html_body中的{html}变量未赋值,运行时会触发报错。
修正后的代码
from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email.mime.text import MIMEText from email import encoders import smtplib, ssl import os def sendmail(file_pair, sender, receiver): # 读取html文件内容作为邮件正文 html_path = file_pair['html'] with open(html_path, 'r', encoding='utf-8') as f: html_content = f.read() html_body = f''' <html> <body> <p style="font-size: 12;"> <strong>Alert</strong><br>{html_content}</p> </body> </html> ''' subject = f'Signal {file_pair["id"]} 文件' # 创建多部分邮件消息 message = MIMEMultipart() message['From'] = sender message['To'] = receiver message['Subject'] = subject # 添加邮件正文 message.attach(MIMEText(html_body, 'html')) # 附加两个文件 for file_path in [file_pair['txt'], file_pair['html']]: filename = os.path.basename(file_path) with open(file_path, 'rb') as attachment: part = MIMEBase('application', 'octet-stream') part.set_payload(attachment.read()) encoders.encode_base64(part) part.add_header( 'Content-Disposition', f"attachment; filename= {filename}", ) message.attach(part) # 发送邮件 text = message.as_string() context = ssl.create_default_context() with smtplib.SMTP("smtp.mail.com", 25) as server: # server.starttls(context=context) # server.login(sender, 'password') server.sendmail(sender, receiver, text) print(f"Signal {file_pair['id']} 的邮件已发送!") # 主逻辑:按编号分组文件 dirname = r'C:\Path\To\Files' file_groups = {} for entry in os.scandir(dirname): if entry.is_file(): filename = entry.name # 提取文件编号(如signal1.txt中的'1') if filename.startswith('signal') and (filename.endswith('.txt') or filename.endswith('.html')): file_id = filename[6:-4] # 从"signalX.ext"中提取X ext = filename[-4:] if file_id not in file_groups: file_groups[file_id] = {'id': file_id} file_groups[file_id][ext[1:]] = entry.path # 存储为'txt'或'html'键 # 遍历每组文件发送邮件 senders_email = 'mail@mail.com' receiver_email = 'mail@mail.com' for group in file_groups.values(): # 确保组内同时存在txt和html文件 if 'txt' in group and 'html' in group: sendmail(group, senders_email, receiver_email) else: print(f"Signal {group['id']} 文件不完整,跳过发送")
关键改进点
- 按编号分组:通过提取文件名中的编号,将同编号的txt和html文件配对,确保每组文件一次性处理。
- 独立函数封装:将
sendmail函数移到循环外部,通过参数传递文件路径、收发件人等信息,避免作用域问题。 - 动态附加文件:循环处理组内的两个文件,动态获取文件名和路径,确保附件正确匹配。
- 修复正文变量:读取对应html文件内容作为邮件正文,解决原代码中变量未定义的问题。
内容的提问来源于stack exchange,提问作者CUI
相关产品推荐
相关产品推荐

