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

如何让email.message_from_bytes兼容Unicode/Emoji输入避免报错

问题

使用email.message_from_bytes()处理包含Unicode/Emoji的邮件头时,会触发意外的TypeError,同时邮件头中的Emoji会显示为乱码。需要通过编码/解码处理,让gyb.py能正常清理恢复含Unicode/Emoji的.eml备份文件,且字符不损坏。

最小复现代码

import email
f = open('./sample.eml', 'rb')
bytes = f.read()
message = email.message_from_bytes(bytes)

# 无Unicode/Emoji:正常工作
print(message['to'])
print(len(message['to']))

# 含Unicode/Emoji:出现意外TypeError
print(message['from'])
print(len(message['from']))

sample.eml内容

To: recipient <to@example.com>
From:🔥sender🔥 <from@example.com>

运行输出

$ python check-message.py
recipient <to@example.com>
26
����sender���� <from@example.com>
Traceback (most recent call last):
  File "V:\gyb\jkm\check-message.py", line 10, in <module>
    print(len(message['from']))
          ^^^^^^^^^^^^^^^^^^^^
TypeError: object of type 'Header' has no len()

解决方法

1. 用现代化解析策略(最简便)

Python 3.3+的email模块提供了默认策略,能自动处理Unicode邮件头,直接返回字符串而非Header对象,彻底解决问题:

import email

f = open('./sample.eml', 'rb')
bytes = f.read()
# 指定默认策略解析
message = email.message_from_bytes(bytes, policy=email.policy.default)

print(message['to'])
print(len(message['to']))

print(message['from'])  # 正确显示🔥sender🔥 <from@example.com>
print(len(message['from']))  # 正常获取长度

2. 解析后处理Header对象

如果不能修改解析策略,可直接将返回的Header对象转为字符串,解决乱码和len()调用失败问题:

import email

f = open('./sample.eml', 'rb')
bytes = f.read()
message = email.message_from_bytes(bytes)

# 正常处理无Unicode的头
print(message['to'])
print(len(message['to']))

# 处理含Emoji的头
from_header = message['from']
from_str = str(from_header)
print(from_str)  # 正确显示🔥sender🔥 <from@example.com>
print(len(from_str))  # 正常获取长度

3. 预处理.eml文件(修复非标准邮件头)

原始.eml的邮件头未按MIME规范编码(直接用了未编码的Emoji),可提前将其转为标准Encoded-Word格式:

import email
from email.header import Header

# 读取并解码.eml内容
with open('./sample.eml', 'rb') as f:
    eml_content = f.read().decode('utf-8')

# 拆分邮件头和正文
header_part, body_part = eml_content.split('\n\n', 1)
new_headers = []

for line in header_part.splitlines():
    if line.startswith('From:'):
        # 拆分名称和邮箱部分
        name_part = line.split('<')[0].replace('From:', '').strip()
        email_part = line.split('<')[1].strip()
        # 编码含Emoji的名称为标准格式
        encoded_name = Header(name_part, 'utf-8').encode()
        new_from = f'From: {encoded_name} <{email_part}'
        new_headers.append(new_from)
    else:
        new_headers.append(line)

# 重新组合并转为二进制
fixed_eml_content = '\n'.join(new_headers) + '\n\n' + body_part
fixed_eml_bytes = fixed_eml_content.encode('utf-8')

# 解析修复后的内容
message = email.message_from_bytes(fixed_eml_bytes)
print(message['from'])
print(len(str(message['from'])))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 14:53:26