メールバックアップファイル.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