我有一个.eml
包含 MS-Word 附件的电子邮件文件:
------=_Part_239376_662463351.1415605722579
Content-Type: application/msword;
name="=?GBK?B?1cK5scf4s8e53L7WudjT2s34wufT38fp0MXPoteo?=
=?GBK?B?sai1xLTwuLQoz8K6vszBMbrFKS5kb2M=?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="=?GBK?B?1cK5scf4s8e53L7WudjT2s34wufT38fp0MXPoteo?=
=?GBK?B?sai1xLTwuLQoz8K6vszBMbrFKS5kb2M=?="
0M8R4KGxGuEAAAAAAAAA [rest of base64-encoded attachment]
我成功对附件进行了 base64 解码,文件内容正常。
但是如何解码文件名呢?
的价值filename=""
似乎成为繁體中文-encoded 但 Python.decode('gbk')
无法运作,返回相同的字符串:
>>> "1cK5scf4s8e53L7WudjT2s34wufT38fp0MXPoteo".decode('gbk')
u'1cK5scf4s8e53L7WudjT2s34wufT38fp0MXPoteo'
那么,这个字符串是用什么编码的以及如何解码呢?
=?GBK?B?1cK5scf4s8e53L7WudjT2s34wufT38fp0MXPoteo?=
=?GBK?B?sai1xLTwuLQoz8K6vszBMbrFKS5kb2M=?=
答案1
这些 -
=?GBK?B?1cK5scf4s8e53L7WudjT2s34wufT38fp0MXPoteo?=
=?GBK?B?sai1xLTwuLQoz8K6vszBMbrFKS5kb2M=?=
– 是 MIME编码词.一般形式为:
=?<字符集>?<传输编码>?<编码文本>?=
你说的没错,字符集是 GBK,但你必须先解开传输编码,用于B
Base64 或Q
Quoted-Printable,以获取实际的 GBK 编码字节:
>>> base64.b64decode("sai1xLTwuLQoz8K6vszBMbrFKS5kb2M=").decode("GBK")
'报的答复(下壕塘1号).doc'
然而,email.header.decode_header()
可以更好地处理这个问题:
>>> x = email.header.decode_header("=?GBK?B?1cK5s<...>brFKS5kb2M=?=")
>>> x
[(b'\xd5\xc2\xb9\xb1<...>\xc11\xba\xc5).doc', 'gbk')]
>>> x[0][0].decode(x[0][1])
'章贡区城管局关于网络舆情信息专报的答复(下壕塘1号).doc'
第一个结果的结构是这样的,因为单个标题可能有多个组件,即不同的编码或混合的原始文本和编码词。Python 模块让您自行 join() 结果:
def decode_header(enc):
dec = email.header.decode_header(enc)
dec = [f[0].decode(f[1] or "us-ascii") for f in dec]
return "".join(dec)
类似地,在 Perl 中,它Encode::decode()
也可以使用MIME-Header
编码来处理这个问题:
$ perl -E 'use open qw(:std :utf8);
use Encode;
say Encode::decode("MIME-Header", "=?GBK?B?1cK5scf<...>brFKS5kb2M=?=");'
章贡区城管局关于网络舆情信息专报的答复(下壕塘1号).doc
(另外,主体不是 uuencoded 的,而是Base64-编码。它们使用不同的字符集,尽管两者都是 3:4 编码,并且uudecode
通常足够智能,可以检测原始 Base64。)