このライブラリは、POP3 (Post Office Protocol version 3) を用いてPOPサーバからメールを受信する機能を提供するライブラリです。
POP3 の実装は [RFC1939] に基いています。
[RFC2449] で定義されているPOP3拡張には対応していません。
以下のコードは、メールを受信してファイル 'inbox/1' 'inbox/2'... に書きこみ、サーバ上からメールを消します。
'pop.example.com' は適当なPOP3のサーバのホスト名に、 'YourAccount' と 'YourPassword' は適当なアカウント名とパスワードに適宜読みかえてください。
require 'net/pop' pop = Net::POP3.new('pop.example.com', 110) pop.start('YourAccount', 'YourPassword') # POPのセッションを開始 if pop.mails.empty? $stderr.puts 'no mail.' else pop.mails.each_with_index do |m, idx| # 各メッセージにアクセスする File.open("inbox/#{idx + 1}", 'w') {|f| f.write m.pop } m.delete end $stderr.puts "#{pop.mails.size} mails popped." end pop.finish # セッションを終了する
POP サーバはネットワークのむこうに存在するので、なにか仕事をさせるにはその前に開始手続きを、終わったら終了手続きを、行わなければいけません。それを行うのが Net::POP3#start と Net::POP3#finish で、 POP3 オブジェクトはその二つのメソッドの間でだけ有効になります。
サーバ上のメールは Net::POPMail オブジェクトとして表現されており、このオブジェクトのメソッドを呼ぶことでメールを取ってきたり消したりすることができます。Net::POP3#mails はこの Net::POPMail オブジェクトの配列であり、 Net::POP3#each_mail はさらに pop.mails.each のショートカットです。
上の例はあえて省略や短縮用メソッドを避けたためにかなり冗長です。まず、ブロック付きの Net::POP3.start を使うことで POP3.new, #start, #finish を併合できます。
require 'net/pop' Net::POP3.start('pop.example.com', 110, 'YourAccount', 'YourPassword') {|pop| if pop.mails.empty? $stderr.puts 'no mail.' else pop.mails.each_with_index do |m, idx| File.open("inbox/#{idx + 1}", 'w') {|f| f.write m.pop } m.delete end $stderr.puts "#{pop.mails.size} mails popped." end }
Net::POP3#delete_all を使うとさらに Net::POP3#each_mail と Net::POPMail#delete を併合できます。
require 'net/pop' Net::POP3.start('pop.example.com', 110, 'YourAccount', 'YourPassword') {|pop| if pop.mails.empty? $stderr.puts 'no mail.' else i = 0 pop.delete_all do |m| File.open("inbox/#{i}", 'w') {|f| f.write m.pop } i += 1 end end }
クラスメソッドの Net::POP3.delete_all を使うとさらに短くなります。
require 'net/pop' i = 0 Net::POP3.delete_all('pop.example.com', 110, 'YourAccount', 'YourPassword') do |m| File.open("inbox/#{i}", 'w') {|f| f.write m.pop } i += 1 end
これまでの例では Net::POPMail#pop を使い、メールをひとつの文字列としてうけとっていました。しかし、もしメールが 100MB を越えるような巨大なメールだった場合、この方法ではまずいかもしれません。そのような場合は以下のように Net::POPMail#pop に File オブジェクトを与える手が使えます。
require 'net/pop' i = 0 Net::POP3.delete_all('pop.example.com', 110, 'YourAccount', 'YourPassword') do |m| File.open('inbox/#{i}', 'w') {|f| m.pop f } i += 1 end
Net::POPMail#popにブロックを渡すと、メールデータを細かく分割してブロックを呼びだします。この機能を使って同様のことができます。
require 'net/pop' i = 0 Net::POP3.delete_all('pop.example.com', 110, 'YourAccount', 'YourPassword') do |m| File.open('inbox/#{i}', 'w') {|f| m.pop {|chunk| f.write(chunk) } } i += 1 end
Net::POP3 クラスのかわりに Net::APOP クラスを使うと、認証時に APOP を使うようになります。また動的にノーマル POP と APOP を選択するには、以下のように Net::POP3.APOP メソッドを使うのが便利です。
require 'net/pop' # use APOP authentication if $isapop == true pop = Net::POP3.APOP($isapop).new('apop.example.com', 110) pop.start('YourAccount', 'YourPassword') {|pop| # 残りのコードは同じ }
この方法はクラス自体を変えるので、クラスメソッドの start や foreach、 delete_all、auth_only なども APOP とともに使えます。
利用しているPOP3サーバが UIDL 機能を提供している場合には、以下のようにして特定のメールだけを取り出すことができます。
require 'net/pop' def need_pop?(id) # 取り出したいメールの場合に真を返す end Net::POP3.start('pop.example.com', 110, 'Your account', 'Your password') do |pop| pop.mails.select { |m| need_pop?(m.unique_id) }.each do |m| do_something(m.pop) end end
Net::POPMail#unique_id はメッセージのユニークIDを文字列で返します。これは通常そのメッセージのハッシュ値です。
このライブラリは pop3s と呼ばれる、995番ポートを使いPOP3の通信全体を SSLで包む方法での通信の認証および暗号化が可能です。この方法は標準化されていません。
[RFC2595] で定義されている STLS 拡張による TLS の利用はできません。
Net::POP3#enable_ssl でそのオブジェクトが SSL を利用するように設定します。
また、Net::POP3.enable_ssl で以降生成されるすべての Net::POP3 オブジェクトで SSL を利用するように設定できます。グローバルに状態を変更するのであまり利用しないほうがよいでしょう。
Net::POP | Alias of Net::POP3 |
Net::POP3 | POP3 のセッションを表すクラスです。 |
Net::APOP | このクラスでは新しいメソッドは導入していません。認証方式が APOP に変わるだけです。 |
Net::APOPSession | Alias of Net::APOP |
Net::POPMail | POP サーバー上のメール一通を表現するクラス。 |
Net::POPSession | Alias of Net::POP3 |
Net::POPAuthenticationError | POP3 で認証に失敗したときに発生します。 |
Net::POPError | POP3 の、認証以外のエラーが起きたときに発生します。サーバからの "-ERR" 応答コードに対応します。 |
Net::POPBadResponse | サーバから予期しないレスポンスが帰ってきたときに発生します。 |