You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:批量发送含对应txt与html附件对的邮件问题

问题分析与解决方案

问题根源

  1. 逻辑错误:原代码逐个遍历单个文件而非按编号配对处理文件组,导致每次邮件仅能附加一个文件,且硬编码附件名为signal.html,无法匹配对应编号的文件。
  2. 作用域混乱:sendmail函数定义在循环内部,变量捕获逻辑异常,且未动态传入当前处理的文件路径。
  3. 未定义变量: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 09:56:20