1999-10-13 03:29:15 -04:00
|
|
|
=begin
|
|
|
|
|
1999-10-18 05:03:16 -04:00
|
|
|
= Net module version 1.0.3 reference manual
|
1999-10-13 03:29:15 -04:00
|
|
|
|
|
|
|
pop.rb written by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
|
|
|
|
|
|
|
|
This library is distributed under the terms of Ruby style license.
|
|
|
|
You can freely distribute/modify/copy this file.
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
1999-09-22 03:32:33 -04:00
|
|
|
|
|
|
|
require 'net/session'
|
|
|
|
require 'md5'
|
|
|
|
|
|
|
|
|
|
|
|
module Net
|
|
|
|
|
1999-10-13 03:29:15 -04:00
|
|
|
=begin
|
|
|
|
|
|
|
|
== Net::POP3Session
|
|
|
|
|
|
|
|
=== Super Class
|
|
|
|
|
|
|
|
Net::Session
|
|
|
|
|
|
|
|
=== Class Methods
|
|
|
|
|
|
|
|
: new( address = 'localhost', port = 110 )
|
|
|
|
|
|
|
|
This method create a new POP3Session object but this will not open connection.
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
1999-09-22 03:32:33 -04:00
|
|
|
class POP3Session < Session
|
|
|
|
|
1999-10-13 03:29:15 -04:00
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
=== Methods
|
|
|
|
|
|
|
|
: start( account, password )
|
|
|
|
|
|
|
|
This method start POP session.
|
|
|
|
|
|
|
|
: each{|popmail| ...}
|
|
|
|
|
|
|
|
This method is equals to "POP3Session.mails.each"
|
|
|
|
|
|
|
|
: mails
|
|
|
|
|
|
|
|
This method returns an array of <a href="#popi">POP3Session::POPMail</a>.
|
|
|
|
This array is renewed when login.
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
1999-09-22 03:32:33 -04:00
|
|
|
attr :mails
|
|
|
|
|
|
|
|
def each() @mails.each{|m| yield m} end
|
|
|
|
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
|
|
|
|
def proto_initialize
|
|
|
|
@proto_type = POP3Command
|
|
|
|
@port = 110
|
|
|
|
@mails = [].freeze
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def do_start( acnt, pwd )
|
|
|
|
@proto.auth( acnt, pwd )
|
|
|
|
@mails = []
|
|
|
|
@proto.list.each_with_index do |size,idx|
|
|
|
|
if size then
|
|
|
|
@mails.push POPMail.new( idx, size, @proto )
|
|
|
|
end
|
|
|
|
end
|
|
|
|
@mails.freeze
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def do_finish
|
|
|
|
@proto.quit
|
|
|
|
end
|
|
|
|
|
|
|
|
|
1999-10-13 03:29:15 -04:00
|
|
|
=begin
|
|
|
|
|
|
|
|
== Net::POP3Session::POPMail
|
|
|
|
|
|
|
|
A class of mail which exists on POP server.
|
|
|
|
|
|
|
|
=== Super Class
|
|
|
|
|
|
|
|
Object
|
|
|
|
|
|
|
|
=end
|
1999-09-22 03:32:33 -04:00
|
|
|
|
|
|
|
class POPMail
|
|
|
|
|
|
|
|
def initialize( idx, siz, pro )
|
|
|
|
@num = idx
|
|
|
|
@size = siz
|
|
|
|
@proto = pro
|
|
|
|
|
|
|
|
@deleted = false
|
|
|
|
end
|
|
|
|
|
1999-10-13 03:29:15 -04:00
|
|
|
=begin
|
|
|
|
|
|
|
|
=== Method
|
|
|
|
|
|
|
|
: all
|
|
|
|
: pop
|
|
|
|
: mail
|
|
|
|
|
|
|
|
This method fetches a mail and return it.
|
|
|
|
|
|
|
|
: header
|
|
|
|
|
|
|
|
This method fetches only mail header.
|
|
|
|
|
|
|
|
: top( lines )
|
|
|
|
|
|
|
|
This method fetches mail header and 'lines' lines body.
|
|
|
|
|
|
|
|
: delete
|
|
|
|
: delete!
|
|
|
|
|
|
|
|
This method deletes mail.
|
|
|
|
|
|
|
|
: size
|
|
|
|
|
|
|
|
size of mail(bytes)
|
|
|
|
|
|
|
|
: deleted?
|
|
|
|
|
|
|
|
true if mail was deleted
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
1999-09-22 03:32:33 -04:00
|
|
|
attr :size
|
|
|
|
|
|
|
|
def all( dest = '' )
|
|
|
|
@proto.retr( @num, dest )
|
|
|
|
end
|
|
|
|
alias pop all
|
|
|
|
alias mail all
|
|
|
|
|
|
|
|
def top( lines, dest = '' )
|
|
|
|
@proto.top( @num, lines, dest )
|
|
|
|
end
|
|
|
|
|
|
|
|
def header( dest = '' )
|
|
|
|
top( 0, dest )
|
|
|
|
end
|
|
|
|
|
|
|
|
def delete
|
|
|
|
@proto.dele( @num )
|
|
|
|
@deleted = true
|
|
|
|
end
|
|
|
|
alias delete! delete
|
|
|
|
|
|
|
|
def deleted?
|
|
|
|
@deleted
|
|
|
|
end
|
|
|
|
|
1999-10-18 05:03:16 -04:00
|
|
|
def uidl
|
|
|
|
@proto.uidl @num
|
|
|
|
end
|
|
|
|
|
1999-09-22 03:32:33 -04:00
|
|
|
end
|
|
|
|
|
1999-10-13 03:29:15 -04:00
|
|
|
end # POP3Session
|
|
|
|
|
|
|
|
POPSession = POP3Session
|
|
|
|
POP3 = POP3Session
|
|
|
|
|
1999-09-22 03:32:33 -04:00
|
|
|
|
1999-10-13 03:29:15 -04:00
|
|
|
=begin
|
|
|
|
|
|
|
|
== Net::APOP3Session
|
|
|
|
|
|
|
|
This class has no new methods. Only way of authetication is changed.
|
|
|
|
|
|
|
|
=== Super Class
|
|
|
|
|
|
|
|
Net::POP3Session
|
|
|
|
|
|
|
|
=end
|
1999-09-22 03:32:33 -04:00
|
|
|
|
|
|
|
class APOPSession < POP3Session
|
|
|
|
|
|
|
|
def proto_initialize
|
|
|
|
super
|
|
|
|
@proto_type = APOPCommand
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
1999-10-13 03:29:15 -04:00
|
|
|
APOP = APOPSession
|
1999-09-22 03:32:33 -04:00
|
|
|
|
|
|
|
|
1999-10-13 03:29:15 -04:00
|
|
|
=begin
|
|
|
|
|
|
|
|
== Net::POP3Command
|
|
|
|
|
|
|
|
POP3 protocol class.
|
|
|
|
|
|
|
|
=== Super Class
|
|
|
|
|
|
|
|
Net::Command
|
|
|
|
|
|
|
|
=== Class Methods
|
1999-09-22 03:32:33 -04:00
|
|
|
|
1999-10-13 03:29:15 -04:00
|
|
|
: new( socket )
|
|
|
|
|
|
|
|
This method creates new POP3Command object. 'socket' must be ProtocolSocket.
|
|
|
|
|
|
|
|
=end
|
1999-09-22 03:32:33 -04:00
|
|
|
|
|
|
|
class POP3Command < Command
|
|
|
|
|
1999-10-18 05:03:16 -04:00
|
|
|
def initialize( sock )
|
|
|
|
@uidl = nil
|
|
|
|
super
|
|
|
|
end
|
|
|
|
|
1999-10-13 03:29:15 -04:00
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
=== Methods
|
|
|
|
|
|
|
|
: auth( account, password )
|
|
|
|
|
|
|
|
This method do POP authorization (no RPOP)
|
|
|
|
In case of failed authorization, raises Protocol::ProtocolError exception.
|
|
|
|
|
|
|
|
: list
|
|
|
|
|
|
|
|
a list of mails which existing on server.
|
|
|
|
The list is an array like "array[ number ] = size".
|
|
|
|
|
|
|
|
ex:
|
|
|
|
|
|
|
|
The list from server is
|
|
|
|
|
|
|
|
1 2452
|
|
|
|
2 3355
|
|
|
|
4 9842
|
|
|
|
:
|
|
|
|
|
|
|
|
then, an array is
|
|
|
|
|
|
|
|
[ nil, 2452, 3355, nil, 9842, ... ]
|
|
|
|
|
|
|
|
: quit
|
|
|
|
|
|
|
|
This method finishes POP3 session.
|
|
|
|
|
|
|
|
: rset
|
|
|
|
|
|
|
|
This method reset all changes done in current session,
|
|
|
|
by sending 'RSET' command.
|
|
|
|
|
|
|
|
: top( num, lines = 0 )
|
|
|
|
|
|
|
|
This method gets all mail header and 'lines' lines body
|
|
|
|
by sending 'TOP' command. 'num' is mail number.
|
|
|
|
|
|
|
|
WARNING: the TOP command is 'Optional' in RFC1939 (POP3)
|
|
|
|
|
|
|
|
|
|
|
|
: retr( num : Integer )
|
|
|
|
|
|
|
|
This method gets a mail by 'RETR' command. 'num' is mail number.
|
|
|
|
|
|
|
|
|
|
|
|
: dele( num : Integer )
|
|
|
|
|
|
|
|
This method deletes a mail on server by 'DELE'.
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
1999-09-22 03:32:33 -04:00
|
|
|
def auth( acnt, pass )
|
|
|
|
@socket.writeline( 'USER ' + acnt )
|
|
|
|
check_reply_auth
|
|
|
|
|
|
|
|
@socket.writeline( 'PASS ' + pass )
|
|
|
|
ret = check_reply_auth
|
|
|
|
|
|
|
|
return ret
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def list
|
|
|
|
@socket.writeline( 'LIST' )
|
|
|
|
check_reply( SuccessCode )
|
|
|
|
|
|
|
|
arr = []
|
|
|
|
@socket.read_pendlist do |line|
|
|
|
|
num, siz = line.split( / +/o )
|
|
|
|
arr[ num.to_i ] = siz.to_i
|
|
|
|
end
|
|
|
|
|
|
|
|
return arr
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def rset
|
|
|
|
@socket.writeline( 'RSET' )
|
|
|
|
check_reply( SuccessCode )
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def top( num, lines = 0, dest = '' )
|
|
|
|
@socket.writeline( sprintf( 'TOP %d %d', num, lines ) )
|
|
|
|
check_reply( SuccessCode )
|
|
|
|
|
|
|
|
return @socket.read_pendstr( dest )
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def retr( num, dest = '', &block )
|
|
|
|
@socket.writeline( sprintf( 'RETR %d', num ) )
|
|
|
|
check_reply( SuccessCode )
|
|
|
|
|
|
|
|
return @socket.read_pendstr( dest, &block )
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def dele( num )
|
1999-10-18 05:03:16 -04:00
|
|
|
@socket.writeline( 'DELE ' + num.to_s )
|
1999-09-22 03:32:33 -04:00
|
|
|
check_reply( SuccessCode )
|
|
|
|
end
|
|
|
|
|
|
|
|
|
1999-10-18 05:03:16 -04:00
|
|
|
def uidl( num )
|
|
|
|
@socket.writeline( 'UIDL ' + num.to_s )
|
|
|
|
rep = check_reply( SuccessCode )
|
|
|
|
uid = rep.msg.split(' ')[1]
|
|
|
|
|
|
|
|
uid
|
|
|
|
end
|
|
|
|
|
1999-09-22 03:32:33 -04:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
|
|
|
|
def do_quit
|
|
|
|
@socket.writeline( 'QUIT' )
|
|
|
|
check_reply( SuccessCode )
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def check_reply_auth
|
|
|
|
begin
|
|
|
|
cod = check_reply( SuccessCode )
|
|
|
|
rescue ProtocolError
|
|
|
|
raise ProtoAuthError, 'Fail to POP authentication'
|
|
|
|
end
|
|
|
|
|
|
|
|
return cod
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def get_reply
|
|
|
|
str = @socket.readline
|
|
|
|
|
|
|
|
if /\A\+/ === str then
|
|
|
|
return SuccessCode.new( str[0,3], str[3, str.size - 3].strip )
|
|
|
|
else
|
|
|
|
return ErrorCode.new( str[0,4], str[4, str.size - 4].strip )
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
1999-10-13 03:29:15 -04:00
|
|
|
=begin
|
|
|
|
|
|
|
|
== APOPCommand
|
|
|
|
|
|
|
|
=== Super Class
|
|
|
|
|
|
|
|
POP3
|
|
|
|
|
|
|
|
=== Methods
|
|
|
|
|
|
|
|
: auth( account, password )
|
|
|
|
|
|
|
|
This method do authorization by sending 'APOP' command.
|
|
|
|
If server is not APOP server, this raises Net::ProtoAuthError exception.
|
|
|
|
On other errors, raises Net::ProtocolError.
|
|
|
|
|
|
|
|
=end
|
1999-09-22 03:32:33 -04:00
|
|
|
|
|
|
|
class APOPCommand < POP3Command
|
|
|
|
|
|
|
|
def initialize( sock )
|
|
|
|
rep = super( sock )
|
|
|
|
|
|
|
|
/<[^@]+@[^@>]+>/o === rep.msg
|
|
|
|
@stamp = $&
|
|
|
|
unless @stamp then
|
|
|
|
raise ProtoAuthError, "This is not APOP server: can't login"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def auth( acnt, pass )
|
|
|
|
@socket.writeline( "APOP #{acnt} #{digest(@stamp + pass)}" )
|
|
|
|
return check_reply_auth
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def digest( str )
|
|
|
|
temp = MD5.new( str ).digest
|
|
|
|
|
|
|
|
ret = ''
|
|
|
|
temp.each_byte do |i|
|
|
|
|
ret << sprintf( '%02x', i )
|
|
|
|
end
|
|
|
|
return ret
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
1999-10-18 05:03:16 -04:00
|
|
|
unless Session::Version == '1.0.3' then
|
1999-09-22 03:32:33 -04:00
|
|
|
$stderr.puts "WARNING: wrong version of session.rb & pop.rb"
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|