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
相关产品推荐
相关产品推荐

