(v_08)Python MIME形式のメール件名
MIME
Pythonでいろいろやって見たことを記載しています。※開発環境はThonnyを使用しています。
MIMEエンコードされたメール件名(Subject)のデータをデコードして見ようと思います。
記事(v07)でpopLibを使って受信メールのデータを得ることはできましたが、可読できない部分がありました。
ここでは、MIMEエンコードされたメール件名(subject)を可読できるようにデコードしたいと思います。
MIMEエンコードは
=?<文字コード>?<エンコード方式>?<エンコードされた内容>?=
の形式で記載されています。
そのため「内容(データ)」を「エンコードの方式」でデコードして、「文字コード」でデコードすれば可読できる文字列になりそうです。
文字列の分離
MIMEエンコードの例文として以下を使います。
b’Subject: =?utf-8?B?44Kk44Kq44Oz44K344ON44Oe54m55Yil6ZGR6LOe5YSq5b6F?=’
s='Subject: =?utf-8?B?44Kk44Kq44Oz44K344ON44Oe54m55Yil6ZGR6LOe5YSq5b6F?='
たぶん、もっと良い方法があると思いますが..。
[文字コード, エンコード方式, エンコードされた内容] になるように分離して行きます。
空白文字で分離 | split(' ')
['Subject:', '=?utf-8?B?44Kk44Kq44Oz44K344ON44Oe54m55Yil6ZGR6LOe5YSq5b6F?=']
'?='のある項だけにする | '?=' in
['=?utf-8?B?44Kk44Kq44Oz44K344ON44Oe54m55Yil6ZGR6LOe5YSq5b6F?=']
'?='を消去 | replace('?=','')
'=?utf-8?B?44Kk44Kq44Oz44K344ON44Oe54m55Yil6ZGR6LOe5YSq5b6F'
#'=?'を消去 | replace('=?','')
'utf-8?B?44Kk44Kq44Oz44K344ON44Oe54m55Yil6ZGR6LOe5YSq5b6F'
'?'で分離 | split('?')
['utf-8', 'B', '44Kk44Kq44Oz44K344ON44Oe54m55Yil6ZGR6LOe5YSq5b6F']
これで、[文字コード, エンコード方式, エンコードされた内容]になりました。
文字列のデコード
エンコード方式’B’ならbase64、’Q’ならquoted-printableだそうです。
可読できる文字列に変換する手順は「エンコードされた内容」を「エンコード方式」でデコード、その値を「文字コード」でデコードします。
msg=’44Kk44Kq44Oz44K344ON44Oe54m55Yil6ZGR6LOe5YSq5b6F’としてThonnyのShellで確認してみます。
エンコード方式’B’ならbase64なのでbase64モジュールをインポートします。
>>> import base64
>>> msg='44Kk44Kq44Oz44K344ON44Oe54m55Yil6ZGR6LOe5YSq5b6F'
>>> s=base64.b64decode(msg)
>>> s # base64デコードした値
b'\xe3\x82\xa4\xe3\x82\xaa\xe3\x83\xb3\xe3\x82\xb7\xe3\x83\x8d\xe3\x83\x9e
\xe7\x89\xb9\xe5\x88\xa5\xe9\x91\x91\xe8\xb3\x9e\xe5\x84\xaa\xe5\xbe\x85'
>>> s.decode('utf-8')
'イオンシネマ特別鑑賞優待'
>>>
’44Kk44Kq44Oz44K344ON44Oe54m55Yil6ZGR6LOe5YSq5b6F’の文字列は’イオンシネマ特別鑑賞優待’になりました。
スクリプト
以下のスクリプトはエンコード方式が’Q’のquoted-printableの場合も加えて一連の処理を記載しています。
mime_subject_01b.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import base64
import quopri
# 例文
bytes_msg=b'Subject: =?utf-8?B?44Kk44Kq44Oz44K344ON44Oe54m55Yil6ZGR6LOe5YSq5b6F?='
s=bytes_msg.decode() #bytes->moji
sp=s.split(' ') #'_'で分離 正当なやり方だろうと思う リスト化
bun='' #変換した文字列
n=len(sp) #分離した数
ss=[] #MIME [moji-code, encode, moji-data]
for i in sp:
if '?=' in i: #'?='がある項だけのリストにする
ss.append(i)
else:
bun=bun + i # subject:など'?='がない文字列
dat=[]
for j in ss:
j=j.replace('?=','') #'?='を消去
j=j.replace('=?','') #'=?'を消去 ==?はあり得るようなので'?='削除後に削除
j=j.split('?') #'?'で分離
dat.append(j) #[[moji-code, encode, moji-data],[ b'data-- ]]の形式になる
k=len(dat)
for i in range(k):
#charset(文字コード)
chset=dat[i][0] # charset utf-8, iso-2022-jp, ascii
#Content-Transfer-Encoding
ctenc=dat[i][1] # moji-encode base64, quoted-printable non
msg=dat[i][2] # massage bytes-moji-data
if 'B' in ctenc.upper():
cte='base64'
b = base64.b64decode(msg) #b bytedata
elif 'Q' in ctenc.upper():
cte='quoted-printable'
b = quopri.decodestring(msg)
else:
cte='non'
b = msg
line=b.decode(chset, "ignore")
bun=bun + line # つなぐ
print(bun)
実行結果
実行した結果例です。※Thonnyのshellに表示されます。
b’Subject: =?utf-8?B?44Kk44Kq44Oz44K344ON44Oe54m55Yil6ZGR6LOe5YSq5b6F?=’は
「Subject:イオンシネマ特別鑑賞優待」になりました。
>>> %Run mime_subject_01b.py
Subject:イオンシネマ特別鑑賞優待
>>>
まとめ
MIMEエンコードされたメール件名(Subject)をデコードして可読することができました。