* lib/net/pop.rb: do not dispatch LIST when a mailbox is empty.

* lib/net/pop.rb: merge the 'STAT' patch from Frank S.Fejes <frank@oopdreams.com>, with modifications (listed below).
* lib/net/pop.rb: new method Net::POP#mail_size.
* lib/net/pop.rb: new method Net::POP#bytes.
* lib/net/pop.rb: new method Net::POPCommand#stat.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
aamine 2003-03-09 16:53:30 +00:00
parent ced8bbee7c
commit 70b55f2018
2 changed files with 110 additions and 74 deletions

View File

@ -1,3 +1,16 @@
Mon Mar 10 01:59:47 2003 Minero Aoki <aamine@loveruby.net>
* lib/net/pop.rb: do not dispatch LIST when a mailbox is empty.
* lib/net/pop.rb: merge the 'STAT' patch from Frank S.Fejes
<frank@oopdreams.com>, with modifications (listed below).
* lib/net/pop.rb: new method Net::POP#mail_size.
* lib/net/pop.rb: new method Net::POP#bytes.
* lib/net/pop.rb: new method Net::POPCommand#stat.
Sun Mar 9 19:30:25 2003 WATANABE Hirofumi <eban@ruby-lang.org> Sun Mar 9 19:30:25 2003 WATANABE Hirofumi <eban@ruby-lang.org>
* lib/fileutils.rb (mkdir, mkdir_p): revert. * lib/fileutils.rb (mkdir, mkdir_p): revert.

View File

