min117の日記

初期desireもち。趣味Mac,メインFedora,仕事xp。

vmg2eml2jpg 二つ折りケータイのメールvmgをeml形式に変換したのをjpgにしてAmazonPhotosに永久保存する

メールバックアップファイル.emlファイルから本文と画像を取り出す

とりあえずできた。

$ python3 eml2jpg.py

現時点の機能

・メールの本文が表示され、画像に焼かれてjpgとして保存される。

・添付画像があれば↑の2ページ目として連結されて画像になる(AmazonPhotosに容量無制限で保存できる)

・添付画像自体も1枚の画像として保存される。

$ python3 /hoge/fuga/eml2.jpg.py /foo/bar/test.eml

とした場合には、test.emlに含まれる画像は/hoge/fuga/test.jpgとして保存される(スクリプトと同じ場所に保存される)。/foo/barには保存されないので、ソースemlの入っているディレクトリを汚さない。

 

このあとやりたいこと

・添付ファイルが画像じゃない場合にも対応

・本文のテキストは.txtファイルにも落とす

 

###  python3 -m pip install email-parser pillow
### (pip install email-parser pillow)

import sys
import os
import email
from email.header import decode_header
#import base64
from PIL import Image, ImageDraw, ImageFont
import chardet


def decode_header_part(header_part):
    fragments = decode_header(header_part)
    decoded_parts =
    for fragment, encoding in fragments:
        if isinstance(fragment, bytes):
            decoded_parts.append(fragment.decode(encoding or "ASCII", errors="replace"))
        else:
            decoded_parts.append(fragment)
    return "".join(decoded_parts)


def decode_body(part):
    payload = part.get_payload(decode=True)
    charset = part.get_content_charset()

    if charset is None:
        detected = chardet.detect(payload)
        charset = detected['encoding']

    #OKK return payload.decode(charset, errors="replace")

    # ISO-2022-JP エンコーディングに対応するために適切なデコード処理
    try:
        return payload.decode(charset, errors="replace")
    except (UnicodeDecodeError, TypeError):
        return payload.decode('iso-2022-jp', errors="replace")

 


def eml_to_jpg(eml_file):

    # スクリプトのディレクトリを取得
    script_dir = os.path.dirname(os.path.abspath(__file__))
    eml_filename = os.path.splitext(os.path.basename(eml_file))[0]


    # EMLファイルの読み込み ("rb"でバイナリモード)
    with open(eml_file, "rb") as file:
        msg = email.message_from_bytes(file.read())

    # メール情報の抽出
    subject = decode_header_part(msg.get("Subject", "No Subject"))
    from_ = decode_header_part(msg.get("From", "Unknown Sender"))
    to_ = decode_header_part(msg.get("To", "Unknown Recipient"))
    date_ = decode_header_part(msg.get("Date", "No Date"))


# メール本文の抽出
    body = ""

    for part in msg.walk():
        if part.get_content_maintype() == "multipart":
            continue
        if part.get_filename() is None:
            if body == "":
                body = decode_body(part)
        else:
            filename = decode_header_part(part.get_filename())
            new_filename2 = f"{eml_filename}_{filename}"
            with open(new_filename2, "wb") as f:
                f.write(part.get_payload(decode=True))
            print(f"Attachment saved as {new_filename2}")
            #attachments.append(new_filename2)
    print('###########')
    print('添付ファイルattachments')
    #print(attachments)
    print('###########')
    print('body')
    print(body)
    print('###########')
    print('new_filename2')
    print(new_filename2)
    print('###########')

 

