稼働中

(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.fetch
>>>

ログアウトします。


>>> 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

M.fetch
内容は以下で得られます。


>>> a[1][0][1]

M.fetch内容

以下は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: ‘が複数あったようで不要部が表示されていますが、各件名と差出人が表示されています。
件名とFrom

まとめ

imaplibモジュールを使って、メール件名と差出人のリストを表示することができました。