requires=
classes=Net=IMAP,Net=IMAP=ContinuationRequest,Net=IMAP=UntaggedResponse,Net=IMAP=TaggedResponse,Net=IMAP=ResponseText,Net=IMAP=ResponseCode,Net=IMAP=MailboxList,Net=IMAP=MailboxQuota,Net=IMAP=MailboxQuotaRoot,Net=IMAP=MailboxACLItem,Net=IMAP=StatusData,Net=IMAP=FetchData,Net=IMAP=Envelope,Net=IMAP=Address,Net=IMAP=ContentDisposition,Net=IMAP=ThreadMember,Net=IMAP=BodyTypeBasic,Net=IMAP=BodyTypeText,Net=IMAP=BodyTypeMessage,Net=IMAP=BodyTypeMultipart,Net=IMAP=Error,Net=IMAP=DataFormatError,Net=IMAP=ResponseParseError,Net=IMAP=ResponseError,Net=IMAP=NoResponseError,Net=IMAP=BadResponseError,Net=IMAP=ByeResponseError,Net=IMAP=FlagCountError
methods=
sublibraries=
is_sublibrary=false
category=Network

このライブラリは Internet Message Access Protocol (IMAP) の
クライアントライブラリです。[[RFC:2060]] を元に
実装されています。

=== IMAP の概要