#OKK    for part in msg.walk():
#OKK        if part.get_content_maintype() == "multipart":
#OKK            continue
#OKK        if part.get_filename() is None:
#OKK            body = decode_body(part)
#OKK            #OKK charset = part.get_content_charset()
#OKK            #OKK if charset:
#OKK            #OKK     body = part.get_payload(decode=True).decode(charset, errors="replace")
#OKK            #OKK else:
#OKK            #OKK     body = part.get_payload(decode=True)
#OKK
#OKK        else:
#OKK            # 添付ファイルを保存
#OKK            #filename = decode_header_part(part.get_filename())
#OKK            # 添付ファイルを保存 (EMLファイル名を付加)
#OKK            filename = decode_header_part(part.get_filename())
#OKK            new_filename = f"{eml_filename}_{filename}"
#OKK            with open(new_filename, "wb") as f:
#OKK                f.write(part.get_payload(decode=True))
#OKK            #print(f"Attachment saved as {filename}")
#OKK            print(f"Attachment saved as {new_filename}")
#OKK    print('----------')
#OKK    print(body)
#OKK    print('----------')
#OKK    print(new_filename)
#OKK    print('----------')

    # 画像の作成
    #OKK width, height = 800, 1200
    #OKK image = Image.new('RGB', (width, height), color=(255, 255, 255))
    #OKK draw = ImageDraw.Draw(image)

    # 保存する画像サイズの設定
    width, height = 800, 1600
    body_image = Image.new('RGB', (width, height), color=(255, 255, 255))
    draw = ImageDraw.Draw(body_image)

    # # フォントとサイズ設定
    # font = ImageFont.load_default()

    # https://www.higashisalary.com/entry/python-pic-add-string
    #myIMG = cv2.imread(myJPYUSD)
    #font_path='/usr/share/fonts/ipa-gothic/ipag.ttf'
    #font_path='/usr/share/fonts/google-noto-serif-cjk-vf-fonts/NotoColorEmoji.ttf'
    #OKK font_path='/usr/share/fonts/google-noto-serif-cjk-vf-fonts/NotoSansCJK-VF.ttc'
    font_path='/usr/share/fonts/google-noto-serif-cjk-vf-fonts/NotoSerifCJK-VF.ttc'

    # フォントの設定
    try:
        # カスタムフォントを指定する (例: Noto Sans CJK)
        # font = ImageFont.truetype("/path/to/NotoSansCJK-Regular.ttc", size=24)
        font = ImageFont.truetype(font_path, size=24)
    except IOError:
        # フォントファイルが見つからない場合はデフォルトフォントを使用
        font = ImageFont.load_default()

    # テキストを画像に描画
    #OKK draw.text((10, 10), body, font=font, fill=(0, 0, 0))
    y_text = 10
    draw.text((10, y_text), f"Subject: {subject}", font=font, fill=(0, 0, 0))
    y_text += 30
    draw.text((10, y_text), f"From: {from_}", font=font, fill=(0, 0, 0))
    y_text += 30
    draw.text((10, y_text), f"To: {to_}", font=font, fill=(0, 0, 0))
    y_text += 30
    draw.text((10, y_text), f"Date: {date_}", font=font, fill=(0, 0, 0))
    y_text += 30
    draw.text((10, y_text), "Body:", font=font, fill=(0, 0, 0))
    y_text += 30
    draw.text((10, y_text), body, font=font, fill=(0, 0, 0))


    # 添付ファイルを保存し、2ページ目の画像を作成
    # attachments =
# 添付ファイルの画像を結合
    attachments = [os.path.join(script_dir, f"{eml_filename}_{decode_header_part(part.get_filename())}") for part in msg.walk() if part.get_content_maintype() != "multipart" and part.get_filename() is not None]
        

