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

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

新規登録して質問してみよう
ただいま回答率
85.49%
Gmail

GmailとはGoogleによって提供されているウェブメールのサービスのことです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

メール

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

Q&A

解決済

2回答

6069閲覧

PythonでContent-Transfer-Encoding: quoted-printableのメールを受信する方法

sandalwalk

総合スコア77

Gmail

GmailとはGoogleによって提供されているウェブメールのサービスのことです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

メール

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

0グッド

0クリップ

投稿2018/09/28 06:04

Python3.6でgmailを受信&表示するプログラムを書いています。
ヘッダー情報で、
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: base64
となっているメールは以下のコードで解読できるのですが、ヘッダー情報が
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
のメールが読み込まれるとエラーが出てしまいます。
どうすれば、両者とも解読&表示することができるのでしょうか。

import imaplib import email import base64 gmail = imaplib.IMAP4_SSL("imap.gmail.com") gmail.login(“mymail@gmail.com”,”my password”) gmail.select('INBOX',readonly=True) typ, [data] = gmail.search(None,'(UNSEEN)') for num in data.split(): count+=1 result, d = gmail.fetch(num,"(RFC822)") raw_email = d[0][1] msg = email.message_from_string(raw_email.decode('iso-2022-jp')) msg_encoding = email.header.decode_header(msg.get('Subject'))[0][1] or 'iso-2022-jp' #本文の取得 body = "" if msg.is_multipart(): for payload in msg.get_payload(): if payload.get_content_type() == "text/plain": body = payload.get_payload() if msg_encoding == 'utf-8': body = base64.urlsafe_b64decode(body.encode('ASCII')).decode("utf-8") else: if msg.get_content_type() == "text/plain": body = msg.get_payload() if msg_encoding == 'utf-8': body = base64.urlsafe_b64decode(body.encode('ASCII')).decode("utf-8") print(body) print('') gmail.close() gmail.logout()

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

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

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

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

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

guest

回答2

0

opyonさんのやり方でいけると思います。
cteの決め方は以下はどうでしょう。

Python

1msg_subject = msg.get('Subject').lower() 2 3if b"?b?" in msg_subject: 4 cte = "base64" 5elif b"?q?" in msg_subject: 6 cte = "quoted-printable" 7else: 8 cte = "ascii"

投稿2018/09/28 08:42

takey

総合スコア312

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

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

sandalwalk

2018/09/29 02:24 編集

私のコード(ネット上の情報を参考に作成)もそうなのですが、本文のエンコード方式を知りたいのに、'Subject'に見に行くのはどうしてなのでしょうか?メールのヘッダーを見ると(下に例)、CTEはSubjectとは別の場所に書かれている様に思えて理解できていません。Content-Transfer-Encodingヘッダーを直接見に行く方法があれば教えて頂けますでしょうか。 Subject: こんばんは~ Cc: cc@example.com In-Reply-To: <CAA3QdPUTTwPuefb40LKXitkx=6N9D80-U1p3_jpe49Jzt5awxw@example.com> References: <20140620193439.7CBF.78EEE63C@example.com> <CAAwPuefb40LKX3QdPUTTitkx=6N9D80-U1p3_jpe49Jazt5wxw@example.com> Message-Id: <20140701162135.7CBF.9BE9E63C@example.com> MIME-Version: 1.0 Content-Type: text/plain; charset="ISO-2022-JP" Content-Transfer-Encoding: 7bit
takey

2018/09/29 02:26

本文とSubjectは同じエンコード方式でエンコーディングされているとは限りません。 ですので、本文のエンコード方式を知りたいときはContent-Typeヘッダのcharsetと、Content-Transfer-Encodingヘッダを確認します。 Subjectのエンコード方式を知りたいときは、Subjectを解析します。 例えば、 b"Subject: =?UTF-8?Q?=E3=80=90=E3=83=A4=E3=..." とあれば、charsetはUTF-8で、「?Q?」がquoted-printable変換を意味しています。
sandalwalk

2018/09/30 02:11

いろいろなメールで試してみましたが、'Subject'のCTEはご指摘の方法で取得ができそうです。本文のCTEについては、実際のメール(少なくとも私に来るもの)の多くがマルチパートのメールで、その場合にはヘッダーだけを見て、cte = msg.get('Content-Transfer-Encoding')として、一発変換することはできない様です。このコードをマルチパートメールで使うと、本文中に書かれているcharsetとContent-Transfer-Encoding部分の情報とは異なる結果が得られてしまいます。
takey

2018/09/30 05:25

マルチパートの場合、パートごとにContent-TypeとContent-Transfer-Encodingが設定されていると思いますので、それぞれの場合でcteをセットし、そのパートをデコードするという処理になると思います。
guest

0

ベストアンサー

検索しただけですがコードや解説見る限りお決まりの定型処理で出来るようですよ。

メールのデコード処理の流れ

-以下引用-
メール本文のデコード処理の流れ
受信したメールのメッセージには、Content-Transfer-EncodingヘッダとContent-typeヘッダが記載されています。
デコード処理の流れとしては、まずContent-Transfer-Encodingヘッダを見てデコードし、次にContent-typeヘッダのcharsetを見て更にデコードします。

python

1def decode_msg(msg, cte, charset): 2 """ メール本文をデコードする 3 * msg 4 - メール本文(バイナリ形式) 5 * cte(Content-Transfer-Encoding) 6 - "base64" 7 - "quoted-printable" 8 - それ以外は、そのまま 9 * charset(文字コード) 10 - "utf-8" 11 - "iso-2022-jp" 12 - それ以外は、"ascii"とみなす 13 """ 14 import quopri 15 import base64 16 17 if cte == "base64": 18 b = base64.b64decode(msg) 19 elif cte == "quoted-printable": 20 b = quopri.decodestring(msg, header=False) 21 else: 22 b = msg 23 if charset == "iso-2022-jp": 24 return b.decode("iso-2022-jp", "ignore") 25 elif charset == "utf-8": 26 return b.decode("utf-8", "ignore") 27 else: 28 return b.decode("ascii", "ignore")

投稿2018/09/28 07:22

opyon

総合スコア1009

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問