email.headerregistry: カスタムヘッダーオブジェクト

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


Added in version 3.6: [1]

ヘッダーは str のカスタマイズされたサブクラスで表現されます。 与えられたヘッダーを表現するために使用される特定のクラスは、ヘッダーが作成されるときに有効な policy の header_factory で決定されます。 このセクションでは、email ライブラリが RFC 5322 に準拠したメールメッセージを扱うために実装している、特定の header_factory について説明します。このヘッダーは、様々なヘッダータイプに対してカスタマイズされたヘッダーオブジェクトを提供するだけでなく、アプリケーションが独自のカスタムヘッダータイプを追加できるような拡張メカニズムも備えています。

EmailPolicy から派生したポリシーオブジェクトのいずれかを使用する場合、すべてのヘッダーは HeaderRegistry によって生成され、最終的な基底クラスとして BaseHeader を有します。 各ヘッダクラスには、ヘッダの種類によって決まる追加のベースクラスがあります。 例えば、多くのヘッダーは UnstructuredHeader というクラスをもうひとつの基底クラスとして持っています。 ヘッダーに特化した第二のクラスは、ヘッダーの名前によって決定され、 HeaderRegistry に格納されたルックアップテーブルを使用します。 これらすべては、典型的なアプリケーションプログラムに対しては透過的に管理されますが、より複雑なアプリケーションで使用するためにデフォルトの動作を変更するためのインタフェースが提供されています。

以下のセクションでは、まずヘッダーの基本クラスとその属性を説明し、次に HeaderRegistry の動作を変更するための API、そして最後に構造化ヘッダーからパースされたデータを表現するためのサポートクラスについて説明します。

class email.headerregistry.BaseHeader(name, value)

name と value は、header_factory の呼び出しから BaseHeader に渡されます。 ヘッダーオブジェクトの文字列としての値は、value を完全にデコードした文字列です。

基底クラスは以下の読み出し専用属性を定義しています:

name

ヘッダーの名前(フィールドの':'の前の部分)。これは header_factory の name の呼び出しで渡された値と全く同じです; つまり、大文字・小文字が保持されます。

defects

パース中に見つかったRFCのコンプライアンス問題を報告する HeaderDefect インスタンスのタプルです。 email パッケージはコンプライアンスに関する問題を完全に検出するように努めています。 報告されるかもしれない欠陥の種類の議論については、 errors モジュールを参照してください。

max_count

このタイプのヘッダーで、同じ name を持つことができる最大数。 値として None を指定すると、無制限になります。 この属性の BaseHeader の値は None です; 特殊な header クラスでは、必要に応じてこの値をオーバーライドすることが期待されます。

BaseHeader は以下のメソッドも提供します。このメソッドはemail ライブラリのコードから呼び出され、一般にアプリケーションプログラムからは呼び出されません:

fold(*, policy)

ヘッダを policy に従って正しく折りたたむために必要な linesep 文字を含む文字列を返します。 ヘッダには任意のバイナリデータを含めることができないため、 cte_type が 8bit の場合は 7bit と同じように扱われます。 もし utf8 が False であれば、非ASCIIデータは RFC 2047 でエンコードされます。

BaseHeader 自身はヘッダーオブジェクトを生成するために使用することはできません。このクラスは、それぞれの特殊化ヘッダーがヘッダーオブジェクトを生成するために協力するプロトコルを定義しています。 具体的には、 BaseHeader は parse という名前の classmethod() を特殊化されたクラスが提供することを要求しています。このメソッドは以下のように呼び出されます:

parse(string, kwds)

kwds は、あらかじめ初期化されたキー defects を一つ含む辞書です。 defects の値は空のリストです。 parse() メソッドは、検出した欠陥をこのリストに追加する必要があります。 戻る際には、kwds 辞書に少なくとも decoded、defects、parse_tree の各キーの値が なければなりません。 decoded はヘッダーの文字列値、つまりヘッダー値を完全にデコードした文字列にします。 parse_tree には、ヘッダーを解析して得た構文木を設定します。 parse() メソッドは、string にコンテンツ転送エンコーディングが適用された部分が含まれる可能性を考慮するとともに、エンコードされていないヘッダー値も解析できるよう、すべての有効な Unicode 文字を正しく扱う必要があります。