@ -2,7 +2,8 @@
= net/pop.rb = net/pop.rb
Copyright (c) 1999-2002 Yukihiro Matsumoto Copyright (c) 1999-2003 Yukihiro Matsumoto
Copyright (c) 1999-2003 Minero Aoki
written & maintained by Minero Aoki <aamine@loveruby.net> written & maintained by Minero Aoki <aamine@loveruby.net>
@ -31,14 +32,14 @@ Replace 'pop3.server.address' your POP3 server address.
require 'net/pop' require 'net/pop'
pop = Net::POP3.new( 'pop3.server.address', 110 ) pop = Net::POP3.new('pop3.server.address', 110)
pop.start( 'YourAccount', 'YourPassword' ) ### pop.start('YourAccount', 'YourPassword') ###
if pop.mails.empty? then if pop.mails.empty? then
puts 'no mail.' puts 'no mail.'
else else
i = 0 i = 0
pop.each_mail do |m| # or "pop.mails.each ..." pop.each_mail do |m| # or "pop.mails.each ..."
File.open( 'inbox/' + i.to_s, 'w' ) {|f| File.open('inbox/' + i.to_s, 'w') {|f|
f.write m.pop f.write m.pop
} }
m.delete m.delete
@ -46,7 +47,7 @@ Replace 'pop3.server.address' your POP3 server address.
end end
puts "#{pop.mails.size} mails popped." puts "#{pop.mails.size} mails popped."
end end
pop.finish ### pop.finish ###
(1) call Net::POP3#start and start POP session (1) call Net::POP3#start and start POP session
(2) access mails by using POP3#each_mail and/or POP3#mails (2) access mails by using POP3#each_mail and/or POP3#mails
@ -61,40 +62,40 @@ alternates POP3.new, POP3#start and POP3#finish.
require 'net/pop' require 'net/pop'
Net::POP3.start( 'pop3.server.address', 110 ) Net::POP3.start('pop3.server.address', 110)
'YourAccount', 'YourPassword' ) 'YourAccount', 'YourPassword')
if pop.mails.empty? then if pop.mails.empty?
puts 'no mail.' puts 'no mail.'
else else
i = 0 i = 0
pop.each_mail do |m| # or "pop.mails.each ..." pop.each_mail do |m| # or "pop.mails.each ..."
File.open( 'inbox/' + i.to_s, 'w' ) {|f| File.open('inbox/' + i.to_s, 'w') {|f|
f.write m.pop f.write m.pop
} }
m.delete m.delete
i += 1 i += 1
end end
puts "#{pop.mails.size} mails popped." puts "#{pop.mails.size} mails popped."
end end
} }
POP3#delete_all alternates #each_mail and m.delete. POP3#delete_all alternates #each_mail and m.delete.
require 'net/pop' require 'net/pop'
Net::POP3.start( 'pop3.server.address', 110, Net::POP3.start('pop3.server.address', 110,
'YourAccount', 'YourPassword' ) {|pop| 'YourAccount', 'YourPassword') {|pop|
if pop.mails.empty? then if pop.mails.empty?
puts 'no mail.' puts 'no mail.'
else else
i = 0 i = 0
pop.delete_all do |m| pop.delete_all do |m|
File.open( 'inbox/' + i.to_s, 'w' ) {|f| File.open('inbox/' + i.to_s, 'w') {|f|
f.write m.pop f.write m.pop
} }
i += 1 i += 1
end end
end end
} }
And here is more shorter example. And here is more shorter example.
@ -102,9 +103,9 @@ And here is more shorter example.
require 'net/pop' require 'net/pop'
i = 0 i = 0
Net::POP3.delete_all( 'pop3.server.address', 110, Net::POP3.delete_all('pop3.server.address', 110,
'YourAccount', 'YourPassword' ) do |m| 'YourAccount', 'YourPassword') do |m|
File.open( 'inbox/' + i.to_s, 'w' ) {|f| File.open('inbox/' + i.to_s, 'w') {|f|
f.write m.pop f.write m.pop
} }
i += 1 i += 1
@ -116,9 +117,9 @@ All examples above get mail as one big string.
This example does not create such one. This example does not create such one.
require 'net/pop' require 'net/pop'
Net::POP3.delete_all( 'pop3.server.address', 110, Net::POP3.delete_all('pop3.server.address', 110,
'YourAccount', 'YourPassword' ) do |m| 'YourAccount', 'YourPassword') do |m|
File.open( 'inbox', 'w' ) {|f| File.open('inbox', 'w') {|f|
m.pop f #### m.pop f ####
} }
end end
@ -132,8 +133,8 @@ You can use utility method, Net::POP3.APOP(). Example:
require 'net/pop' require 'net/pop'
# use APOP authentication if $isapop == true # use APOP authentication if $isapop == true
pop = Net::POP3.APOP($isapop).new( 'apop.server.address', 110 ) pop = Net::POP3.APOP($isapop).new('apop.server.address', 110)
pop.start( YourAccount', 'YourPassword' ) {|pop| pop.start(YourAccount', 'YourPassword') {|pop|
# Rest code is same. # Rest code is same.
} }
@ -151,10 +152,10 @@ You can use utility method, Net::POP3.APOP(). Example:
equals to Net::POP3.new( address, port ).start( account, password ) equals to Net::POP3.new( address, port ).start( account, password )
Net::POP3.start( addr, port, account, password ) {|pop| Net::POP3.start( addr, port, account, password ) {|pop|
pop.each_mail do |m| pop.each_mail do |m|
file.write m.pop file.write m.pop
m.delete m.delete
end end
} }
: APOP( is_apop ) : APOP( is_apop )
@ -176,8 +177,8 @@ You can use utility method, Net::POP3.APOP(). Example:
Net::POP3.start( address, port, account, password ) {|pop| Net::POP3.start( address, port, account, password ) {|pop|
pop.each_mail do |m| pop.each_mail do |m|
yield m yield m
end end
} }
# example # example
@ -302,11 +303,11 @@ A class of mail which exists on POP server.
# example # example
POP3.start( 'localhost', 110 ) {|pop3| POP3.start( 'localhost', 110 ) {|pop3|
pop3.each_mail do |m| pop3.each_mail do |m|
m.pop do |str| m.pop do |str|
# do anything # do anything
end end
end end
} }
: header : header
@ -332,6 +333,9 @@ require 'digest/md5'
module Net module Net
class BadResponseError < StandardError; end
class POP3 < Protocol class POP3 < Protocol
protocol_param :default_port, '110' protocol_param :default_port, '110'
@ -340,7 +344,6 @@ module Net
protocol_param :mail_type, '::Net::POPMail' protocol_param :mail_type, '::Net::POPMail'
protocol_param :socket_type, '::Net::InternetMessageIO' protocol_param :socket_type, '::Net::InternetMessageIO'
def POP3.APOP( isapop ) def POP3.APOP( isapop )
isapop ? APOP : POP3 isapop ? APOP : POP3
end end
@ -364,15 +367,13 @@ module Net
new(address, port).auth_only account, password new(address, port).auth_only account, password
end end
def auth_only( account, password ) def auth_only( account, password )
raise IOError, 'opening already opened POP session' if active? raise IOError, 'opening already opened POP session' if active?
start(account, password) { start(account, password) {
# none ;
} }
end end
# #
# connection # connection
# #
@ -393,7 +394,7 @@ module Net
def conn_command def conn_command
@command = (@apop ? self.class.apop_command_type : @command = (@apop ? self.class.apop_command_type :
self.class.command_type).new(socket()) self.class.command_type ).new(socket())
end end
def do_finish def do_finish
@ -402,15 +403,31 @@ module Net
disconn_socket disconn_socket
end end
# #
# POP operations # POP operations
# #
public public
def mail_size
return @nmails if @nmails
@nmails, @bytes = command().stat
@nmails
end
def bytes
return @bytes if @bytes
@nmails, @bytes = command().stat
@bytes
end
def mails def mails
return @mails if @mails return @mails if @mails
if mail_size() == 0
# some popd raises error for LIST on the empty mailbox.
@mails = []
return @mails
end
mails = [] mails = []
mailclass = self.class.mail_type mailclass = self.class.mail_type
@ -418,6 +435,8 @@ module Net
mails.push mailclass.new(idx, size, command()) if size mails.push mailclass.new(idx, size, command()) if size
end end
@mails = mails.freeze @mails = mails.freeze
@mails
end end
def each_mail( &block ) def each_mail( &block )
@ -436,28 +455,28 @@ module Net
def reset def reset
command().rset command().rset
mails().each do |m| mails().each do |m|
m.instance_eval { @deleted = false } m.instance_eval {
@deleted = false
}
end end
end end
def command def command
io_check io_check
super super
end end
def io_check def io_check
(not socket() or socket().closed?) and raise IOError, 'POP session is not opened yet'\
raise IOError, 'POP session is not opened yet' if not socket() or socket().closed?
end end
end end
POP = POP3 POP = POP3
POPSession = POP3 POPSession = POP3
POP3Session = POP3 POP3Session = POP3
class APOP < POP3 class APOP < POP3
def APOP.command_type def APOP.command_type
APOPCommand APOPCommand
@ -477,16 +496,14 @@ module Net
@deleted = false @deleted = false
end end
attr :size attr_reader :size
def inspect def inspect
"#<#{self.class} #{@num}#{@deleted ? ' deleted' : ''}>" "#<#{self.class} #{@num}#{@deleted ? ' deleted' : ''}>"
end end
def pop( dest = '', &block ) def pop( dest = '', &block )
if block dest = ReadAdapter.new(block) if block
dest = ReadAdapter.new(block)
end
@command.retr @num, dest @command.retr @num, dest
end end
@ -539,16 +556,25 @@ module Net
end end
def list def list
arr = []
atomic { atomic {
getok 'LIST' getok 'LIST'
list = []
@socket.each_list_item do |line| @socket.each_list_item do |line|
m = /\A(\d+)[ \t]+(\d+)/.match(line) or m = /\A(\d+)[ \t]+(\d+)/.match(line) or
raise BadResponse, "illegal response: #{line}" list[m[1].to_i] = m[2].to_i
arr[m[1].to_i] = m[2].to_i
end end
return list
}
end
def stat
atomic {
@socket.writeline 'STAT'
line = @socket.readline
m = /\A\+OK (\d+)[ \t]+(\d+)/.match(line) or
raise BadResponseError, "illegal response: #{line}"
return [m[1].to_i, m[2].to_i]
} }
arr
end end
def rset def rset
@ -602,7 +628,6 @@ module Net
def get_reply def get_reply
str = @socket.readline str = @socket.readline
if /\A\+/ === str if /\A\+/ === str
Response.new(SuccessCode, str[0,3], str[3, str.size - 3].strip) Response.new(SuccessCode, str[0,3], str[3, str.size - 3].strip)
else else
@ -616,10 +641,8 @@ module Net
class APOPCommand < POP3Command class APOPCommand < POP3Command
def initialize( sock ) def initialize( sock )
response = super(sock) @stamp = super(sock).message.slice(/<.+>/) or
m = /<.+>/.match(response.msg) or
raise ProtoAuthError.new("not APOP server: cannot login", nil) raise ProtoAuthError.new("not APOP server: cannot login", nil)
@stamp = m[0]
end end
def auth( account, pass ) def auth( account, pass )