MIME Base64 を作る方法
- 入力 · テキスト にテキストを貼り付けます。折り返し はあらかじめ 76 (MIME, LF) になっています。
- メッセージが別の文字コードを宣言していない限り 文字コード は UTF-8 のままにし、
Content-Typeヘッダーにも同じ値を使います。 - 折り返した Base64 を 出力 · Base64 からコピーするか、ダウンロード で
base64.txtとして保存します。 - 証明書や鍵の本体なら、折り返し を 64 (PEM) に切り替えます。HTTP、JSON など 1 行を求めるものには なし を選びます。
MIME Base64 とは
MIME(RFC 2045)は、メールで添付ファイル、英語以外のテキスト、HTML を運べるようにする規格です。パートの本文がバイナリだったり非 ASCII のバイトだらけだったりすると、送信側はそれを Base64 でエンコードし、Content-Transfer-Encoding: base64 を付けます。RFC 2045 は素の Base64 に加えて、エンコード後の行は最大 76 文字という行の長さのルールを定めています。76 文字の行には入力の 57 バイトが入ります。
この方法でエンコードしたテキストのパートは、次のようになります。2 行の Base64 は、下に引用した文をこのツールで出力したものです。
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: base64
Q2Fmw6kgbWVudTogY3LDqG1lIGJyw7tsw6llLCBqYWxhcGXDsW8sIHNtw7ZyZ8Olc2JvcmQuIFRo
aXMgbGluZSBpcyBsb25nIGVub3VnaCB0byB3cmFwIGFmdGVyIDc2IGNoYXJhY3RlcnMu
元のテキストは Café menu: crème brûlée, jalapeño, smörgåsbord. This line is long enough to wrap after 76 characters. で、UTF-8 で 108 バイトです。Base64 デコーダー で 2 行をまとめてデコードすると、改行は無視されて元の文に戻ります。
改行、CRLF、サイズ
折り返し には 76 桁の 2 つの選択肢があります。76 (MIME, LF) は行を改行(\n)で区切り、76 (MIME, CRLF) は \r\n を使います。送受信されるメールは CRLF を使いますが、メールライブラリはメッセージをシリアライズするときに改行コードを変換するので、コードで使うなら LF で問題ありません。出力を生の .eml ファイルや SMTP セッションに直接貼り付けるなら、CRLF の方を選んでください。
折り返すと、通常の 33% に加えてわずかに余分な領域を使います。
| 出力 | 入力 57 バイトあたりの文字数 | 増加率 |
|---|---|---|
| 1 行、改行なし | 76 | 33.3% |
| LF で 76 文字ごとに改行 | 77 | 35.1% |
| CRLF で 76 文字ごとに改行 | 78 | 36.8% |
メールのサイズ制限はエンコード後のメッセージに適用されるので、10 MB の添付ファイルは制限のうち約 13.7 MB を使います。正確な数値は サイズ計算ツール でわかります。パートの組み立て方は メールの Base64 で解説しています。
ヘッダー用のエンコードワード
Subject や From などのヘッダーでは Content-Transfer-Encoding を使えません。非 ASCII のヘッダーテキストには、RFC 2047 のエンコードワード =?charset?B?base64?= を使います。作るには、折り返し を なし にしてテキストをエンコードし、結果を自分で囲みます。
Subject: =?UTF-8?B?R3LDvMOfZSBhdXMgQmVybGlu?=
これをデコードすると Grüße aus Berlin になります。1 つのエンコードワードは最大 75 文字で、それより長い件名は、空白で区切った複数のエンコードワードに分けます。ほぼ ASCII のテキストなら、メールソフトは代わりに quoted-printable に基づく ?Q? 形式を使うことがよくあります。
コードとコマンドラインでの MIME Base64
Python の base64.encodebytes は \n で 76 文字ごとに折り返し、このツールと同じ行を出力します。
import base64
text = "Café menu: crème brûlée, jalapeño, smörgåsbord. This line is long enough to wrap after 76 characters."
print(base64.encodebytes(text.encode("utf-8")).decode("ascii"))
メッセージ全体を扱うなら、email パッケージがエンコード、ヘッダー、CRLF を処理してくれます。Linux では、GNU の base64 はデフォルトで 76 文字、openssl base64 は 64 文字で折り返します。
base64 attachment.pdf > attachment.b64
openssl base64 -in attachment.pdf -out attachment.pem.b64
逆に生のメールを分解するなら、メール(EML)デコーダー で開けば本文と添付ファイルを取り出せます。
よくある質問
MIME Base64 が 76 文字の行を使うのはなぜですか?
RFC 2045 が上限を 76 文字と定めているからで、メールの行の上限 998 文字(RFC 5322)を十分に下回ります。76 は 4 の倍数なので、各行にはちょうど 57 バイトが入ります。
MIME Base64 は普通の Base64 と違うのですか?
アルファベットとパディングは同じです。違いは改行だけで、デコーダーは改行を無視することになっているため、折り返した版もしない版も同じバイト列にデコードされます。
メールの Subject 行の Base64 は折り返すべきですか?
いいえ。ヘッダーには =?UTF-8?B?R3LDvMOfZQ==?= のような RFC 2047 のエンコードワードを使い、これには改行を入れてはいけません。件名は折り返しをなしにしてエンコードし、各エンコードワードを 75 文字以下に収めてください。
openssl で 64 文字の行になるのはなぜですか?
openssl base64 は PEM の慣例どおり 64 文字で折り返し、GNU の base64 やほとんどのメールライブラリは 76 文字で折り返すからです。どちらも同じようにデコードされます。openssl とまったく同じ出力が必要なら、ここで 64 を選んでください。