library net/imap

要約

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

IMAP の概要

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

メールボックス内のメッセージ(メール)を処理する場合、まず Net::IMAP#select もしくは 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)の送り元とサブジェクトを表示する。

require 'net/imap'

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" へ移動させる

require 'net/imap'

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 は並列実行をサポートしています。例として、

require '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

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

これらのエラーはそれぞれ

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

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

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

tagged response と untagged response

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

これはそれぞれ Net::IMAP::TaggedResponseNet::IMAP::UntaggedResponse に対応します。

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

References

以上のうち、いくつかの RFC は obsolete になって置き換えられています。 [RFC2060][RFC3501] に、[RFC822][RFC2822] に、置き換えられています。

クラス

Net::IMAP

IMAP 接続を表現するクラスです。

Net::IMAP::FetchData

FETCH コマンドの応答を表すクラスです。

Net::IMAP::Address

メールアドレスを表すクラスです。

Net::IMAP::BodyTypeBasic

text 型(Net::IMAP::BodyTypeText)、 multipart 型(Net::IMAP::BodyTypeMultipart)、 message 型(Net::IMAP::BodyTypeMessage)、のいずれでもないようなメッセージボディ構造を表すクラスです。

Net::IMAP::BodyTypeMessage

Content-Type が "message" であるメッセージを表すクラスです。

Net::IMAP::BodyTypeMultipart

マルチパートなメッセージを表すクラスです。

Net::IMAP::BodyTypeText

Content-Type が text であるメッセージを表すクラスです。

Net::IMAP::ContentDisposition

[RFC1806], [RFC2183] で定義されている MIME の Content-Disposition フィールドを表すクラスです。

Net::IMAP::ContinuationRequest

IMAP の continuation request (命令継続要求) を表すクラスです。

Net::IMAP::Envelope

メッセージのエンベロープを表すクラスです。

Net::IMAP::MailboxACLItem

GETACL の応答の各要素を表すクラスです。

Net::IMAP::MailboxList

Net::IMAP#listNet::IMAP#xlistNet::IMAP#lsub で返されるメールボックスのデータを表します。

Net::IMAP::MailboxQuota

Net::IMAP#getquotaNet::IMAP#getquotaroot で得られる quota の情報を表すオブジェクトです。

Net::IMAP::MailboxQuotaRoot

Net::IMAP#getquotaroot の結果として得られる quota root 情報を表わすオブジェクトです。

Net::IMAP::ResponseCode

応答のレスポンスコードを表すクラスです。

Net::IMAP::ResponseText

応答のテキストを表すクラスです。

Net::IMAP::StatusData

STATUS 応答を表わすクラスです。

Net::IMAP::TaggedResponse

IMAP のタグ付きレスポンスを表すクラスです。

Net::IMAP::ThreadMember

Net::IMAP#threadNet::IMAP#uid_thread から得られるスレッドの木構造のノードを表すクラスです。

Net::IMAP::UntaggedResponse

IMAP のタグ付きレスポンスを表すクラスです。

例外クラス

Net::IMAP::Error

すべての IMAP 例外クラスのスーパークラス。

  Net::IMAP::DataFormatError

データフォーマットが正しくない場合に発生する例外のクラスです。

  Net::IMAP::FlagCountError

サーバからのレスポンスに含まれるフラグが多すぎるときに発生する例外です。

  Net::IMAP::ResponseError

サーバからのレスポンスがエラーを示している場合に発生する例外のクラスです。

   Net::IMAP::BadResponseError

サーバから "BAD" レスポンスが来た場合に発生する例外のクラスです。クライアントからのコマンドが IMAP の規格から外れている場合やサーバ内部エラーの場合に発生します。

   Net::IMAP::ByeResponseError

サーバから "BYE" レスポンスが来た場合に発生する例外のクラスです。ログインが拒否された場合や、クライアントが無反応でタイムアウトした場合に発生します。

   Net::IMAP::NoResponseError

サーバから "NO" レスポンスが来た場合に発生する例外のクラスです。コマンドが正常に完了しなかった場合に発生します。

  Net::IMAP::ResponseParseError

サーバからのレスポンスが正しくパースできない場合に発生する例外のクラスです。