18.11. "rfc822" --- RFC 2822 準拠のメールヘッダ読み出し
*******************************************************

バージョン 2.3 で非推奨: "rfc822" モジュールを使うよりも "email" パッ
ケージを使うべきです。このモジュールは以前のバージョンとの互換性のため
に保守されているにすぎません。 Python 3 ではこのモジュールは削除されま
した。

このモジュールでは、インターネット標準 **RFC 2822** [1] で定義されてい
る "電子メールメッセージ" を表現するクラス、 "Message" を定義していま
す。このメッセージはメッセージヘッダ群とメッセージボディの集まりからな
ります。このモジュールではまた、ヘルパークラス **RFC 2822** アドレス群
を解釈するための "AddressList" クラスを定義しています。 **RFC 2822**
メッセージ固有の構文に関する情報は RFC を参照してください。

"mailbox" モジュールでは、多くのエンドユーザメールプログラムによって生
成されるメールボックスを読み出すためのクラスを提供しています。

class rfc822.Message(file[, seekable])

   "Message" インスタンスは入力オブジェクトをパラメタに与えてインスタ
   ンス化します。入力オブジェクトのメソッドのうち、Message が依存する
   のは "readline()" だけです; 通常のファイルオブジェクトは適格です。
   インスタンス化を行うと、入力オブジェクトからデリミタ行 (通常は空行
   1 行) に到達するまでヘッダを読み出し、それらをインスタンス中に保持
   します。ヘッダの後のメッセージ本体は読み出しません。

   このクラスは "readline()" メソッドをサポートする任意の入力オブジェ
   クトを扱うことができます。入力オブジェクトが seek および tell でき
   る場合、 "rewindbody()" メソッドが動作します。また、不正な行データ
   を入力ストリームにプッシュバックできます。入力オブジェクトが seek
   できない一方で、入力行をプッシュバックする "unread()" メソッドを持
   っている場合、 "Message" は不正な行データにこのプッシュバックを使い
   ます。こうして、このクラスはバッファされているストリームから来るメ
   ッセージを解釈するのに使うことができます。

   オプションの *seekable* 引数は、 "lseek()" システムコールが動作しな
   いと分かるまでは "tell()" がバッファされたデータを無視するような、
   ある種の stdio ライブラリでの回避手段として提供されています。可搬性
   を最大にするために、socket オブジェクトによって生成されたファイルの
   ような、seek できないオブジェクトを渡す際には、最初に "tell()" が呼
   び出されないようにするために seekable 引数をゼロに設定すべきです。

   ファイルとして読み出された入力行データは CR-LF と単一の改行 (line
   feed) のどちらで終端されていてもかまいません; 行データを記憶する前
   に、終端の CR-LF は単一の改行と置き換えられます。

   ヘッダに対するマッチは全て大小文字に依存しません。例えば、
   "m['From']" 、 "m['from']" 、および "m['FROM']" は全て同じ結果にな
   ります。

class rfc822.AddressList(field)

   **RFC 2833** アドレスがカンマで区切られたものとして解釈できる単一の
   文字列パラメタを使って、 "AddressList" ヘルパークラスをインスタンス
   化することができます。 (パラメタ "None" は空のリストを表します。)

rfc822.quote(str)

   *str* 中のバックスラッシュが 2 つのバックスラッシュに置き換えられ、
   二重引用符がバックスラッシュ付きの二重引用符に置き換えられた、新た
   な文字列を返します。

rfc822.unquote(str)

   文字列 *str* を *逆クォート* した新しい文字列を返します。もし *str*
   の先頭あるいは末尾がダブルクォートだった場合、これらは単に切りおと
   されます。同様にもし *str* の先頭あるいは末尾が角ブラケット (<、>)
   だった場合も切りおとされます。

