19.1.8. email.header: 国際化されたヘッダ

ソースコード: Lib/email/header.py


RFC 2822 は電子メールメッセージの形式を規定する基本規格です。これはほとんどの電子メールが ASCII 文字のみで構成されていたころ普及した RFC 822 標準から発展したものです。 RFC 2822 は電子メールがすべて 7-bit ASCII 文字のみから構成されていると仮定して作られた仕様です。

もちろん、電子メールが世界的に普及するにつれ、この仕様は国際化されてきました。今では電子メールに言語依存の文字集合を使うことができます。基本規格では、まだ電子メールメッセージを 7-bit ASCII 文字のみを使って転送するよう要求していますので、多くの RFC でどうやって非ASCII の電子メールを RFC 2822 準拠な形式にエンコードするかが記述されています。これらの RFC は以下のものを含みます: RFC 2045RFC 2046RFC 2047 、および RFC 2231email パッケージは、 email.header および email.charset モジュールでこれらの規格をサポートしています。

ご自分の電子メールヘッダ、たとえば SubjectTo などのフィールドに非ASCII文字を入れたい場合、 Header クラスを使う必要があります。 Message オブジェクトの該当フィールドに文字列ではなく、 Header インスタンスを使うのです。 Header クラスは email.header モジュールからインポートしてください。たとえば:

>>> from email.message import Message
>>> from email.header import Header
>>> msg = Message()
>>> h = Header('p\xf6stal', 'iso-8859-1')
>>> msg['Subject'] = h
>>> msg.as_string()
'Subject: =?iso-8859-1?q?p=F6stal?=\n\n'

Subject フィールドに非ASCII文字を含めていることに注目してください。ここでは、含めたいバイト列がエンコードされている文字集合を指定して Header インスタンスを作成することによって実現しています。のちにこの Message インスタンスからフラットなテキストを生成する際に、この Subject フィールドは RFC 2047 準拠の適切な形式にエンコードされます。MIME 機能のあるメーラなら、このヘッダに埋めこまれた ISO-8859-1 文字を正しく表示するでしょう。

以下は Header クラスの説明です:

class email.header.Header(s=None, charset=None, maxlinelen=None, header_name=None, continuation_ws=' ', errors='strict')

別の文字集合の文字列を含む MIME 準拠なヘッダを作成します。

オプション引数 s はヘッダの値の初期値です。これが None の場合 (デフォルト)、ヘッダの初期値は設定されません。この値はあとから append() メソッドを呼びだすことによって追加することができます。 sbytes または str のインスタンスにできます。このセマンティクスについては append() の項を参照してください。

オプション引数 charset には 2 つの目的があります。ひとつは append() メソッドにおける charset 引数と同じものです。もうひとつは、これ以降 charset 引数を省略した append() メソッド呼び出しすべてにおける、デフォルト文字集合を決定するものです。コンストラクタに charset が与えられない場合 (デフォルト)、初期値の s および以後の append() 呼び出しにおける文字集合として us-ascii が使われます。

行の最大長は maxlinelen によって明示的に指定できます。最初の行を (Subject などの s に含まれないフィールドヘッダの責任をとるため) 短く切りとる場合、 header_name にそのフィールド名を指定してください。 maxlinelen のデフォルト値は 76 であり、 header_name のデフォルト値は None です。これはその最初の行を長い、切りとられたヘッダとして扱わないことを意味します。

オプション引数 continuation_wsRFC 2822 準拠の折り返し用余白文字で、ふつうこれは空白か、ハードタブ文字 (hard tab) である必要があります。ここで指定された文字は複数にわたる行の行頭に挿入されます。 continuation_ws のデフォルト値は 1 つのスペース文字です。

オプション引数 errors は、 append() メソッドにそのまま渡されます。

append(s, charset=None, errors='strict')

この MIME ヘッダに文字列 s を追加します。

オプション引数 charset がもし与えられた場合、これは Charset インスタンス (email.charset を参照) か、あるいは文字集合の名前でなければなりません。この場合は Charset インスタンスに変換されます。この値が None の場合 (デフォルト)、コンストラクタで与えられた charset が使われます。

