summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-04-25 06:51:21 +0000
committerknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-04-25 06:51:21 +0000
commit74efef0be85061c3c9e24ee0cfdf5f83c2af9a22 (patch)
tree2db7641808ab4f14daf322ee4eae9786b372dc35 /lib
parent23de09d6bb2005efe55b08e90875ff6a6c6f8976 (diff)
Merge from ruby_1_8.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_7@16193 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib')
-rw-r--r--lib/net/pop.rb228
1 files changed, 173 insertions, 55 deletions
diff --git a/lib/net/pop.rb b/lib/net/pop.rb
index 6d1343eded..82cc9a747b 100644
--- a/lib/net/pop.rb
+++ b/lib/net/pop.rb
@@ -1,8 +1,8 @@
# = net/pop.rb
#
-# Copyright (c) 1999-2003 Yukihiro Matsumoto.
+# Copyright (c) 1999-2007 Yukihiro Matsumoto.
#
-# Copyright (c) 1999-2003 Minero Aoki.
+# Copyright (c) 1999-2007 Minero Aoki.
#
# Written & maintained by Minero Aoki <aamine@loveruby.net>.
#
@@ -10,18 +10,24 @@
#
# This program is free software. You can re-distribute and/or
# modify this program under the same terms as Ruby itself,
-# Ruby Distribute License or GNU General Public License.
+# Ruby Distribute License.
#
-# NOTE: You can find Japanese version of this document in
-# the doc/net directory of the standard ruby interpreter package.
+# NOTE: You can find Japanese version of this document at:
+# http://www.ruby-lang.org/ja/man/html/net_pop.html
#
# $Id$
-#
+#
# See Net::POP3 for documentation.
#
require 'net/protocol'
require 'digest/md5'
+require 'timeout'
+
+begin
+ require "openssl/ssl"
+rescue LoadError
+end
module Net
@@ -196,10 +202,19 @@ module Net
# Class Parameters
#
- # The default port for POP3 connections, port 110
def POP3.default_port
+ default_pop3_port()
+ end
+
+ # The default port for POP3 connections, port 110
+ def POP3.default_pop3_port
110
end
+
+ # The default port for POP3S connections, port 995
+ def POP3.default_pop3s_port
+ 995
+ end
def POP3.socket_type #:nodoc: obsolete
Net::InternetMessageIO
@@ -220,7 +235,7 @@ module Net
# ....
# end
#
- def POP3.APOP( isapop )
+ def POP3.APOP(isapop)
isapop ? APOP : POP3
end
@@ -244,9 +259,9 @@ module Net
# m.delete if $DELETE
# end
#
- def POP3.foreach( address, port = nil,
- account = nil, password = nil,
- isapop = false, &block ) # :yields: message
+ def POP3.foreach(address, port = nil,
+ account = nil, password = nil,
+ isapop = false, &block) # :yields: message
start(address, port, account, password, isapop) {|pop|
pop.each_mail(&block)
}
@@ -265,9 +280,9 @@ module Net
# file.write m.pop
# end
#
- def POP3.delete_all( address, port = nil,
- account = nil, password = nil,
- isapop = false, &block )
+ def POP3.delete_all(address, port = nil,
+ account = nil, password = nil,
+ isapop = false, &block)
start(address, port, account, password, isapop) {|pop|
pop.delete_all(&block)
}
@@ -287,16 +302,16 @@ module Net
# Net::POP3.auth_only('pop.example.com', 110,
# 'YourAccount', 'YourPassword', true)
#
- def POP3.auth_only( address, port = nil,
- account = nil, password = nil,
- isapop = false )
+ def POP3.auth_only(address, port = nil,
+ account = nil, password = nil,
+ isapop = false)
new(address, port, isapop).auth_only account, password
end
# Starts a pop3 session, attempts authentication, and quits.
# This method must not be called while POP3 session is opened.
# This method raises POPAuthenticationError if authentication fails.
- def auth_only( account, password )
+ def auth_only(account, password)
raise IOError, 'opening previously opened POP session' if started?
start(account, password) {
;
@@ -304,6 +319,59 @@ module Net
end
#
+ # SSL
+ #
+
+ @ssl_params = nil
+
+ # call-seq:
+ # Net::POP.enable_ssl(params = {})
+ #
+ # Enable SSL for all new instances.
+ # +params+ is passed to OpenSSL::SSLContext#set_params.
+ def POP3.enable_ssl(*args)
+ @ssl_params = create_ssl_params(*args)
+ end
+
+ def POP3.create_ssl_params(verify_or_params = {}, certs = nil)
+ begin
+ params = verify_or_params.to_hash
+ rescue NoMethodError
+ params = {}
+ params[:verify_mode] = verify_or_params
+ if certs
+ if File.file?(certs)
+ params[:ca_file] = certs
+ elsif File.directory?(certs)
+ params[:ca_path] = certs
+ end
+ end
+ end
+ return params
+ end
+
+ # Disable SSL for all new instances.
+ def POP3.disable_ssl
+ @ssl_params = nil
+ end
+
+ def POP3.ssl_params
+ return @ssl_params
+ end
+
+ def POP3.use_ssl?
+ return !@ssl_params.nil?
+ end
+
+ def POP3.verify
+ return @ssl_params[:verify_mode]
+ end
+
+ def POP3.certs
+ return @ssl_params[:ca_file] || @ssl_params[:ca_path]
+ end
+
+ #
# Session management
#
@@ -323,27 +391,28 @@ module Net
# end
# end
#
- def POP3.start( address, port = nil,
- account = nil, password = nil,
- isapop = false, &block ) # :yield: pop
+ def POP3.start(address, port = nil,
+ account = nil, password = nil,
+ isapop = false, &block) # :yield: pop
new(address, port, isapop).start(account, password, &block)
end
-
+
# Creates a new POP3 object.
#
# +address+ is the hostname or ip address of your POP3 server.
#
- # The optional +port+ is the port to connect to; it defaults to 110.
+ # The optional +port+ is the port to connect to.
#
# The optional +isapop+ specifies whether this connection is going
# to use APOP authentication; it defaults to +false+.
#
# This method does *not* open the TCP connection.
- def initialize( addr, port = nil, isapop = false )
+ def initialize(addr, port = nil, isapop = false)
@address = addr
- @port = port || self.class.default_port
+ @ssl_params = POP3.ssl_params
+ @port = port
@apop = isapop
-
+
@command = nil
@socket = nil
@started = false
@@ -361,6 +430,32 @@ module Net
@apop
end
+ # does this instance use SSL?
+ def use_ssl?
+ return !@ssl_params.nil?
+ end
+
+ # call-seq:
+ # Net::POP#enable_ssl(params = {})
+ #
+ # Enables SSL for this instance. Must be called before the connection is
+ # established to have any effect.
+ # +params[:port]+ is port to establish the SSL connection on; Defaults to 995.
+ # +params+ (except :port) is passed to OpenSSL::SSLContext#set_params.
+ def enable_ssl(verify_or_params = {}, certs = nil, port = nil)
+ begin
+ @ssl_params = verify_or_params.to_hash.dup
+ @port = @ssl_params.delete(:port) || @port
+ rescue NoMethodError
+ @ssl_params = POP3.create_ssl_params(verify_or_params, certs)
+ @port = port || @port
+ end
+ end
+
+ def disable_ssl
+ @ssl_params = nil
+ end
+
# Provide human-readable stringification of class state.
def inspect
"#<#{self.class} #{@address}:#{@port} open=#{@started}>"
@@ -379,7 +474,7 @@ module Net
# ....
# end
#
- def set_debug_output( arg )
+ def set_debug_output(arg)
@debug_output = arg
end
@@ -387,7 +482,9 @@ module Net
attr_reader :address
# The port number to connect to.
- attr_reader :port
+ def port
+ return @port || (use_ssl? ? POP3.default_pop3s_port : POP3.default_pop3_port)
+ end
# Seconds to wait until a connection is opened.
# If the POP3 object cannot open a connection within this time,
@@ -400,7 +497,7 @@ module Net
attr_reader :read_timeout
# Set the read timeout.
- def read_timeout=( sec )
+ def read_timeout=(sec)
@command.socket.read_timeout = sec if @command
@read_timeout = sec
end
@@ -418,9 +515,8 @@ module Net
# closes the session after block call finishes.
#
# This method raises a POPAuthenticationError if authentication fails.
- def start( account, password ) # :yield: pop
+ def start(account, password) # :yield: pop
raise IOError, 'POP session already started' if @started
-
if block_given?
begin
do_start account, password
@@ -434,9 +530,23 @@ module Net
end
end
- def do_start( account, password )
- @socket = self.class.socket_type.old_open(@address, @port,
- @open_timeout, @read_timeout, @debug_output)
+ def do_start(account, password)
+ s = timeout(@open_timeout) { TCPSocket.open(@address, port) }
+ if use_ssl?
+ raise 'openssl library not installed' unless defined?(OpenSSL)
+ context = OpenSSL::SSL::SSLContext.new
+ context.set_params(@ssl_params)
+ s = OpenSSL::SSL::SSLSocket.new(s, context)
+ s.sync_close = true
+ s.connect
+ if context.verify_mode != OpenSSL::SSL::VERIFY_NONE
+ s.post_connection_check(@address)
+ end
+ end
+ @socket = InternetMessageIO.new(s)
+ logging "POP session started: #{@address}:#{@port} (#{@apop ? 'APOP' : 'POP'})"
+ @socket.read_timeout = @read_timeout
+ @socket.debug_output = @debug_output
on_connect
@command = POP3Command.new(@socket)
if apop?
@@ -446,7 +556,12 @@ module Net
end
@started = true
ensure
- do_finish if not @started
+ # Authentication failed, clean up connection.
+ unless @started
+ s.close if s and not s.closed?
+ @socket = nil
+ @command = nil
+ end
end
private :do_start
@@ -526,7 +641,7 @@ module Net
# end
#
# This method raises a POPError if an error occurs.
- def each_mail( &block ) # :yield: message
+ def each_mail(&block) # :yield: message
mails().each(&block)
end
@@ -573,6 +688,10 @@ module Net
end
end
+ def logging(msg)
+ @debug_output << msg + "\n" if @debug_output
+ end
+
end # class POP3
# class aliases
@@ -600,7 +719,7 @@ module Net
#
class POPMail
- def initialize( num, len, pop, cmd ) #:nodoc:
+ def initialize(num, len, pop, cmd) #:nodoc:
@number = num
@length = len
@pop = pop
@@ -679,7 +798,7 @@ module Net
# The optional +dest+ argument is obsolete.
#
# This method raises a POPError if an error occurs.
- def top( lines, dest = '' )
+ def top(lines, dest = '')
@command.top(@number, lines) do |chunk|
dest << chunk
end
@@ -691,7 +810,7 @@ module Net
# The optional +dest+ argument is obsolete.
#
# This method raises a POPError if an error occurs.
- def header( dest = '' )
+ def header(dest = '')
top(0, dest)
end
@@ -739,7 +858,7 @@ module Net
alias uidl unique_id
- def uid=( uid ) #:nodoc: internal use only (used from POP3#set_all_uids)
+ def uid=(uid) #:nodoc: internal use only
@uid = uid
end
@@ -748,7 +867,7 @@ module Net
class POP3Command #:nodoc: internal use only
- def initialize( sock )
+ def initialize(sock)
@socket = sock
@error_occured = false
res = check_response(critical { recv_response() })
@@ -759,14 +878,14 @@ module Net
"#<#{self.class} socket=#{@socket}>"
end
- def auth( account, password )
+ def auth(account, password)
check_response_auth(critical {
check_response_auth(get_response('USER %s', account))
get_response('PASS %s', password)
})
end
- def apop( account, password )
+ def apop(account, password)
raise POPAuthenticationError, 'not APOP server; cannot login' \
unless @apop_stamp
check_response_auth(critical {
@@ -797,28 +916,28 @@ module Net
end
def rset
- check_response(critical { get_response 'RSET' })
+ check_response(critical { get_response('RSET') })
end
- def top( num, lines = 0, &block )
+ def top(num, lines = 0, &block)
critical {
getok('TOP %d %d', num, lines)
@socket.each_message_chunk(&block)
}
end
- def retr( num, &block )
+ def retr(num, &block)
critical {
getok('RETR %d', num)
@socket.each_message_chunk(&block)
}
end
- def dele( num )
+ def dele(num)
check_response(critical { get_response('DELE %d', num) })
end
- def uidl( num = nil )
+ def uidl(num = nil)
if num
res = check_response(critical { get_response('UIDL %d', num) })
return res.split(/ /)[1]
@@ -841,12 +960,12 @@ module Net
private
- def getok( fmt, *fargs )
+ def getok(fmt, *fargs)
@socket.writeline sprintf(fmt, *fargs)
check_response(recv_response())
end
- def get_response( fmt, *fargs )
+ def get_response(fmt, *fargs)
@socket.writeline sprintf(fmt, *fargs)
recv_response()
end
@@ -855,13 +974,13 @@ module Net
@socket.readline
end
- def check_response( res )
- raise POPError, res unless /\A\+OK/i === res
+ def check_response(res)
+ raise POPError, res unless /\A\+OK/i =~ res
res
end
- def check_response_auth( res )
- raise POPAuthenticationError, res unless /\A\+OK/i === res
+ def check_response_auth(res)
+ raise POPAuthenticationError, res unless /\A\+OK/i =~ res
res
end
@@ -878,4 +997,3 @@ module Net
end # class POP3Command
end # module Net
-