(v_10)Python メールの受信 imaplib
imaplib
Pythonでいろいろ試してみたことを記載しています。※開発環境はThonnyを使用しています。
imaplibモジュールを使ってメールの受信を試しました。
imaplibモジュールには三つのクラス IMAP4, IMAP4_SSL と IMAP4_stream があるそうです。
IMAP4_SSLを使って記事(v_09)と同じようにメール件名と差出人を確認したいと思います。
class imaplib
imaplibの使用例です。ThonnyのShellで試しています。
初期化します。
>>> import imaplib
>>> M = imaplib.IMAP4_SSL(udat[0], port=993)
udat[0]:imapサーバー名(例:'imap.****.ne.jp'
ログインします。
>>> M.login(udat[1],udat[2])
('OK', [b'Logged in'])
※udat[1]はユーザーアカウント名(例:'abcd@****.ne.jp') udat[2]はパスワード
受信ボックスのメール数を確認します。ここでは8通あります。
>>> M.select()
('OK', [b'8'])
メールの内容を確認します。ここでは5番目です。
>>> M.fetch(b'5', '(RFC822)')
ログアウトします。
>>> M.logout()
('BYE', [b'Logging out'])
>>>
スクリプト
imaplibモジュールを使ってメール件名と差出人を確認するスクリプトは以下のようにしました。
m_imap_02b.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import imaplib
import base64
import quopri
# MIME形式を変換
def m_chn(str_msg):
#s=bytes_msg.decode() #bytes->moji
s=str_msg
sp=s.split(' ') #'_'で分離 正当なやり方だろうと思う リスト化
n=len(sp) #分離した数
bun='' #変換した文字列
ss=[] #'?='付き部分
for i in sp:
if '?=' in i: #'?='がある項だけのリストにする
ss.append(i)
else:
bun=bun + i # '?='のついていない subject:などの文字列
dat=[] #[[moji-code, encode, bytes-data],[ ]]に分離する
for j in ss:
j=j.replace('?=','') #'?='を消去
j=j.replace('=?','') #'=?'を消去 ==?はあり得るようなので後で削除
j=j.split('?') #'?'で分離
dat.append(j) # 以下のような形式になる
##print('dat=',dat) #[[moji-code, encode, bytes-moji-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] # bytes-moji-data(massage)
##print(msg)
if 'B' in ctenc.upper():
cte='base64'
b = base64.b64decode(msg) #b bytedata 文
##print('base64 decode-data',b)
elif 'Q' in ctenc.upper():
cte='quoted-printable'
msg=msg.replace(b'==',b'=')
b = quopri.decodestring(msg)
##print('quoted decode-data',b)
else:
cte='non'
b = msg
##print('non decode-data',b)
line=b.decode(chset, "ignore") #chset=dat[i][0]
#line=b.decode(chset, "replace")
bun=bun + line # つなぐ
print(bun)
return bun
# main ------
udat=[' ']*3
#udat= input("'imap server','user_account', 'Passwords'=").split(',')
#user data 個人情報を入力
udat[0]='imap.****.jp'
udat[1]='*****.ne.jp'
udat[2]='*********'
# 初期化
M = imaplib.IMAP4_SSL(udat[0], port=993)
# ログイン
M.login(udat[1],udat[2])
#m_sel=M.select('INBOX')
m_sel=M.select() # ('OK', [b'8']) mailbox 内のメッセージ数
m_num=int(m_sel[1][0].decode()) #[b'8']を数値にする
for i in range(m_num):
m=str(i+1).encode() # b'8'の形式に
print(m)
#IMAP4.fetch(message_set, message_parts)
a=M.fetch(m, '(RFC822)')
c=a[1][0][1]
d=c.decode() # 文字データにする
e=d.split('\r\n') # 改行コードで分離
m=len(e) # 分離数
#'Subject: '、'From: 'があればm_chnで文字変換して表示する
for i in range(m):
if 'Subject: ' in e[i]:
m_chn(e[i])
if 'From: ' in e[i]:
m_chn(e[i])
print('')
#ログアウト
M.logout()
部分説明
メールの内容を以下で得ます。5番目の内容を得た例です。
>>> a=M.fetch(b'5', '(RFC822)')
>>> a
>>> a[1][0][1]
以下はa[1][0][1]で得たデータの一部分を抜出して記載したものです。
記事(v_09)では行単位でしたが、改行コードの’\r\n’を含めて一括のデータになっていました。
(省略)
b'Return-Path: <information@ma.email.aeon.co.jp>\r\nDelivered-To: *****.ne.jp\r\n
(省略)
\r\nFrom: =?utf-8?B?44Kk44Kq44Oz44OV44Kj44OK44Oz44K344Oj44Or44K144O844OT44K55qCq5
byP5Lya56S+?= <information@ma.email.aeon.co.jp>\r\nSubject: =?utf-8?B?44Kk44Kq44O
z44K344ON44Oe54m55Yil6ZGR6LOe5YSq5b6F?=\r\n =?utf-?B?44Gu54m55YW444Oq44OL44Ol44O8
44Ki44Or44Gr44Gk44GE44Gm?=\r\n
(省略)
\r\nContent-Type: text/plain;\r\n\tcharset="utf-8"\r\nContent-Transfer-Encoding:
8bit\r\n\r\n\xe2\x80\xbb\xe6\x9c\xac\xe3\x83\xa1\xe3\x83\xbc\xe3\x83\xab\xe3\x81
(省略)
\x91\r\n\xe3\x80\x8c\xe3\x82\xa4\xe3\x82\xaa\xe3\x83\xb3\xe3\x82\xb7\xe3\x83\x8…
一括データのため改行コードで分離するだけよさそうです。split(‘\r\n’)で区切って分離します。
その後の処理は記事(v_09)とほぼ同様です。
‘Subject: ‘、’From: ‘の含んだデータをm_chn(str_msg)でデコードします。
str_msgは文字データです。
m_chn(str_msg)については記事(v_08)を参照ください。ほぼ同じです。
実行結果
実行結果は以下のようになりました。
受信メールの件数は6件です。各件名と差出人が表示されています。
1件目(b’1’)には’Subject: ‘、’From: ‘が複数あったようで不要部が表示されていますが、各件名と差出人が表示されています。
まとめ
imaplibモジュールを使って、メール件名と差出人のリストを表示することができました。