その後、 BaseHeader の __new__ がヘッダのインスタンスを生成し、 init メソッドを呼び出します。 特殊クラスは、 BaseHeader が提供しない属性を設定したい場合にのみ init メソッドを提供する必要があります。 このような init メソッドは以下のようなものです。

def init(self, /, *args, **kw):
    self._myattr = kw.pop('myattr')
    super().init(*args, **kw)

つまり、特殊クラスが kwds の辞書に追加したものはすべて削除して処理し、 kw の残りの内容 (と args) は BaseHeader の init メソッドに渡す必要があるのです。

class email.headerregistry.UnstructuredHeader

"unstructured" ヘッダは RFC 5322 におけるデフォルトのヘッダのタイプです。指定された構文を持たないすべてのヘッダは、unstructuredとして扱われます。 構造化されていないヘッダの典型的な例は Subject ヘッダです。

RFC 5322 では、非構造化ヘッダーは ASCII 文字集合による任意のテキストの並びです。 ただし、RFC 2047 は、ヘッダー値の中で非 ASCII テキストを ASCII 文字にエンコードする、RFC 5322 と互換性のある仕組みを定めています。 エンコードされた語を含む value がコンストラクタに渡されると、UnstructuredHeader のパーサーは、非構造化テキストに関する RFC 2047 の規則に従ってそれらを文字列に変換します。 パーサーは、一部の規格に準拠しないエンコードされた語についても、ヒューリスティックによってデコードを試みます。 その場合には欠陥が記録されます。 エンコードされた語やエンコードされていないテキストに不正な文字がある場合なども同様です。

このヘッダ型には追加の属性はありません。

class email.headerregistry.DateHeader

RFC 5322 は、電子メールヘッダー内の日付について厳密な形式を定めています。 DateHeader のパーサーはその形式に加え、実際のメールで見かけるさまざまな変形も認識します。

このヘッダ型は以下の属性も提供しています:

datetime

ヘッダー値を何らかの有効な日付形式として認識できた場合、この属性にはその日時を表す datetime インスタンスが入ります。 入力のタイムゾーンが -0000 (UTC だが送信元のタイムゾーン情報はないことを示します) の場合、datetime は naive な datetime になります。 +0000 を含む特定のタイムゾーンオフセットが見つかった場合、datetime は datetime.timezone でオフセットを記録した aware な datetime になります。

ヘッダーの decoded 値は、datetime を RFC 5322 の規則に従って書式化したものです。 つまり、次のように設定されます。

email.utils.format_datetime(self.datetime)

DateHeader を作成する際に、 value は datetime インスタンスである可能性があります。 これは、例えば、次のようなコードは有効であり、期待通りの動作をすることを意味します:

msg['Date'] = datetime(2011, 7, 15, 21)

これはnaive な datetime であるため、UTC タイムスタンプとして解釈され、結果として -0000 というタイムゾーンを持つ値になります。 もっと便利なのは utils モジュールの localtime() 関数を使用することです。

msg['Date'] = utils.localtime()

この例では、現在のタイムゾーンオフセットを使用して、日付ヘッダーを現在の時刻と日付に設定します。

class email.headerregistry.AddressHeader

アドレスヘッダは最も複雑な構造のヘッダタイプの1つです。 AddressHeader クラスは、あらゆるアドレスヘッダに対する汎用的なインターフェースを提供します。

このヘッダ型は以下の属性も提供しています:

groups

ヘッダー値に含まれるアドレスとグループをエンコードした Group オブジェクトのタプルです。 グループに属さないアドレスは、このリストでは display_name が None であるシングルアドレスの Groups として表現されます。