# 添付ファイルの画像を結合
    if attachments:
        attachment_images = [Image.open(att) for att in attachments]
        attachment_width, attachment_height = attachment_images[0].size
        total_height = sum(img.height for img in attachment_images)
        attachments_image = Image.new('RGB', (attachment_width, total_height), color=(255, 255, 255))

        y_offset = 0
        for img in attachment_images:
            attachments_image.paste(img, (0, y_offset))
            y_offset += img.height

        # 画像ファイル名の生成
        body_image_filename = f"{eml_filename}_body.jpg"
        #attachments_image_filename = f"{eml_filename}_attachments.jpg"
        attachments_image_filename = os.path.join(script_dir, f"{eml_filename}_attachments.jpg")

        # 1ページ目 (メール本文) の保存
        body_image.save(body_image_filename)
        print(f"Body image saved as {body_image_filename}")

        # 2ページ目 (添付ファイル) の保存
        attachments_image.save(attachments_image_filename)
        print(f"Attachments image saved as {attachments_image_filename}")

        # 結合画像の作成
        final_width = max(body_image.width, attachments_image.width)
        final_height = body_image.height + attachments_image.height
        final_image = Image.new('RGB', (final_width, final_height), color=(255, 255, 255))
        final_image.paste(body_image, (0, 0))
        final_image.paste(attachments_image, (0, body_image.height))

        # 出力ファイル名の生成
        final_output_file = f"{eml_filename}.jpg"

        # 最終画像の保存
        final_image.save(final_output_file)
        print(f"Final image saved as {final_output_file}")

        print('----------')
        print(body)
        print('----------')
        print(new_filename2)
        print('----------')
        print(final_output_file)
        print('----------')


    else:
        for part in msg.walk():
            if part.get_content_maintype() == "multipart":
                continue
            if part.get_filename() is None:
                body = decode_body(part)
                #OKK charset = part.get_content_charset()
                #OKK if charset:
                #OKK     body = part.get_payload(decode=True).decode(charset, errors="replace")
                #OKK else:
                #OKK     body = part.get_payload(decode=True)

            else:
                # 添付ファイルを保存
                #filename = decode_header_part(part.get_filename())
                # 添付ファイルを保存 (EMLファイル名を付加)
                filename = decode_header_part(part.get_filename())
                new_filename = f"{eml_filename}_{filename}"
                with open(new_filename, "wb") as f:
                    f.write(part.get_payload(decode=True))
                #print(f"Attachment saved as {filename}")
                print(f"Attachment saved as {new_filename}")
                # 出力ファイル名の生成
                output_file = f"{os.path.splitext(eml_file)[0]}.jpg"

                # 画像の保存
                image.save(output_file)
                print(f"Image saved as {output_file}")
        print('==========')
        print(body)
        print('==========')
        print(new_filename)
        print('==========')

 


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python3 vmg2eml2jpg.py <eml_file>")
        sys.exit(1)

    eml_file = sys.argv[1]
    eml_to_jpg(eml_file)

 

 

#OKK # "rb"でバイナリファイル読み込み
#OKK # email_file = open("読み込みたいemlファイルのパス", "rb")
#OKK email_file = open("./08060500_00018_test.eml", "rb")
#OKK msg = email.message_from_bytes(email_file.read())
#OKK 
#OKK # ヘッダーから情報を取得する
#OKK for fragment, encoding in email.header.decode_header(msg.get("From")):
#OKK     if type(fragment) is bytes:
#OKK         if encoding:
#OKK             print(fragment.decode(encoding)) 
#OKK         else:
#OKK             print(fragment.decode("ASCII"))
#OKK     elif type(fragment) is str:
#OKK         print(fragment)
#OKK 
#OKK # 本文を取得する
#OKK for part in msg.walk():
#OKK     if part.get_content_maintype() == "multipart":
#OKK         continue
#OKK     if part.get_filename() is None:
#OKK         charset = str(part.get_content_charset())
#OKK         if charset:
#OKK             body = part.get_payload(decode=True).decode(charset, errors="replace")
#OKK         else:
#OKK             body = part.get_payload(decode=True)
#OKK 
#OKK print(body)

 


# def decode_payload(part):
#     # デコードが必要な場合、Base64デコードを実行
#     payload = part.get_payload(decode=True)
#     content_transfer_encoding = part.get("Content-Transfer-Encoding")

#     print('----------')
#     print(content_transfer_encoding)

#     if content_transfer_encoding == "base64":
#         payload = base64.b64decode(payload)

#     charset = part.get_content_charset() or "utf-8"
#     return payload.decode(charset, errors="replace")

# def eml_to_jpg(eml_file):
#     # EMLファイルの読み込み
#     with open(eml_file, 'r') as file:
#         msg = email.message_from_file(file)