rfc822.parseaddr(address)

   *To* や *Cc* といった、アドレスが入っているフィールドの値 *address*
   を解析し、含まれている "実名 (realname)" 部分および "電子メールアド
   レス" 部分に分けます。それらの情報からなるタプルを返します。解析が
   失敗した場合には 2 要素のタプル "(None, None)" を返します。

rfc822.dump_address_pair(pair)

   "parseaddr()" の逆で、実名と電子メールアドレスからなる 2要素のタプ
   ル"(realname, email_address)" を引数にとり、 *To* あるいは *Cc* ヘ
   ッダに適した形式の文字列を返します。タプル *pair* の第1要素が偽であ
   る場合、第2要素の値をそのまま返します。

rfc822.parsedate(date)

   **RFC 2822** の規則に従っている日付を解析しようと試みます。しかしな
   がら、メーラによっては **RFC 2822** で指定されているような書式に従
   わないため、そのような場合には "parsedata()" は正しい日付を推測しよ
   うと試みます。 *date* は "'Mon, 20 Nov 1995 19:12:08 -0500'" のよう
   な **RFC 2822** 様式の日付を収めた文字列です。日付の解析に成功した
   場合、 "parsedate()" は "time.mktime()" にそのまま渡すことができる
   ような 9 要素のタプルを返します; そうでない場合には "None" を返しま
   す。結果のインデックス 6、7、および 8 は有用な情報ではありません。

rfc822.parsedate_tz(date)

   "parsedate()" と同じ機能を実現しますが、 "None" または 10 要素のタ
   プルを返します; 最初の 9 要素は "time.mktime()" に直接渡すことがで
   きるようなタプルで、 10 番目の要素はその日のタイムゾーンにおける
   UTC (グリニッチ標準時の公式名称) からのオフセットです。(タイムゾー
   ンオフセットの符号は、同じタイムゾーンにおける "time.timezone" 変数
   の符号と反転しています; 後者の変数が POSIX 標準に従っている一方、こ
   のモジュールは **RFC 2822** に従っているからです。) 入力文字列がタ
   イムゾーン情報を持たない場合、タプルの最後の要素は "None" になりま
   す。結果のインデックス 6、7、および 8 は有用な情報ではありません。

rfc822.mktime_tz(tuple)

   "parsedata_tz()" が返す 10 要素のタプルを UTC タイムスタンプに変換
   します。タプル内のタイムゾーン要素が "None" の場合、地域の時刻を表
   しているものと仮定します。些細な欠陥: この関数はまず最初の 8 要素を
   地域における時刻として変換し、次にタイムゾーンの違いに対する補償を
   行います; これにより、夏時間の切り替え日前後でちょっとしたエラーが
   生じるかもしれません。通常の利用に関しては心配ありません。

参考:

  "email" モジュール
     包括的な e-mail 処理パッケージです。 "rfc822" に取って代わります
     。

  "mailbox" モジュール
     エンドユーザのメールプログラムによって生成される、様々な mailbox
     形式を読み出すためのクラス群。

  "mimetools" モジュール
     MIME エンコードされたメッセージを処理する "rfc822.Message" のサブ
     クラス。


18.11.1. Message オブジェクト
=============================

"Message" インスタンスは以下のメソッドを持っています:

Message.rewindbody()

   メッセージ本体の先頭に seek します。このメソッドはファイルオブジェ
   クトが seek 可能である場合にのみ動作します。

Message.isheader(line)

   ある行が正しい **RFC 2822** ヘッダである場合、その行の正規化された
   フィールド名 (インデクス指定の際に使われる辞書キー) を返します; そ
   うでない場合 "None" を返します (解析をここで一度中断し、行データを
   入力ストリームに押し戻すことを意味します)。このメソッドをサブクラス
   で上書きすると便利なことがあります。

Message.islast(line)

   与えられた line が Message の区切りとなるデリミタであった場合に真を
   返します。このデリミタ行は消費され、ファイルオブジェクトの読み位置
   はその直後になります。標準ではこのメソッドは単にその行が空行かどう
   かをチェックしますが、サブクラスで上書きすることもできます。

