QP

Quoted-Printable と Q符号化 (MIME)

RFC 2045 の BNF

     quoted-printable := qp-line *(CRLF qp-line)
     qp-line := *(qp-segment transport-padding CRLF)
                qp-part transport-padding
     qp-part := qp-section
                ; Maximum length of 76 characters 最大長76文字
     qp-segment := qp-section *(SPACE / TAB) "="
                   ; Maximum length of 76 characters 最大長76文字
     qp-section := [*(ptext / SPACE / TAB) ptext]
     ptext := hex-octet / safe-char
     safe-char := <any octet with decimal value of 33 through
                  60 inclusive, and 62 through 126>
                  ; Characters not listed as "mail-safe" in
                  ; RFC 2049 are also not recommended.
                  ;; RFC 2049 の 「mail-safe」 (メイル安全)に無い文字は
                  ;; 使用しないのが良い。
     hex-octet := "=" 2(DIGIT / "A" / "B" / "C" / "D" / "E" / "F")
                  ; Octet must be used for characters > 127, =,
                  ; SPACEs or TABs at the ends of lines, and is
                  ; recommended for any character not listed in
                  ; RFC 2049 as "mail-safe".
                  ;; 127以上、 = 、行末の SP・TAB  はダメ。
                  ;; RFC 2049 の(以下同文)。
                  ;; 書いてないけど大文字・小文字を区別する。
     transport-padding := *LWSP-char
                          ; Composers MUST NOT generate
                          ; non-zero length transport
                          ; padding, but receivers MUST
                          ; be able to handle padding
                          ; added by message transports.
                  ;; 構成者は生成しちゃダメ。受信者は扱えないとダメ

説明 (RFC 2045, 2047 より抜粋・補足)

CTE で使われるのが Quoted-Printable, それに似た encoded-word で使われてる のが Q 符号化。

1. text/* で CRLF やってる CR (0x0D), LF (0x0A) 以外のオクテットは 「"=" 2HEXDIGIT」で表せる。 A 〜 F は大文字のみ、小文字は禁止。 ところがどっこい、 RFC 2047 では大文字にするべき (小文字 should)。 なんだ、小文字でもいい(こともある)んだ?

2. 0x21 〜 0x3C, 0x3E 〜 0x7E は生で出現可能。但し場面に左右される。 (cf. 0x3D "=")

3. SP, TAB は生で出現 OK。但し符号化行の最後にあたる部分 (CRLF の手前) では生では現れたら駄目。その時は 1 に従い =20 とかする。 encoded-word の Q 符号化では駄目。 =20, =09 を使うべし。

4. text/* で CRLF はそのまま。そうでない 0x0A, 0x0D は 1 に従い =0A とかする。 encoded-word の Q 符号化では当然駄目。 =0D とか =0A 使うべし。

5. (軟改行 soft line-break) = で終わる (あるいは = のあとに SP, TAB だけが幾つか続いて終わる) (終わるというか、その次が改行 CRLF になる) 時は、その改行は元データの改行ではない。 (から、 復号した時に = 以降まとめてなくなる。) encoded-word の Q 符号化では当然駄目。

6. 符号化した人は行末に SP, TAB を入れちゃいけないけど、 中継者が入れるかもしれないから、復号する人は必ず無視しないといけない。 encoded-word の Q 符号化では関係なし。

7. Q 符号化では、 0x20 を 「_」(0x5F)で表現できる。 (もちろん、本来の 0x5F は =5F になる。) Quoted-Printable では駄目。「_」は単に 0x5F。

エラー処理

RFC 2045 にはエラー処理の話が。

1. = の後2文字は 0-9A-F で大文字 only だけど、 慈悲深い人 (原文は robust でごーいんな人:-) は小文字も解釈してあげたら。 (でもこれは解釈するべきだと思う。前節の 1 参照。)

2. = の後に来るはず無い文字が来たら、そのまま処理 (=xy をそのまま 0x5C 0x78 0x79 と解釈) して、利用者にイかれてたよって教えてあげたら良さげ。

3. いっちばん最後かその手前に = が来た時も 2 とおんなじ。

4. 0x09 (TAB), CRLF, 0x20 〜 0x7E 以外のオクテットが来たら、 ごーいんな人はそいつを取り除いちゃって、利用者にイかれてたよって 教えてあげたら良さげ。

5. 76オクテットを超えてても、ふつーに処理して、利用者に以下略。

変種

QPRINTABLE

  • [1] JISX4346:1999 = ISO/IEC13522-6:1998 の B.3.4 で規定されている QPRINTABLE は、 RFC 1521 の Quoted‐Printable の変種で、(1) 16進数に小文字を使っても構わない (2) 改行は CRLF ではなく 1*(CR / LF / FF) とし、一行の文字数も規制しないという修正を加えたものです。

DKIM-Quoted-Printable

[2] RFC 4871DKIM-Quoted-Printable という Quoted Printable の変種を定義しています。 MIME の Quoted Printable との違いは、 (1) 空白が意味を持つ場合は符号化しなければならず、 DKIM-Quoted-Printable された文字列中には空白 (FWS) を自由に挿入でき、 無視されること、 (2) やわらかい改行 (行末の = により改行が無視されるというもの) を使えないこと、 (3) 行長制限を持たないことです。本体に適用することが想定されている MIME の Quoted Printable に対して、 DKIM-Quoted-Printableプロトコル要素で利用することが想定されているため、 このような違いがあるものと考えられます。なお、 DKIM-Quoted-Printable でも十六進数大文字でなければなりません。

[3] DKIM-Quoted-Printable 自体は、 ; (タグ分離に使われます。) と = (符号化オクテットの1文字目に使われます。) と SPACE を除くすべての ASCII 印字可能文字をそのまま用いることを認めています。 (なお、 ABNF注釈において、 RFC 2049 mail-safe でない文字は符号化することが推奨 (小文字 recommend) されています。) しかし、 DKIM-Quoted-Printable を使う場所によっては、 そのまま用いられる文字を更に制限していることがあります。 DKIM-Signature: 頭欄z= タグでは、 | も符号化しなければなりません。

qp-section

[4] RFC 4871 における DKIM 文章表現 (3.6.1. 節) における n= タグの値は qp-section として定義されています。 qp-section は、 MIME Quoted Printable の1行にあたります。同じ RFC 4871 で定義されている DKIM-Quoted-Printable とは異なり、空白は無視されず、 その空白自体として解釈されることになります。 ;タグ分離するために使われるので、 文字としての ;タグの値で使う場合、 符号化する必要があります (なぜか 3.5. で説明されています)。

関連

[7] エスケープ文字こそ違いますが、URLパーセント符号化と同種の方式といえます。 Base16 とも遠い親戚といえます。

歴史

[5] RFC 6376 - DomainKeys Identified Mail (DKIM) Signatures ( 版) <http://tools.ietf.org/html/rfc6376>

[6] Article delegate/1443 (95Apr23) Re: Netscape 1.1b3 mail ( ( 版)) <http://news.delegate.org/mail-lists/delegate/1443>