
本文详解如何使用 Python 的 email 模块安全、准确地提取 IMAP 收取邮件的正文内容,避免常见编码错误与结构误判,推荐使用现代 EmailMessage 类及 get_body() 方法。
本文详解如何使用 python 的 `email` 模块安全、准确地提取 imap 收取邮件的正文内容,避免常见编码错误与结构误判,推荐使用现代 `emailmessage` 类及 `get_body()` 方法。
在通过 IMAP 协议读取邮件时,许多开发者会遇到 email_message.get_payload() 返回嵌套的 Message 对象列表(如 [
✅ 正确做法是:使用 email.message_from_bytes() + EmailMessage.get_body(),配合显式 policy=default 启用现代邮件处理模型(Python 3.3+):
import imaplib
import email
from email.policy import default
def read_email_body(username: str, password: str, sender_filter: str = None) -> list:
imap = imaplib.IMAP4_SSL("imap.mail.com", 993)
imap.login(username, password)
imap.select('INBOX')
# 搜索未读邮件(支持发件人过滤)
search_criteria = ['UNSEEN']
if sender_filter:
search_criteria.extend(['FROM', f'"{sender_filter}"'])
status, response = imap.uid('SEARCH', None, *search_criteria)
if status != 'OK':
return []
msg_ids = response[0].split()
results = []
for e_id in msg_ids:
# ✅ 关键修正:直接用 bytes 解析,避免 UTF-8 解码失败
_, msg_data = imap.uid('FETCH', e_id, '(RFC822)')
raw_email = msg_data[0][1] # type: bytes
email_message = email.message_from_bytes(raw_email, policy=default)
# ✅ 提取首选正文:优先 HTML,退化到纯文本
body_part = email_message.get_body(preferencelist=('html', 'plain'))
if body_part is not None:
try:
body_text = body_part.get_content() # 自动解码 base64/quopri
except (LookupError, ValueError):
# 备用:手动解码(极少数边缘情况)
payload = body_part.get_payload(decode=True)
body_text = payload.decode(body_part.get_content_charset() or 'utf-8', errors='replace')
else:
body_text = "(无正文内容)"
results.append({
'from': email.utils.parseaddr(email_message.get('From', '')),
'to': email_message.get('To', ''),
'subject': email.header.decode_header(email_message.get('Subject', ''))[0][0],
'body': body_text[:500] + '...' if len(body_text) > 500 else body_text # 示例截断
})
imap.logout()
return results
# 使用示例
emails = read_email_body("user@mail.com", "app_password", "pedro@example.com")
for mail in emails:
print(f"【{mail['subject']}】\n{mail['body']}\n{'─' * 50}")? 关键注意事项:
- 永不使用 message_from_string() 处理原始 IMAP 响应:IMAP 返回的是 bytes,可能含非 UTF-8 编码(如 GBK、ISO-8859-1),强制 .decode('utf-8') 会导致 UnicodeDecodeError。
- get_body() 是现代标准:它按 RFC 规范自动处理 multipart/alternative 的优先级协商(如客户端偏好 HTML,则返回 text/html 部分),比手动遍历 walk() 更健壮。
- 处理编码异常:get_content() 内部已调用 decode=True 并依据 Content-Transfer-Encoding(base64/quopri)和 charset 自动解码;若遇损坏邮件,需捕获异常并降级处理。
- 安全提示:生产环境务必使用应用专用密码(App Password),禁用明文密码;对 HTML 正文做 XSS 过滤后再渲染。
? 总结:提取邮件正文的本质是尊重 MIME 结构。放弃“字符串拼接”思维,拥抱 EmailMessage 的语义化 API —— get_body() 是获取人类可读内容的黄金方法,配合 message_from_bytes() 和 policy=default,即可稳健应对 99% 的真实邮件场景。
立即学习“前端免费学习笔记(深入)”;