Message.iscomment(line)

   与えられた行全体を無視し、単に読み飛ばすときに真を返します。標準で
   は、これは控えメソッド (stub) であり、常に "False" を返しますが、サ
   ブクラスで上書きすることもできます。

Message.getallmatchingheaders(name)

   *name* に一致するヘッダ全てで構成される行のリストを返します。各物理
   行は継続行であるか否かに関わらず別々のリスト要素になります。 *name*
   に一致するヘッダがない場合、空のリストを返します。

Message.getfirstmatchingheader(name)

   *name* に一致する最初のヘッダと、その行に継続する (複数) 行からなる
   行データのリストを返します。 *name* に一致するヘッダがない場合
   "None" を返します。

Message.getrawheader(name)

   *name* に一致する最初のヘッダにおけるコロン以降のテキストが入った単
   一の文字列を返します。このテキストには、先頭の空白、末尾の改行、ま
   た継続の行がある場合には途中の改行と空白が含まれます。 *name* に一
   致するヘッダが存在しない場合には "None" を返します。

Message.getheader(name[, default])

   *name* に一致する最後のヘッダから先頭および末尾の空白を剥ぎ取った単
   一の文字列を返します。途中にある空白は剥ぎ取られません。オプション
   の *default* 引数は、 *name* に一致するヘッダが存在しない場合に、別
   のデフォルト値を返すように指定するために使われます。デフォルトは
   "None" です。パースされたヘッダを得る方法としてはこれが好ましいでし
   ょう。

Message.get(name[, default])

   正規の辞書との互換性をより高めるための "getheader()" の別名です。

Message.getaddr(name)

   "getheader(name)" が返した文字列を解析して、 "(full name, email
   address)" からなるペアを返します。 *name* に一致するヘッダが無い場
   合、 "(None, None)" が返されます; そうでない場合、 *full name* およ
   び *address* は (空文字列をとりうる) 文字列になります。

   例: *m* に最初の *From* ヘッダに文字列 "'jack@cwi.nl (Jack
   Jansen)'" が入っている場合、 "m.getaddr('From')" はペア "('Jack
   Jansen', 'jack@cwi.nl')" になります。また、 "'Jack Jansen
   <jack@cwi.nl>'" であっても、全く同じ結果になります。

Message.getaddrlist(name)

   "getaddr(list)" に似ていますが、複数のメールアドレスからなるリスト
   が入ったヘッダ (例えば *To* ヘッダ) を解析し、 "(full name, email
   address)" のペアからなるリストを (たとえヘッダには一つしかアドレス
   が入っていなかったとしても) 返します。 *name* に一致するヘッダが無
   かった場合、空のリストを返します。

   指定された名前に一致する複数のヘッダが存在する場合 (例えば、複数の
   *Cc* ヘッダが存在する場合)、全てのアドレスを解析します。指定された
   ヘッダが継続行で収められている場合も解析されます。

Message.getdate(name)

   "getheader()" を使ってヘッダを取得して解析し、 "time.mktime()" と互
   換な 9 要素のタプルにします; フィールド 6、7、および 8 は有用な値で
   はないので注意して下さい。 *name* に一致するヘッダが存在しなかった
   り、ヘッダが解析不能であった場合、 "None" を返します。

   日付の解析は黒魔術のようなものであり、全てのヘッダが標準に従ってい
   るとは限りません。このメソッドは多くの発信源から集められた膨大な数
   の電子メールでテストされており、正しく動作することが分かっています
   が、間違った結果を出力してしまう可能性はまだあります。