#     # メール本文の抽出
#     body = ""
#     if msg.is_multipart():
#         for part in msg.walk():
#             if part.get_content_type() == 'text/plain':
#                 # body = part.get_payload(decode=True).decode(part.get_content_charset(), errors="replace")
#                 body = decode_payload(msg)
#                 break
#     else:
#         #body = msg.get_payload(decode=True).decode(msg.get_content_charset(), errors="replace")
#         body = decode_payload(msg)

#     print('----------')        
#     print(body)
#     print('----------')        

#     # 画像の作成
#     width, height = 800, 1200
#     image = Image.new('RGB', (width, height), color=(255, 255, 255))
#     draw = ImageDraw.Draw(image)

#     # フォントとサイズ設定
#     font = ImageFont.load_default()

#     # テキストを画像に描画
#     draw.text*1

#     # 出力ファイル名の生成
#     output_file = f"{os.path.splitext(eml_file)[0]}.jpg"

#     # 画像の保存
#     image.save(output_file)
#     print(f"Image saved as {output_file}")

# if __name__ == "__main__":
#     if len(sys.argv) != 2:
#         print("Usage: python3 vmg2eml2jpg.py <eml_file>")
#         sys.exit(1)

#     eml_file = sys.argv[1]
#     eml_to_jpg(eml_file)

 

###############
# vmgtoemail.sh
###############
## #!/bin/bash
## 
## #   vmg-textConverter   ver1.0
## 
## # 携帯電話のvmgメールファイルを一つのテキストファイルに変換するスクリプトです。
## # 探したいメールがすぐ見つかる代わりに、添付ファイルは正常に読み込めません
## # *生成されたテキストファイルは高度なエディターだと読めない可能性があります。
## # *絵文字には非対応
## 
## #                         Written by takapocchi
## 
## echo "vmgファイルの場所を絶対パスで入力してください。"
## echo "(例:/home/hogehoge/cellphone.vmg)"
## read -p "> " FILE
## 
## echo "出力先のテキストファイルの名前を決めてください。"
## echo "現在の作業ディレクトリ $PWD の中に新しく生成されます"
## echo "(既存のファイル名は避けてください)"
## read -p "> " COMPLETE
## 
## #新規作業ディレクトリを作成、移動
## mkdir ./.mailertemp    
## cd ./.mailertemp
## 
## echo "しばらくお待ち下さい..."
## 
## #改行コードをwindows(CR+LF)からunix(LF)に変換
## cp $FILE WINCODE
## tr -d '\r' <WINCODE > UNIXCODE
## 
## NUMBER=0
## FLAG=0
## 
## while read LINE
## do
##     if [ "${LINE}" = "END:VBODY" ]
##         then    FLAG=0
##     elif [ "${LINE}" = "BEGIN:VBODY" ]
##         then    NUMBER=`expr ${NUMBER} + 1`
##             FLAG=1
##             echo "" >> "${COMPLETE}"
##             echo "===========================" >> "${COMPLETE}"
##     elif [ "${LINE}" = "" ]
##         then    FLAG=2
##     elif [ ${FLAG} = 0 ]
##         then    :
##     elif [ ${FLAG} = 1 ]
##         then    echo ${LINE} >> "${COMPLETE}"
##     elif [ ${FLAG} = 2 ]
##         then    echo ${LINE} | base64 -d | iconv -f SHIFT-JIS -t UTF-8 >> "${COMPLETE}"
##     else    :
##     fi
## done < UNIXCODE
## 
## #後片付け
## rm WINCODE UNIXCODE
## mv ${COMPLETE} ../
## cd ../;rm ./.mailertemp

 

 

1,000万円を超えたbitcoinを少しだけどもらえるURL

https://bitflyer.com/invitation?id=l50e5ljw&lang=ja-JP

ハピタスからポイントもらえるURL

その買うを、もっとハッピーに。|ハピタス

 

*1:10, 10), body, font=font, fill=(0, 0, 0