使用Python的email模块解析shift_jis编码的邮件时出错

1 投票
1 回答
1384 浏览
提问于 2025-04-16 14:50

我在使用我的邮件解析器解码一个用 shift_jis 编码的邮件并转换成 Unicode 时,遇到了一个错误,提示“UnicodeDecodeError: 'shift_jis' codec can't decode bytes in position 2-3: illegal multibyte sequence”。下面是相关的代码和邮件内容:

import email.header
import base64
import sys
import email

def getrawemail():
    line = ' '
    raw_email = ''
    while line:
        line = sys.stdin.readline()
        raw_email += line
    return raw_email

def getheader(subject, charsets):
    for i in charsets:
        if isinstance(i, str):
            encoding = i
            break
    if subject[-2] == "?=":
        encoded = subject[5 + len(encoding):len(subject) - 2]
    else:
        encoded = subject[5 + len(encoding):]
    return (encoding, encoded)

def decodeheader((encoding, encoded)):
    decoded = base64.b64decode(encoded)
    decoded = unicode(decoded, encoding)
    return decoded

raw_email = getrawemail()
msg = email.message_from_string(raw_email)
subject = decodeheader(getheader(msg["Subject"], msg.get_charsets()))
print subject

邮件链接:http://pastebin.com/L4jAkm5R

我在另一个 Stack Overflow 的问题中看到,这可能和 Unicode 和 shift_jis 的编码方式不同有关(他们提到了一篇微软知识库的文章)。如果有人知道我的代码中可能是什么原因导致它无法正常工作,或者这个问题是否有合理的解决办法,我将非常感激能得到帮助。

1 个回答

1

从这个字符串开始:

In [124]: msg['Subject']
Out[124]: '=?ISO-2022-JP?B?GyRCNS5KfSRLJEgkRiRiQmdAWiRKJCpDTiRpJDskLCQiJGo'

=?ISO-2022-JP?B? 表示这个字符串是用 ISO-2022-JP 编码的,然后又进行了 base64 编码。

In [125]: msg['Subject'].lstrip('=?ISO-2022-JP?B?')
Out[125]: 'GyRCNS5KfSRLJEgkRiRiQmdAWiRKJCpDTiRpJDskLCQiJGo'

不幸的是,试图逆向这个过程会导致错误:

In [126]: base64.b64decode(msg['Subject'].lstrip('=?ISO-2022-JP?B?'))
TypeError: Incorrect padding

阅读了这个 SO 的回答 后,我尝试在字符串的末尾加上 '?=':

In [130]: print(base64.b64decode(msg['Subject'].lstrip('=?ISO-2022-JP?B?')+'?=').decode('ISO-2022-JP'))
貴方にとても大切なお知らせがあり

根据谷歌翻译,这可能被翻译为“你知道有一个非常重要的”。

所以看起来这个主题行被截断了。

撰写回答