Message.getdate_tz(name)

   "getheader()" を使ってヘッダを取得して解析し、10 要素のタプルにしま
   す; 最初の 9 要素は "time.mktime()" と互換性のあるタプルを形成し、
   10 番目の要素はその日におけるタイムゾーンの UTC からのオフセットを
   与える数字になります。フィールド 6、7、および 8 は有用な値ではない
   ので注意して下さい。 "getdate()" と同様に、 *name* に一致するヘッダ
   がなかったり、解析不能であった場合、 "None" を返します。

"Message" インスタンスはまた、限定的なマップ型のインタフェースを持って
います。すなわち: "m[name]" は "m.getheader(name)" に似ていますが、一
致するヘッダがない場合 "KeyError" を送出します; "len(m)" 、
"m.get(name[, default])" 、 "name in m", "m.keys()" 、 "m.values()" 、
"m.items()" 、および "m.setdefault(name[, default])" は期待通りに動作
します。ただし "setdefault()" は標準の設定値として空文字列をとります。
"Message" インスタンスはまた、マップ型への書き込みを行えるインタフェー
ス "m[name] = value" および "del m[name]" をサポートしています。
"Message" オブジェクトでは、 "clear()" 、 "copy()" 、 "popitem()" 、あ
るいは "update()" といったマップ型インタフェースのメソッドはサポートし
ていません。 ("get()" および "setdefault()" のサポートは Python 2.2 で
しか追加されていません。)

最後に、 "Message" インスタンスはいくつかの public なインスタンス変数
を持っています:

Message.headers

   ヘッダ行のセット全体が、(setitem を呼び出して変更されない限り) 読み
   出された順番に入れられたリストです。各行は末尾の改行を含んでいます
   。ヘッダを終端する空行はリストに含まれません。

Message.fp

   インスタンス化の際に渡されたファイルまたはファイル類似オブジェクト
   です。この値はメッセージ本体を読み出すために使うことができます。

Message.unixfrom

   メッセージに Unix "From" 行がある場合はその行、そうでなければ空文字
   列になります。この値は例えば "mbox" 形式のメールボックスファイルの
   ような、あるコンテキスト中のメッセージを再生成するために必要です。


18.11.2. AddressList オブジェクト
=================================

"AddressList" インスタンスは以下のメソッドを持ちます:

AddressList.__len__()

   アドレスリスト中のアドレスの数を返します。

AddressList.__str__()

   アドレスリストの正規化 (canonicalize) された文字列表現を返します。
   アドレスはカンマで分割された "name" <host@domain> 形式になります。

AddressList.__add__(alist)

   二つの "AddressList" 被演算子中の双方に含まれるアドレスについて、重
   複を除いた (集合和の) 全てのアドレスを含む新たな "AddressList" イン
   スタンスを返します。

AddressList.__iadd__(alist)

   "__add__()" のインプレース演算版です; "AddressList" インスタンスと
   右辺値 *alist* との集合和をとり、その結果をインスタンス自体と置き換
   えます。

AddressList.__sub__(alist)

   左辺値の "AddressList" インスタンスのアドレスのうち、右辺値中に含ま
   れていないもの全てを含む (集合差分の) 新たな "AddressList" インスタ
   ンスを返します。

AddressList.__isub__(alist)

   "__sub__()" のインプレース演算版で、 *alist* にも含まれているアドレ
   スを削除します。

最後に、 "AddressList" インスタンスは public なインスタンス変数を一つ
持ちます:

AddressList.addresslist

   アドレスあたり一つの文字列ペアで構成されるタプルからなるリストです
   。各メンバ中では、最初の要素は正規化された名前部分で、二つ目は実際
   の配送アドレス ("'@'" で分割されたユーザ名とホスト.ドメインからなる
   ペア) です。

-[ 脚注 ]-

[1] このモジュールはもともと **RFC 822** に適合していたので、そう
    いう 名前になっています。その後、 **RFC 2822** が **RFC 822** に対
    する 更新としてリリースされました。このモジュールは **RFC 2822**
    適合で あり、特に **RFC 822** からの構文や意味付けに対する変更がな
    されて います。
