如何使用smtplib基于已有未读邮件对象完成邮件回复
问题根因
- smtplib发信必须明确指定实际收件人,
Reply-To仅为邮件头标识,用于告知收件方回复该邮件时的目标地址,不能作为发信时的收件人配置,未填写msg['To']或smtplib.sendmail未传有效收件人参数,就会触发收件人地址无效的报错。 - 仅填写
msg['To']无法实现回复效果,是因为邮件客户端依赖特定的邮件头识别会话线程,缺少对应配置就会被识别为独立新邮件。
实现正确回复的步骤
1. 从原始邮件提取必要字段
你手里的未读邮件对象(下文称original_msg)需要先取出以下字段:
- 回复目标地址:优先取
original_msg['Reply-To'],如果不存在则取original_msg['From'] - 原始邮件ID:取
original_msg['Message-ID'],用于标记会话关联 - 原始邮件主题:取
original_msg['Subject'],回复主题默认加Re:前缀 - 原始引用链:取
original_msg.get('References', ''),用于补全会话引用链
2. 构造回复邮件并补充必要头字段
核心需要补充2个会话关联头:
In-Reply-To:值为原始邮件的Message-IDReferences:值为原始邮件的References拼接上原始邮件的Message-ID
代码示例如下:
import smtplib from email.message import EmailMessage # 提取原始邮件信息 reply_to = original_msg.get('Reply-To', original_msg['From']) original_msg_id = original_msg['Message-ID'] original_subject = original_msg['Subject'] original_ref = original_msg.get('References', '') # 构造回复邮件 reply_msg = EmailMessage() reply_msg['From'] = '你的邮箱地址' reply_msg['To'] = reply_to # 必须配置实际收件人 # 处理回复主题,避免重复加Re:前缀 reply_msg['Subject'] = original_subject if original_subject.startswith('Re: ') else f'Re: {original_subject}' # 配置会话关联头,实现回复线程效果 reply_msg['In-Reply-To'] = original_msg_id reply_msg['References'] = f"{original_ref} {original_msg_id}".strip() # 配置回复内容,可选引用原始邮件 content = "你的回复内容\n\n--- 原始邮件引用 ---\n" for line in original_msg.get_content().splitlines(): content += f"> {line}\n" reply_msg.set_content(content) # 发送邮件 with smtplib.SMTP_SSL('smtp.你的邮箱服务商地址', 465) as srv: srv.login('你的邮箱地址', '你的邮箱授权码') # sendmail方法必须传入有效收件人列表 srv.sendmail( from_addr=reply_msg['From'], to_addrs=[reply_to], msg=reply_msg.as_string() )
注意事项
- 如果原始邮件有多个收件人、需要抄送原收件列表,可以额外提取
original_msg['To']、original_msg['Cc']字段补充到回复邮件的Cc头中,同时同步到sendmail的to_addrs参数里。 - 纯文本邮件直接用
get_content()获取内容即可,如果是多格式邮件,需要先判断内容类型再提取对应正文。
内容的提问来源于stack exchange,提问作者user13973948
相关产品推荐
相关产品推荐

