質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

PDF

PDF(Portable Document Format)とはISOによって国際標準として制定されている電子ドキュメント用の拡張子です。

メール

メールは、コンピュータネットワークを利用し、 情報等を交換する手段のことです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

4830閲覧

【python】.emlファイルから取得した文字列をpdfにしたい。

tsubasabest

総合スコア1

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

PDF

PDF(Portable Document Format)とはISOによって国際標準として制定されている電子ドキュメント用の拡張子です。

メール

メールは、コンピュータネットワークを利用し、 情報等を交換する手段のことです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/05/19 08:05

編集2021/05/19 08:13

質問の背景

Thunderbirdで受信したメールを"yyyymmdd_受信したメール件名"の形式でフォルダを作成し、
そのフォルダに.emlファイルやemlファイルをpdfにしたもの、添付ファイルを保存する業務があります。

"yyyymmdd_受信したメール件名"
├ メール件名.eml
├ メール件名.pdf
├ 添付ファイル1
└ 添付ファイル2

現在Pythonで上記フォルダ作成、.emlファイル・添付ファイルの保存までは動作できています。

実現したいこと

Pythonで.emlファイルからpdfを作成したいのですが、手法がわかりません。
良いアイディアがあれば教えて下さい。

該当のソースコード

Qiitaのこのページ丸パクリ参考にして下記のコードを作成しました。
結果としてprint(result)で.emlファイルの内容はすべて取得、出力されています。
(Pythonコードの下にresultの内容を記載しています。)

Python

1import sys 2import pathlib 3import email 4from email.header import decode_header 5import datetime 6import shutil 7 8 9class MailParser(object): 10 """メールファイルのパスを受け取り、それを解析するクラス""" 11 12 def __init__(self, mail_file_path): 13 self.mail_file_path = mail_file_path 14 # emlファイルからemail.message.Messageインスタンスの取得 15 with open(mail_file_path, 'rb') as email_file: 16 self.email_message = email.message_from_bytes(email_file.read()) 17 self.subject = None 18 self.to_address = None 19 self.cc_address = None 20 self.from_address = None 21 self.body = "" 22 self.date = None 23 # 添付ファイル関連の情報 24 # {name: file_name, data: data} 25 self.attach_file_list = [] 26 # emlの解釈 27 self._parse() 28 29 def get_attr_data(self): 30 """メールデータの取得""" 31 result = """\ 32DATE: {} 33FROM: {} 34SUBJECT: {} 35TO: {} 36CC: {} 37----------------------- 38BODY: 39{} 40----------------------- 41ATTACH_FILE_NAME: 42{} 43""".format( 44 self.date, 45 self.from_address, 46 self.subject, 47 self.to_address, 48 self.cc_address, 49 self.body, 50 ",".join([x["name"] for x in self.attach_file_list]) 51 ) 52 return result 53 54 def _parse(self): 55 """メールファイルの解析 56 __init__内で呼び出している""" 57 self.subject = self._get_decoded_header("Subject") 58 self.to_address = self._get_decoded_header("To") 59 self.cc_address = self._get_decoded_header("Cc") 60 self.from_address = self._get_decoded_header("From") 61 # 変更したところ 62 self.date = datetime.datetime.strptime( 63 self._get_decoded_header("Date"), 64 "%a, %d %b %Y %H:%M:%S %z" 65 ) 66 67 # メッセージ本文部分の処理 68 for part in self.email_message.walk(): 69 # ContentTypeがmultipartの場合は実際のコンテンツはさらに 70 # 中のpartにあるので読み飛ばす 71 if part.get_content_maintype() == 'multipart': 72 continue 73 # ファイル名の取得 74 attach_fname = part.get_filename() 75 # ファイル名がない場合は本文のはず 76 if not attach_fname: 77 charset = str(part.get_content_charset()) 78 if charset: 79 self.body += part.get_payload(decode=True).decode(charset, errors="replace") 80 else: 81 self.body += part.get_payload(decode=True) 82 else: 83 # ファイル名があるならそれは添付ファイルなので 84 # データを取得する 85 self.attach_file_list.append({ 86 "name": attach_fname, 87 "data": part.get_payload(decode=True) 88 }) 89 90 def _get_decoded_header(self, key_name): 91 """ヘッダーオブジェクトからデコード済の結果を取得する""" 92 ret = "" 93 94 # 該当項目がないkeyは空文字を戻す 95 raw_obj = self.email_message.get(key_name) 96 if raw_obj is None: 97 return "" 98 # デコードした結果をunicodeにする 99 for fragment, encoding in decode_header(raw_obj): 100 if not hasattr(fragment, "decode"): 101 ret += fragment 102 continue 103 # encodeがなければとりあえずUTF-8でデコードする 104 if encoding: 105 ret += fragment.decode(encoding) 106 else: 107 ret += fragment.decode("UTF-8") 108 return ret 109 110 111def make_dir(file_path): 112 """日付_件名の書式でディレクトリを作成""" 113 global dir_path, str_date, obj_eml 114 obj_eml = MailParser(file_path) 115 eml_subject = pathlib.Path(file_path).stem 116 eml_date = obj_eml.date 117# 日付 118 str_year = eml_date.strftime("%Y") 119 str_month = eml_date.strftime("%m") 120 str_day = eml_date.strftime("%d") 121 str_date = str_year + str_month + str_day 122# ディレクトリ名称 123 file_name = str_date + "_" + eml_subject 124 dir_path = pathlib.Path(r"C:\Users\namae\Desktop" + "\" + file_name) 125 dir_path.mkdir() 126 127 128def save_attach(file_path): 129 """メールファイル内より、添付ファイルを取得""" 130 global file_name 131 for attach in obj_eml.attach_file_list: 132 if type(decode_header(attach["name"])[0][0]) == bytes: 133 file_name = decode_header(attach["name"])[0][0].decode(decode_header(attach["name"])[0][1]) 134 with open(str(dir_path) + "\" + file_name, mode="bw") as f: 135 f.write(attach["data"]) 136 else: 137 file_name = decode_header(attach["name"])[0][0] 138 file_name = (file_name).translate(str.maketrans( 139 {'<': '', '>': '', '!': '', '/': '', ':': '', '*': '', '"': '', '|': ''} 140 )) 141 with open(str(dir_path) + "\" + file_name, mode="bw") as f: 142 f.write(attach["data"]) 143 144 145if __name__ == "__main__": 146 email_file = sys.argv[1] 147 make_dir(email_file) 148 shutil.copy(email_file, dir_path) 149 save_attach(dir_path) 150 result = MailParser(email_file).get_attr_data() 151 print(result) 152 input()