addresses

ヘッダー値に含まれる全ての個別アドレスをエンコードした Address オブジェクトのタプルです。 ヘッダ値にグループが含まれている場合、そのグループに含まれる個々のアドレスは、ヘッダ値でグループが出現した時点でリストに含まれます (つまり、アドレスのリストは一次元のリストに「フラット化」されます)。

The decoded value of the header will have all encoded words decoded to a string. idna encoded domain names are also decoded to a string. The decoded value is set by joining the str value of the elements of the groups attribute with ', '.

アドレスヘッダーの値の設定には、Address と Group オブジェクトを自由に組み合わせたリストを使えます。 display_name が None の Group オブジェクトは単独のアドレスとして解釈されます。 このため、元のヘッダーの groups 属性から得たリストを使えば、グループを保持したままアドレス一覧をコピーできます。

class email.headerregistry.SingleAddressHeader

追加の属性を 1 つ持つ、AddressHeader の派生クラスです:

address

ヘッダー値で表された単一のアドレスです。 ヘッダー値に複数のアドレスが含まれる場合 (デフォルトの policy では RFC 違反です)、この属性にアクセスすると ValueError が発生します。

上記のクラスの多くには、Unique 版もあります (例えば UniqueUnstructuredHeader)。 違いは、Unique 版では max_count が 1 に設定されることだけです。

class email.headerregistry.MIMEVersionHeader

MIME-Version ヘッダーの有効な値は実際には 1.0 だけです。 将来に備え、このヘッダークラスは他の有効なバージョン番号もサポートします。 バージョン番号が RFC 2045 に照らして有効であれば、ヘッダーオブジェクトの以下の属性は None 以外の値になります。

version

バージョン番号 (文字列)、空白やコメントは除かれます。

major

メジャーバージョン番号 (整数)

minor

マイナーバージョン番号 (整数)

class email.headerregistry.ParameterizedMIMEHeader

MIME ヘッダーはすべて接頭辞 Content- で始まります。 各ヘッダーにはそれぞれの値があり、対応するクラスの説明に記載されています。 また、共通形式の補助パラメータの一覧を持てるものもあります。 このクラスは、パラメータを持つすべての MIME ヘッダーの基底クラスです。

params

パラメータ名をパラメータ値に対応付ける辞書です。

バージョン 3.15 で変更: types.MappingProxyType ではなく frozendict になりました。

class email.headerregistry.ContentTypeHeader

Content-Type ヘッダを扱う ParameterizedMIMEHeader クラスです。

content_type

maintype/subtype 形式のコンテントタイプ文字列。

maintype
subtype
class email.headerregistry.ContentDispositionHeader

Content-Disposition ヘッダを扱う ParameterizedMIMEHeader クラスです。

content_disposition

一般的に使われる有効な値は inline と attachment だけです。

class email.headerregistry.ContentTransferEncodingHeader

Content-Transfer-Encoding ヘッダを扱います。

cte

有効な値は 7bit、8bit、base64、quoted-printable です。詳細については RFC 2045 を参照してください。

class email.headerregistry.HeaderRegistry(base_class=BaseHeader, default_class=UnstructuredHeader, use_default_map=True)

これは EmailPolicy がデフォルトで使うファクトリです。 HeaderRegistry は、base_class と自身のレジストリから取得した専用クラスを使って、ヘッダーインスタンスを作成するためのクラスを動的に構築します。 ヘッダー名がレジストリにない場合、default_class で指定されたクラスを専用クラスとして使います。 use_default_map が True (デフォルト) の場合、初期化時にヘッダー名からクラスへの標準の対応付けをレジストリにコピーします。 base_class は常に、生成されたクラスの __bases__ 一覧の最後のクラスになります。

デフォルトのマッピング:

subject:

UniqueUnstructuredHeader

date:

UniqueDateHeader

resent-date:

DateHeader

orig-date:

UniqueDateHeader

sender:

UniqueSingleAddressHeader

resent-sender:

SingleAddressHeader

to:

UniqueAddressHeader

resent-to:

AddressHeader

cc:

UniqueAddressHeader

resent-cc:

AddressHeader

bcc:

UniqueAddressHeader

resent-bcc:

AddressHeader

from:

UniqueAddressHeader

resent-from:

AddressHeader

reply-to:

UniqueAddressHeader

mime-version:

MIMEVersionHeader

content-type:

ContentTypeHeader

content-disposition:

ContentDispositionHeader

content-transfer-encoding:

ContentTransferEncodingHeader

message-id:

MessageIDHeader

HeaderRegistry には以下のメソッドがあります:

map_to_type(self, name, cls)

name は対応付けるヘッダーの名前です。 レジストリ内では小文字に変換されます。 cls は専用クラスで、base_class と組み合わせて、name に一致するヘッダーをインスタンス化するクラスの作成に使われます。

__getitem__(name)

name ヘッダーの作成を担当するクラスを構築して返します。

__call__(name, value)

name に関連付けられた専用ヘッダークラスをレジストリから取得します (name がレジストリになければ default_class を使います)。 それを base_class と組み合わせてクラスを作成し、同じ引数リストを渡してそのコンストラクタを呼び出し、生成されたインスタンスを返します。

以下のクラスは、構造化ヘッダーから解析したデータの表現に使われます。 通常、アプリケーションからも、特定のヘッダーに代入する構造化された値の作成に使えます。

class email.headerregistry.Address(display_name='', username='', domain='', addr_spec=None)

このクラスは電子メールのアドレスを表すのに使われます。アドレスの一般的な形式は:

[display_name] <username@domain>

もしくは:

username@domain

各部分は RFC 5322 で定められた構文規則に従う必要があります。

便利な方法として、username と domain の代わりに addr_spec を指定できます。 この場合、username と domain は addr_spec から解析されます。 addr_spec は RFC に従って正しく引用符を付けた文字列でなければならず、そうでなければ Address はエラーを送出します。 Unicode 文字も使用でき、直列化時に適切にエンコードされます。 ただし、RFC に従い、アドレスのユーザー名部分では Unicode は許可 されません。

display_name

アドレスの表示名部分で、引用符はすべて取り除かれます。 アドレスに表示名がなければ、空文字列になります。

username

アドレスの username 部分、クォートは取り除かれます。

domain

アドレスの domain 部分。

addr_spec

アドレスの username@domain 部分で、表示名のないアドレス (上記の 2 番目の形式) として使えるよう正しく引用符が付けられます。 この属性は変更できません。

__str__()

オブジェクトの str 値は、RFC 5322 の規則に従って引用符を付けたアドレスですが、非 ASCII 文字にコンテンツ転送エンコーディングは適用されません。

SMTP (RFC 5321) をサポートするため、Address は一つの特殊な場合を扱います。 username と domain が両方とも空文字列 (または None) の場合、Address の文字列値は <> になります。

class email.headerregistry.Group(display_name=None, addresses=None)

このクラスはアドレスグループを表すのに使われます。アドレスグループの一般的な形式は:

display_name: [address-list];

グループと単独のアドレスが混在する一覧を扱いやすくするため、Group でグループに属さない単独のアドレスを表すこともできます。 その場合、display_name を None にし、addresses にそのアドレスだけを含むリストを渡します。

display_name

グループの display_name です。 値が None で、addresses に Address がちょうど一つある場合、その Group はグループに属さない単独のアドレスを表します。

addresses

グループ内のアドレスを表す Address オブジェクトのタプルです。 空の場合もあります。

__str__()

Group の str 値は RFC 5322 に従って書式化されますが、非 ASCII 文字にコンテンツ転送エンコーディングは適用されません。 display_name が None で、addresses リストに Address が一つだけある場合、str 値はその Address の str 値と同じになります。

脚注