sbytes または str のインスタンスです。 bytes のインスタンスの場合、 charset はその文字列のエンコーディングであり、この文字セットでデコードできないときは UnicodeError が発生します。

sstr のインスタンスの場合、 charset はその文字列の文字セットを決定するためのヒントとして使われます。

いずれの場合でも、 RFC 2822 準拠のヘッダを RFC 2047 の規則を用いて生成する際、文字列は指定された文字セットの出力コーデックを用いてエンコードされます。出力コーデックを用いて文字列がエンコードできないときは UnicodeError が発生します。

オプションの errors は、 s がバイト文字列だった場合のデコード呼び出しに errors 引数として渡されます。

encode(splitchars=';, \t', maxlinelen=None, linesep='\n')

メッセージヘッダを RFC に沿ったやり方でエンコードします。おそらく長い行は折り返され、非 ASCII 部分は base64 または quoted-printable エンコーディングで包含されるでしょう。

オプション引数 splitchars は、通常のヘッダーの折り返し処理の間に分割アルゴリズムによって特別な重みが与えられるべき文字を含む文字列です。これは、 RFC 2822 の 'higher level syntactic breaks' の非常に荒いサポートです: splitchar の後の分割点は、行分割において優先されます。 分割文字は文字列中での出現順に優先されます。スペースとタブは、分割しようとする行に他の分割文字が出現しない時に、分割点として他の文字と比べてどのような優先順位が与えられるべきかを示すために、文字列に含めることができます。 Splitchars は RFC 2047 エンコードされた行には影響しません。

与えられた場合、maxlinelen はインスタンスの最大行長の値を上書きします。

linesep は、折り返しヘッダの行を区切る文字を指定します。デフォルトではPythonアプリケーションコード( `` n``)に最も有用な値になりますが、RFC準拠の行区切り文字でヘッダを生成するために `` r n``を指定することができます。

バージョン 3.2 で変更: linesep 引数が追加されました。

Header クラスは、標準の演算子や組み込み関数をサポートするためのメソッドもいくつか提供しています。

__str__()

Header の概要を文字列として返します。無制限の行長を使用します。すべての箇所は、指定されたエンコーディングを使用してUnicodeに変換され、適切に結合されます。文字セット 'unknown-8bit' を持つ箇所は、 'replace' エラーハンドラを使ってASCIIとしてデコードされます。

バージョン 3.2 で変更: 'unknown-8bit' 文字集合の処理が追加されました。

__eq__(other)

このメソッドは、ふたつの Header インスタンスどうしが等しいかどうか判定するのに使えます。

__ne__(other)

このメソッドは、ふたつの Header インスタンスどうしが異なっているかどうかを判定するのに使えます。

さらに、 email.header モジュールは以下のような簡易関数も提供しています。

email.header.decode_header(header)

文字集合を変換せずにメッセージのヘッダをデコードします。ヘッダの値は header にあります。

この関数はヘッダのそれぞれのデコードされた部分ごとに、(decoded_string, charset) という形式の 2要素タプルからなるリストを返します。charset はヘッダのエンコードされていない部分に対しては None を、それ以外の場合はエンコードされた文字列が指定している文字集合の名前を小文字からなる文字列で返します。

以下はこの使用例です:

>>> from email.header import decode_header
>>> decode_header('=?iso-8859-1?q?p=F6stal?=')
[(b'p\xf6stal', 'iso-8859-1')]
email.header.make_header(decoded_seq, maxlinelen=None, header_name=None, continuation_ws=' ')

decode_header() によって返される 2要素タプルのリストから Header インスタンスを作成します。

decode_header() はヘッダの値をとってきて、 (decoded_string, charset) という形式の 2要素タプルからなるリストを返します。ここで decoded_string はデコードされた文字列、 charset はその文字集合です。

この関数はこれらのリストの項目から、 Header インスタンスを返します。オプション引数 maxlinelenheader_name および continuation_wsHeader コンストラクタに与えるものと同じです。