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

Python邮件回复脚本无法生成对话线程的问题求助

问题描述

我需要实现以下邮件回复逻辑:扫描收件箱中的未读邮件,筛选出包含特定主题内容的邮件,满足条件则向发送者回复指定内容,不满足则回复另一内容。我编写了如下Python代码,但目前代码仅能发送新邮件,无法形成预期的对话线程,请问如何修改以实现带对话线程的邮件回复?

import imaplib
import email
import smtplib


username = 'sample@gmail.com'
password = 'xxxx'


imap_server = imaplib.IMAP4_SSL('smtp.gmail.com')
imap_server.login(username, password)

imap_server.select('INBOX')

result, data = imap_server.search(None, '(UNSEEN)')

email_ids = data[0].split()

for email_id in email_ids:

    result, data = imap_server.fetch(email_id, "(RFC822)")

    raw_email = data[0][1]

    email_message = email.message_from_bytes(raw_email)

    subject = email_message["Subject"]

    if subject == "SOME SPECIFIC CONTENT":

        reply = email.message.EmailMessage()
        reply["To"] = email_message["From"]
        reply["Subject"] = "Re: " + email_message["Subject"]
        reply["In_Reply-To"] = email_message["From"]
              

        server = smtplib.SMTP('smtp.gmail.com', 587)
        server.ehlo()
        server.starttls()
        server.login(username, password)

        server.sendmail(username, reply["In_Reply-To"], 'Subject: Criteria met\n\nThank you.')
        server.quit()

    else:

        
        reply = email.message.EmailMessage()
        reply['To'] = email_message['From']
        reply['Subject'] = "RE:" + email_message['Subject']
        reply["In_Reply-To"] = email_message["From"]
        

        server = smtplib.SMTP('smtp.gmail.com', 587)
        server.ehlo()
        server.starttls()
        server.login(username, password)

        server.sendmail(username, reply["In_Reply-To"], 'Subject: Criteria not met\n\Thank you.')
        print('Sending email')
        server.quit()

imap_server.close()
修复方案

邮件客户端识别对话线程依赖In-Reply-To和References两个核心邮件头,同时需要正确使用构建好的邮件对象发送,以下是具体修改点:

  • 修正回复关联的邮件头:
    原代码错误地将From值赋值给In-Reply-To,正确的做法是使用原邮件的Message-ID。同时添加References头并设置为相同的Message-ID,确保多数邮件客户端能识别对话线程。
  • 正确使用EmailMessage对象发送:
    之前的代码构建了reply对象但未实际使用,而是直接发送纯文本字符串,导致设置的主题、回复头等元数据失效。需要将邮件内容写入reply对象,再发送其字节形式。
  • 复用SMTP连接提升效率:
    原代码每处理一封邮件就新建并关闭SMTP连接,将SMTP连接的创建和登录放在循环外,循环内仅发送邮件,最后统一关闭连接。

修改后的完整代码

import imaplib
import email
import smtplib


username = 'sample@gmail.com'
password = 'xxxx'

# 初始化IMAP连接(修正原代码服务器地址错误)
imap_server = imaplib.IMAP4_SSL('imap.gmail.com')
imap_server.login(username, password)
imap_server.select('INBOX')

# 搜索未读邮件
result, data = imap_server.search(None, '(UNSEEN)')
email_ids = data[0].split()

# 提前初始化SMTP连接,复用连接
smtp_server = smtplib.SMTP('smtp.gmail.com', 587)
smtp_server.ehlo()
smtp_server.starttls()
smtp_server.login(username, password)

for email_id in email_ids:
    result, data = imap_server.fetch(email_id, "(RFC822)")
    raw_email = data[0][1]
    email_message = email.message_from_bytes(raw_email)
    
    subject = email_message["Subject"]
    original_msg_id = email_message["Message-ID"]  # 获取原邮件的Message-ID
    sender = email_message["From"]

    # 构建回复邮件
    reply = email.message.EmailMessage()
    reply["To"] = sender
    reply["Subject"] = f"Re: {subject}"
    reply["In-Reply-To"] = original_msg_id
    reply["References"] = original_msg_id
    reply["From"] = username  # 显式设置发件人,避免客户端识别异常

    # 根据主题设置回复内容
    if subject == "SOME SPECIFIC CONTENT":
        reply.set_content("Thank you.")
    else:
        reply.set_content("Thank you.")
        print('Sending email')
    
    # 发送回复邮件
    smtp_server.send_message(reply)

# 关闭所有连接
smtp_server.quit()
imap_server.close()
imap_server.logout()

额外说明

  • 原代码中IMAP服务器地址写错,应为imap.gmail.com而非smtp.gmail.com,已一并修正。
  • 使用send_message方法发送EmailMessage对象,会自动处理所有邮件头和内容,比sendmail更可靠。

内容的提问来源于stack exchange,提问作者tomh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 13:10:42