IMAPを利用するには、まずサーバに接続し、
[[m:Net::IMAP#authenticate]] もしくは
[[m:Net::IMAP#login]] で認証します。
IMAP ではメールボックスという概念が重要です。
メールボックスは階層的な名前を持ちます。
各メールボックスはメールを保持することができます。
メールボックスの実装はサーバソフトウェアによって異なります。
Unixシステムでは、ディレクトリ階層上の
ファイルを個々のメールボックスとみなして実装されることが多いです。

メールボックス内のメッセージ(メール)を処理する場合、
まず [[m:Net::IMAP#select]] もしくは
[[m:Net::IMAP#examine]] で処理対象のメールボックスを
指定する必要があります。これらの操作が成功したならば、
「selected」状態に移行し、そのメールボックスが「処理対象の」
メールボックスとなります。このようにしてメールボックスを
選択してから、selected状態を終える(別のメールボックスを選択したり、
接続を終了したり)までをセッションと呼びます。

メッセージには2種類の識別子が存在します。message sequence number と
UID です。

message sequence number はメールボックス内の各メッセージに1から順に
振られた番号です。セッション中に処理対象のメールボックスに
新たなメッセージが追加された場合、そのメッセージの
message sequence number は
最後のメッセージの message sequence number+1となります。
メッセージをメールボックスから消した場合には、連番の穴を埋めるように
message sequence number が付け替えられます。

一方、UID はセッションを越えて恒久的に保持されます。
あるメールボックス内の異なる2つのメッセージが同じ  UID 
を持つことはありません。
これは、メッセージがメールボックスから削除された後でも成立します。

しかし、UID はメールボックス内で昇順であることが
規格上要請されているので、
IMAP を使わないメールアプリケーションがメールの順番を
変えてしまった場合は、UID が振り直されます。

=== 例

デフォルトのメールボックス(INBOX)の送り元とサブジェクトを表示する。
  imap = Net::IMAP.new('mail.example.com')
  imap.authenticate('LOGIN', 'joe_user', 'joes_password')
  imap.examine('INBOX')
  imap.search(["RECENT"]).each do |message_id|
    envelope = imap.fetch(message_id, "ENVELOPE")[0].attr["ENVELOPE"]
    puts "#{envelope.from[0].name}: \t#{envelope.subject}"
  end

2003年4月のメールをすべて Mail/sent-mail から "Mail/sent-apr03" へ移動させる

  imap = Net::IMAP.new('mail.example.com')
  imap.authenticate('LOGIN', 'joe_user', 'joes_password')
  imap.select('Mail/sent-mail')
  if not imap.list('Mail/', 'sent-apr03')
    imap.create('Mail/sent-apr03')
  end
  imap.search(["BEFORE", "30-Apr-2003", "SINCE", "1-Apr-2003"]).each do |message_id|
    imap.copy(message_id, "Mail/sent-apr03")
    imap.store(message_id, "+FLAGS", [:Deleted])
  end
  imap.expunge

=== スレッド安全性
Net::IMAP は並列実行をサポートしています。例として、

  imap = Net::IMAP.new("imap.foo.net", "imap2")
  imap.authenticate("cram-md5", "bar", "password")
  imap.select("inbox")
  fetch_thread = Thread.start { imap.fetch(1..-1, "UID") }
  search_result = imap.search(["BODY", "hello"])
  fetch_result = fetch_thread.value
  imap.disconnect

とすると FETCH コマンドと SEARCH コマンドを並列に実行します。

=== エラーについて
IMAP サーバは以下の3種類のエラーを送ります。

: NO
  コマンドが正常に完了しなかったことを意味します。
  例えば、ログインでのユーザ名/パスワードが間違っていた、
  選択したメールボックスが存在しない、などです。

: BAD
  クライアントからのリクエストをサーバが理解できなかった
  ことを意味します。
  クライアントの現在の状態では使えないコマンドを使おうとした
  場合にも発生します。例えば、
  selected状態(SELECT/EXAMINEでこの状態に移行する)にならずに
  SEARCH コマンドを使おうとした場合に発生します。
  サーバの内部エラー(ディスクが壊れたなど)の場合も
  このエラーが発生します。

: BYE
  サーバが接続を切ろうとしていることを意味します。
  これは通常のログアウト処理で発生します。
  また、ログイン時にサーバが(なんらかの理由で)接続
  したくない場合にも発生します。
  それ以外では、サーバがシャットダウンする場合か
  サーバがタイムアウトする場合に発生します。

これらのエラーはそれぞれ
  * [[c:Net::IMAP::NoResponseError]]
  * [[c:Net::IMAP::BadResponseError]]
  * [[c:Net::IMAP::ByeResponseError]]
という例外クラスに対応しています。
原理的には、これらの例外はサーバにコマンドを送った場合には
常に発生する可能性があります。しかし、このドキュメントでは
よくあるエラーのみ解説します。

IMAP は Socket で通信をするため、IMAPクラスのメソッドは
Socket 関連のエラーが発生するかもしれません。例えば、
通信中に接続が切れると [[c:Errno::EPIPE]] 例外が
発生します。詳しくは [[c:Socket]] などを見てください。

[[c:Net::IMAP::DataFormatError]]、
[[c:Net::IMAP::ResponseParseError]] という例外クラスも
存在します。前者はデータのフォーマットが正しくない場合に、
後者はサーバからのレスポンスがパースできない場合に発生します。
これらのエラーはこのライブラリもしくはサーバに深刻な問題が
あることを意味します。

=== tagged response と untagged response
IMAP プロトコルにおいてサーバからの応答には tagged なものと
untagged なものの2通り存在します。
tagged な応答は、クライアントからのコマンドが
成功もしくは失敗のいずれかで完了したことを表すものです。
一方 untagged な応答はそれ以外の情報を渡すためのものです。
untagged な応答はクライアントからのコマンドの結果の情報を
渡すためにも用いられますし、そうでない(サーバのシャットダウンなど)
自発的応答にも用いられます。

これはそれぞれ
[[c:Net::IMAP::TaggedResponse]] と [[c:Net::IMAP::UntaggedResponse]]
に対応します。

untagged な応答はコマンドの送信とは非同期的にサーバから送られるため、
[[c:Net::IMAP]] オブジェクトはユーザのためこれを
[[m:Net::IMAP#responses]] に記録しておきます。

=== References

  * [IMAP]
    M. Crispin, "INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1",
    RFC 2060, December 1996.

  * [LANGUAGE-TAGS]
    Alvestrand, H., "Tags for the Identification of
    Languages", RFC 1766, March 1995.

  * [MD5]
    Myers, J., and M. Rose, "The Content-MD5 Header Field", RFC
    1864, October 1995.

  * [MIME-IMB]
    Freed, N., and N. Borenstein, "MIME (Multipurpose Internet
    Mail Extensions) Part One: Format of Internet Message Bodies", RFC
    2045, November 1996.

  * [RFC-822]
    Crocker, D., "Standard for the Format of ARPA Internet Text
    Messages", STD 11, RFC 822, University of Delaware, August 1982.

  * [RFC-2087]
    Myers, J., "IMAP4 QUOTA extension", RFC 2087, January 1997.

  * [RFC-2086]
    Myers, J., "IMAP4 ACL extension", RFC 2086, January 1997.

  * [OSSL]
    [[url:http://www.openssl.org]]

  * [RSSL]
    [[url:http://savannah.gnu.org/projects/rubypki]]

以上のうち、いくつかの RFC は obsolete になって置き換えられています。
[[RFC:2060]] は [[RFC:3501]] に、[[RFC:822]] は [[RFC:2822]] に、
置き換えられています。
