summaryrefslogtreecommitdiff
path: root/lib/net/pop.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/net/pop.rb')
-rw-r--r--lib/net/pop.rb230
1 files changed, 230 insertions, 0 deletions
diff --git a/lib/net/pop.rb b/lib/net/pop.rb
new file mode 100644
index 0000000000..bd4551571d
--- /dev/null
+++ b/lib/net/pop.rb
@@ -0,0 +1,230 @@
+#
+# pop.rb version 1.0.1
+#
+# author: Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+#
+
+require 'net/session'
+require 'md5'
+
+
+module Net
+
+ class POP3Session < Session
+
+ 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
+
+
+
+ class POPMail
+
+ def initialize( idx, siz, pro )
+ @num = idx
+ @size = siz
+ @proto = pro
+
+ @deleted = false
+ end
+
+ 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
+
+ end
+
+ end
+
+
+ class APOPSession < POP3Session
+
+ def proto_initialize
+ super
+ @proto_type = APOPCommand
+ end
+
+ end
+
+
+ POPSession = POP3Session
+ POP3 = POP3Session
+
+
+
+ class POP3Command < Command
+
+ 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 )
+ @socket.writeline( sprintf( 'DELE %s', num ) )
+ check_reply( SuccessCode )
+ end
+
+
+
+ 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
+
+
+
+ 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
+
+
+ unless Session::Version == '1.0.1' then
+ $stderr.puts "WARNING: wrong version of session.rb & pop.rb"
+ end
+
+end