みずりゅの自由帳

主に参加したイベントやソフトウェア技術/開発について記録しています

Python3でmbox形式のファイルからメッセージを取り出す

備忘メモ。

Python3で「mbox」形式のファイルから1つずつメール(=メッセージ)を取り出すのに利用した方法。

ライブラリ「mailbox」を利用する。
https://docs.python.jp/3/library/mailbox.html

import mailbox

def read_contents(file):
    mbox = mailbox.mbox(file)
    keys = mbox.keys()
    return [(k, mbox.get_bytes(k)) for k in keys]

mbox形式のファイルパスを引数fileで指定し、mbox形式で開く。
keys()でキーを全て取得。
その後、キーを指定してmboxからメッセージをバイナリ形式で取り出している。
これで「メッセージを一意に表すキー」と「対応するメッセージのバイナリデータ」の組み合わせの配列が戻り値となる。
なお、キーは0から始まる連番である。つまり、1通目はキーが0、2通目はキーが1となる。
そのため「N通目以降から取り出したい」という場合なら、「if k >= N -1」をfor文に付与してやる。

    return [(k, mbox.get_bytes(k)) for k in keys if k >= N -1]

メールヘッダの先頭にある"From "の扱い

「mbox.get_bytes(k)」で取得した場合、メッセージの区切りである「メールヘッダの先頭にある"From "(From+半角スペース)」の行が削除されている。
「メールヘッダの先頭にある"From "」の行も欲しかったのでソースコードを確認してみると、クラス「_mboxMMDF」の場合は「def get_bytes(self, key, from_=False):」で定義されていた。なお、「_mboxMMDF」は「mailbox.mbox()」の「__init__」で設定されている。

https://github.com/python/cpython/blob/3.6/Lib/mailbox.py
https://github.com/python/cpython/blob/3.6/Lib/mailbox.py#L789
https://github.com/python/cpython/blob/3.6/Lib/mailbox.py#L835


これにならい、「mbox.get_bytes(k)」を「mbox.get_bytes(k, True)」にして実施してみたところ、「メールヘッダの先頭にある"From "」の行も取得することができた。

import mailbox

def read_contents(file):
    mbox = mailbox.mbox(file)
    keys = mbox.keys()
    return [(k, mbox.get_bytes(k, True)) for k in keys]

余談:
「mbox 固有の動作をするメッセージ」は以下に書かれてもいる。
https://docs.python.jp/3/library/mailbox.html#mailbox.mboxMessage