Quoted-Printable をデコードする方法
- ツール上部の Quoted-printable → テキスト をクリックして、デコード方向に切り替えます。
- メールのソースからコピーした本文パートなど、エンコードされたテキストを入力欄に貼り付けます。
- 出力欄のテキストを確認します。アクセント付きの文字がおかしい場合は、出力欄の下の 文字コード を、そのパートの
Content-Typeヘッダーにある文字コード(charset=iso-8859-1など)に合わせてください。 - 出力をコピー または ダウンロード します。ソフト改行はつなげられ、
=XXはすべて元のバイトに戻ります。
エンコードするときは、方向を テキスト → Quoted-printable のままにしてテキストを入力するか貼り付けます。非 ASCII 文字をどのバイト列にするかは、入力欄の下の 文字コード で決まります。
Quoted-Printable の仕組み
Quoted-Printable(RFC 2045 の 6.7 節)は、読めるところはそのまま残し、必要な部分だけをエスケープします。
- 印字可能な ASCII 文字は、
=を除いてそのままです。 - それ以外のバイトは、
=と大文字の16進数 2 桁で表します。UTF-8 では、非 ASCII 文字 1 つが 2~4 個のエスケープになります。 =自体は=3Dになります。- 行末のスペースやタブは
=20や=09になります。 - 1 行は最大 76 文字です。それより長い行はソフト改行で分割されます。ソフト改行とは行末の
=のことで、デコーダーが取り除きます。
| テキスト | Quoted-Printable |
|---|---|
café | caf=C3=A9 |
Grüße aus München | Gr=C3=BC=C3=9Fe aus M=C3=BCnchen |
100% = €5 | 100% =3D =E2=82=AC5 |
<p style="color:red">Hi</p> | <p style=3D"color:red">Hi</p> |
Caf=E9 を ISO-8859-1 としてデコード | Café |
最後の行の =E9 は 1 バイトだけです。ISO-8859-1 や Windows-1252 では é ですが、UTF-8 では単独だと不正なバイトなので、結果はデコードに使う文字コードで変わります。
テキストモードとバイナリモード
エンコーダーは、デフォルトでは入力をテキストとして扱います。改行は本物の改行のまま残り、Python の binascii.b2a_qp と同じく、最初の行が CRLF で終わっていれば、後に出てくる LF 単独の改行も CRLF になります。メール本文としては正しい動作ですが、バイト列は変わります。
バイト列を正確に保ちたい場合は 改行もエンコード(バイナリ) にチェックを入れます。改行は =0D と =0A で書かれるので、Hello、CRLF、World は Hello=0D=0AWorld になり、デコードすると入力したとおりのバイト列に戻ります。もっとも、画像のような本物のバイナリデータなら Base64 のほうが適しています。
メールでは Quoted-Printable か Base64 か
メールソフトは MIME パートごとに Content-Transfer-Encoding を選びます。Quoted-Printable はほぼ ASCII のテキストに向いています。読みやすさが保たれ、サイズもあまり増えないからです。Base64 は約 33% の固定オーバーヘッドがあり、エスケープが必要なバイトが多くなるとこちらが有利になります。
| テキスト | UTF-8 のバイト数 | Quoted-Printable | Base64 |
|---|---|---|---|
Grüße aus München | 20 | 32 文字 | 28 文字 |
Привет, мир(ロシア語) | 20 | 56 文字 | 28 文字 |
17 文字中に非 ASCII 文字が 3 つだけのドイツ語でも、すでに Quoted-Printable のほうが Base64 より長くなります。キリル文字では Base64 の 2 倍です。メールで必要な 76 文字の行に折り返した Base64 を作るには MIME Base64 エンコーダー を使ってください。メールの Base64 では、添付ファイルやエンコードされたヘッダーも含め、両方のエンコードがメッセージ内でどう現れるかを解説しています。
メール全体を読む
ちょっと確認するだけなら、生のメッセージから本文パートを 1 つコピーすれば十分です。.eml ファイル全体を扱うなら、EML デコーダー がヘッダーを解析し、Quoted-Printable と Base64 のパートを宣言された文字コードでデコードし、添付ファイルをダウンロードできる形で一覧表示します。Quoted-Printable はメール以外でも使われており、たとえば ENCODING=QUOTED-PRINTABLE を含む vCard 2.1 ファイルがそうです。その場合はコロンより後ろの値をここに貼り付けてください。
コードでの Quoted-Printable
import quopri
quopri.encodestring("café".encode("utf-8")) # b'caf=C3=A9'
quopri.decodestring(b"caf=C3=A9 =3D 5=E2=82=AC").decode("utf-8") # 'café = 5€'
Python の email パッケージは適切なデコードを自動で行います。msg.get_payload(decode=True) は、転送エンコーディングが何であれ、パートのデコード済みバイト列を返します。Base64 側については Python のページを参照してください。
よくある質問
メールに出てくる =3D は何ですか?
エンコードされたイコール記号です。Quoted-Printable では = がエスケープの開始を表すので、文字どおりの = はバイト値を16進数にした =3D と書く必要があります。HTML メールでは style=3D"color:red" のような形でよく見かけます。
メールのソースで行末が = で終わっているのはなぜですか?
ソフト改行です。Quoted-Printable の 1 行は最大 76 文字なので、長い行は分割され、区切りごとに末尾へ = が付きます。デコーダーはそれらをつなげて 1 行に戻します。
行末の =20 はどういう意味ですか?
エンコードされたスペースです。メールシステムは行末の空白を削ることがあるため、Quoted-Printable では行末のスペースやタブを =20 や =09 と書いて保護します。
Python で Quoted-Printable をデコードするには?
quopri.decodestring(data) または binascii.a2b_qp(data) がバイト列を返します。続けて .decode("utf-8")、または Content-Type ヘッダーで指定された文字コードでデコードしてください。
=?UTF-8?Q?...?= 形式の件名もデコードできますか?
このページではできません。これは RFC 2047 のエンコードワードで、空白を _ で表す近縁の Q エンコーディングを使います。ヘッダー内のエンコードワードは、Quoted-Printable の本文とあわせて EML デコーダー でデコードできます。