result

1DATE: 2021-05-19 16:34:55+09:00 2FROM: 名前 太郎<namae@hogehoge> 3SUBJECT: Re: 請求書の送付 4TO: aitenonamae@hogehoge 5CC: cctarou@hogehoge, ccjirou@hogehoge 6----------------------- 7BODY: 85億円の請求書をお送りします。 9----------------------- 10ATTACH_FILE_NAME: 11請求書.pdf

補足情報(バージョン・引用)

Python 3.8.5
Windows 10 Pro
Thunderbird 78.6.0 (32ビット)

以下引用です。参考にさてもらいました。ありがとうございます。
python3.7でThunderbirdから保存したEMLファイルのテンプレートを抜き出す
Pythonでemlファイルを扱うサンプル

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

こんばんは。

問題文読ませていただきました。

PDFへ書き換える色々なライブラリが存在しますので、どれかを選んで変換するのが良さそうですね。

<参考>
PythonでPDFを生成するライブラリ比較まとめ

投稿2021/05/19 09:33

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tsubasabest

2021/05/20 01:22

ご助言ありがとうございます。参考URLをチェックしています。 KURORO様がおすすめするプログラミング初学者向けのライブラリはあったりしますか?
退会済みユーザー

退会済みユーザー

2021/05/20 01:37

ある程度型が決まっていたり、単純にPDFだけだったら、WeasyPrintが良さそうです。 細かいところも自作したい系だったら、reportlabですかね。
tsubasabest

2021/05/20 06:05

あまりコードを煩雑にしたくないので、WeasyPrintを調べてみます! ご丁寧にありがとうございました!
退会済みユーザー

退会済みユーザー

2021/05/20 06:43

いえいえ、こちらこそ応援しております。 また困ったこととかありましたら、気軽にご相談ください!! Enjoy!!!
guest

0

出力すべきデータが全部取得できているのであれば、あとはReportLabのようなライブラリでpdf化できると思います。

投稿2021/05/19 08:23

udon-ken

総合スコア657

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tsubasabest

2021/05/20 01:21

ご助言ありがとうございます。 ちなみにですが、PDF化ライブラリでプログラミング初学者におすすめはありませんか? ReportLabを調べてみたのですが、自由度が高い反面コードがスパゲッティーになりそうでして・・・(笑)
udon-ken

2021/05/20 06:28

申し訳ありませんが、お勧めは分からないですね。 そんなに色々なライブラリを使った事がある訳ではないので。
tsubasabest

2021/05/20 07:03

回答ありがとうございました! 様々なライブラリを試してみます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問