[MIME] 解碼電子郵件 (MIME) 中的 encoded word
最近專案要處理 MIME 中的 encoded word~
什麼是 encoded word 呢?
就是將一串文字編碼起來,通常用在 email 裡面,
確保編碼後的文字是在 ASCII 範圍內,
這樣子傳送郵件時,就算裡面有 MBCS (Multi-byte character sequence),也不會因此出錯~
舉例來說,這是將一封 email 裡的內容節錄出來,
可以看到裡面有像是 =?gb2312?B?…=?= 這樣的內容,這就是 encoded word:
--_004_61102C6947C2AE4394997F2AE9EAECAB10A586F2F9mail2dragonje_ Content-Type: application/vnd.ms-excel; name="=?gb2312?B?hWbBpo9TyczVe7Lpse0xLi54bHM=?=" Content-Description: =?gb2312?B?hWbBpo9TyczVe7Lpse0xLi54bHM=?= Content-Disposition: attachment; filename="=?gb2312?B?hWbBpo9TyczVe7Lpse0xLi54bHM=?="; size=33280; creation-date="Tue, 01 Mar 2011 14:08:26 GMT"; modification-date="Sat, 28 Apr 2012 15:39:03 GMT" Content-Transfer-Encoding: base64
看到這種 encoded word 的時候,要如何解碼呢?
它的格式是 =? (語言編碼) ? (B|Q) ? (以 Base64 或 Quoted-printable 編碼後字串) ?=,
因此像 =?gb2312?B?hWbBpo9TyczVe7Lpse0xLi54bHM=?= 這串的話,
先用 base64 將 hWbBpo9TyczVe7Lpse0xLi54bHM= 解碼,
出來的字串就是 gb2312 編碼後的字串。
這時可以再用 gb2312 反解回 Unicode,例如:
>>> "hWbBpo9TyczVe7Lpse0xLi54bHM=".decode("base64") '\x85f\xc1\xa6\x8fS\xc9\xcc\xd5{\xb2\xe9\xb1\xed1..xls' >>> "hWbBpo9TyczVe7Lpse0xLi54bHM=".decode("base64").decode("gb2312") Traceback (most recent call last): File "", line 1, in UnicodeDecodeError: 'gb2312' codec can't decode bytes in position 0-1: illegal multibyte sequence
咦,明明是 gb2312 編碼的字串,為什麼不能反解成功呢?
研究了一下,如果用 gbk 是可以解碼成 Unicode 的:
>>> "hWbBpo9TyczVe7Lpse0xLi54bHM=".decode("base64").decode("gbk") u'\u5354\u529b\u5ee0\u5546\u8abf\u67e5\u88681..xls'
查了一下,gbk 是 gb2312 的超集合 (superset),
所以可能是原始字串事實上用到了 gbk 裡定義的字元,
但 encoded word 裡卻只寫了 gb2312 這個編碼,因此無法反解成功…
把這 Unicode 印出來,就可以看到它原本的字串了
(看起來是正體中文,難怪 gb2312 看不懂…
gbk 包含了正體和簡體中文字,所以是可以成功的):
>>> print u'\u5354\u529b\u5ee0\u5546\u8abf\u67e5\u88681..xls'.encode("utf-8") 協力廠商調查表1..xls
網路上已經有高手寫了個網頁 Online MIME Headers Decoder (RFC 2047),
把 MIME 的內容貼上去,就可以直接幫你反解,
而且剛剛說的 gb2312->gbk 的問題,它似乎也有做,所以可以成功解開:
如果你的程式也需要處理 encoded word 的話,
建議可以拿這網站的結果,來做對照囉~