Open1

IMAPでメールサーバー上のフォルダ名を取得する

m10k1m10k1

IMAP modified UTF-7とは?

IMAPプロトコルでは、
日本語や記号を含むフォルダ名
を「IMAP modified UTF-7」という特殊なエンコーディングで表現します。

例:
&ZeVnLIqe-
という文字列は「受信箱」などの日本語フォルダ名を表します。

フォルダ名をデコードするには

"&"で始まり"-"で終わる部分がIMAP modified UTF-7のコンコード部分。
その中身はBase64でエンコードされたUTF-16BEのデータ。ただし、"/"が","に置き換わっている。

import imaplib
import subprocess
import re
import base64

def decode_imap_utf7(s):
    """IMAP modified UTF-7をデコードする(パッケージ不要)"""
    if isinstance(s, bytes):
        s = s.decode('ascii')
    def repl(m):
        b = m.group(1).replace(',', '/')
        # base64でデコードするには対象が4文字以上必要、
        # '==='を末尾に追加してパディングしておく
        # オーバーした分は無視される。
        return base64.b64decode(b + '===').decode('utf-16-be')
    return re.sub(r'&([A-Za-z0-9+,]+)-', repl, s).replace('&-', '&')


if __name__ == '__main__':
    mail = imaplib.IMAP4_SSL('your_mail_server')
    mail.login('username', 'password')

    status, folders = mail.list()

    if status == 'OK':
        for folder in folders:
            parts = folder.decode().split(' "/" ')
            if len(parts) == 2:
                folder_name = parts[1].strip('"')
                print(f"フォルダー名: {decode_imap_utf7(folder_name)}")
            else:
                print(folder)
    else:
        print('フォルダー一覧の取得に失敗しました。')
    
    mail.logout()