# 18.1.3. `email.generator`: MIME 文書を生成する

よくある作業のひとつは、メッセージオブジェクト構造からフラットな電子メールテキストを生成することです。この作業は `smtplib` や `nntplib` モジュールを使ってメッセージを送信したり、メッセージをコンソールに出力したりするときに必要になります。あるメッセージオブジェクト構造をとってきて、そこからフラットなテキスト文書を生成するのは `Generator` クラスの仕事です。

繰り返しになりますが、 `email.parser` モジュールと同じく、この機能はここでの定義済みジェネレータに制限されるわけではありません。これらはご自身でゼロから作りあげることもできます。しかしながら、定義済みのジェネレータはほとんどの電子メールを標準に沿ったやり方で生成する方法を知っていますし、MIME メッセージも非 MIME メッセージもとても上手く扱えます。さらにこれはフラットなテキストから `Parser` クラスを使ってメッセージ構造に変換し、それをまたフラットなテキストに戻しても、結果が冪等 (入力が出力と同じになる) [1] になるよう設計されています。一方で、プログラムによって構成された `Message` のジェネレータを使う場合、デフォルトの挿入によって `Message` オブジェクトを変えてしまうかもしれません。

`email.generator` モジュールからインポートされる `Generator` クラスで公開されているメソッドには、以下のようなものがあります:

class `email.generator.``Generator`(outfp[, mangle_from_[, maxheaderlen]])

  `Generator` クラスのコンストラクタは outfp と呼ばれるストリーム形式 (file-like) のオブジェクトひとつを引数にとります。 outfp は `write()` メソッドをサポートし、 Python 拡張 print 文の出力ファイルとして使えるようになっている必要があります。

  オプション引数 mangle_from_ はフラグで、`True` のときはメッセージ本体の行で厳密に `From` で始まるもの、つまり行の先頭が `From` でその後に空白が続く行の前に `>` という文字を挿入します。これは、このような行が Unix の mailbox 形式のエンペローブヘッダ区切り文字列として誤認識されるのを防ぐための、移植性ある唯一の方法です (詳しくは WHY THE CONTENT-LENGTH FORMAT IS BAD (なぜ Content-Length 形式が有害か) を参照してください)。デフォルトでは mangle_from_ は `True` になっていますが、Unix の mailbox 形式ファイルに出力しないのならばこれは `False` に設定してもかまいません。

  オプション引数 maxheaderlen は連続していないヘッダの最大長を指定します。ひとつのヘッダ行が maxheaderlen (これは文字数です、tab は空白 8文字に展開されます) よりも長い場合、ヘッダは `Header` クラスで定義されているように途中で折り返され、間にはセミコロンが挿入されます。もしセミコロンが見つからない場合、そのヘッダは放置されます。ヘッダの折り返しを禁止するにはこの値にゼロを指定してください。デフォルトは 78 文字で、 RFC 2822 で推奨されている (ですが強制ではありません) 値です。

  これ以外のパブリックな `Generator` メソッドは以下のとおりです:

  `flatten`(msg[, unixfrom])

    msg を基点とするメッセージオブジェクト構造体の文字表現を出力します。出力先のファイルにはこの `Generator` インスタンスが作成されたときに指定されたものが使われます。各 subpart は深さ優先順序 (depth-first) で出力され、得られるテキストは適切に MIME エンコードされたものになっています。

    オプション引数 unixfrom は、基点となるメッセージオブジェクトの最初の RFC 2822 ヘッダが現れる前に、エンペローブヘッダ区切り文字列を出力することを強制するフラグです。そのメッセージオブジェクトがエンペローブヘッダをもたない場合、標準的なエンペローブヘッダが自動的に作成されます。デフォルトではこの値は `False` に設定されており、エンペローブヘッダ区切り文字列は出力されません。

    注意: 各 subpart に関しては、エンペローブヘッダは出力されません。

    バージョン 2.2.2 で追加.

  `clone`(fp)

    この `Generator` インスタンスの独立したクローンを生成し返します。オプションはすべて同一になっています。

    バージョン 2.2.2 で追加.

  `write`(s)

    文字列 s を既定のファイルに出力します。ここでいう出力先は `Generator` コンストラクタに渡した outfp のことをさします。この関数はただ単に拡張 print 文で使われる `Generator` インスタンスに対してファイル操作風の API を提供するためだけのものです。

ユーザの便宜をはかるため、メソッド `Message.as_string()` と `str(aMessage)` (つまり `Message.__str__()` のことです) をつかえばメッセージオブジェクトを特定の書式でフォーマットされた文字列に簡単に変換することができます。詳細は `email.message` を参照してください。

`email.generator` モジュールはひとつの派生クラスも提供しています。これは `DecodedGenerator` と呼ばれるもので、 `Generator` 基底クラスと似ていますが、非 text 型の subpart を特定の書式でフォーマットされた表現形式で置きかえるところが違っています。

class `email.generator.``DecodedGenerator`(outfp[, mangle_from_[, maxheaderlen[, fmt]]])

  このクラスは `Generator` から派生したもので、メッセージの subpart をすべて渡り歩きます。subpart の主形式が text だった場合、これはその subpart のペイロードをデコードして出力します。オプション引数 _mangle_from_ および maxheaderlen の意味は基底クラス `Generator` のそれと同じです。

  Subpart の主形式が text ではない場合、オプション引数 fmt がそのメッセージペイロードのかわりのフォーマット文字列として使われます。 fmt は `%(keyword)s` のような形式を展開し、以下のキーワードを認識します:

  - `type` -- 非 text 型 subpart の MIME 形式
  - `maintype` -- 非 text 型 subpart の MIME 主形式 (maintype)
  - `subtype` -- 非 text 型 subpart の MIME 副形式 (subtype)
  - `filename` -- 非 text 型 subpart のファイル名
  - `description` -- 非 text 型 subpart につけられた説明文字列
  - `encoding` -- 非 text 型 subpart の Content-transfer-encoding

  fmt のデフォルト値は `None` です。こうすると以下の形式で出力します

      [Non-text (%(type)s) part of message omitted, filename %(filename)s]

  バージョン 2.2.2 で追加.

バージョン 2.5 で変更: 以前の非推奨メソッド `__call__()` は削除されました。

注記

[1] | ここではあなたが `unixfrom` 引数に適切な設定を使い、 maxheaderlen=0 (入力行がどんな長さでも元のものを維持します) をセットしていることを前提にしています。これでもなお厳密には正しくありません。多くの場合ヘッダの連続する空白が単一の空白に置き換えられるからです。これはいずれは修正されるべきバグです。