* lib/net/smtp.rb: reconstruct SMTPS/STARTTLS interface. New interface is incompatible from current 1.9 interface at all.
* lib/net/smtp.rb: All SSL-related class methods are removed; use instance methods instead. * lib/net/smtp.rb: rename methods: *ssl -> *tls (with alias "ssl"). * lib/net/smtp.rb: rename methods: *tls -> *starttls. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11993 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
da3558fddb
commit
736f3c28b0
13
ChangeLog
13
ChangeLog
@ -1,3 +1,16 @@
|
|||||||
|
Mon Mar 5 07:13:28 2007 Minero Aoki <aamine@loveruby.net>
|
||||||
|
|
||||||
|
* lib/net/smtp.rb: reconstruct SMTPS/STARTTLS interface. New
|
||||||
|
interface is incompatible from current 1.9 interface at all.
|
||||||
|
|
||||||
|
* lib/net/smtp.rb: All SSL-related class methods are removed; use
|
||||||
|
instance methods instead.
|
||||||
|
|
||||||
|
* lib/net/smtp.rb: rename methods: *ssl -> *tls (with alias
|
||||||
|
"ssl").
|
||||||
|
|
||||||
|
* lib/net/smtp.rb: rename methods: *tls -> *starttls.
|
||||||
|
|
||||||
Mon Mar 5 01:36:41 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Mon Mar 5 01:36:41 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* parse.y (parser_yylex), win32/win32.c (rb_w32_utime): fixed
|
* parse.y (parser_yylex), win32/win32.c (rb_w32_utime): fixed
|
||||||
|
174
lib/net/smtp.rb
174
lib/net/smtp.rb
@ -1,8 +1,8 @@
|
|||||||
# = net/smtp.rb
|
# = net/smtp.rb
|
||||||
#
|
#
|
||||||
# Copyright (c) 1999-2006 Yukihiro Matsumoto.
|
# Copyright (c) 1999-2007 Yukihiro Matsumoto.
|
||||||
#
|
#
|
||||||
# Copyright (c) 1999-2006 Minero Aoki.
|
# Copyright (c) 1999-2007 Minero Aoki.
|
||||||
#
|
#
|
||||||
# Written & maintained by Minero Aoki <aamine@loveruby.net>.
|
# Written & maintained by Minero Aoki <aamine@loveruby.net>.
|
||||||
#
|
#
|
||||||
@ -31,8 +31,8 @@ module Net
|
|||||||
|
|
||||||
# Module mixed in to all SMTP error classes
|
# Module mixed in to all SMTP error classes
|
||||||
module SMTPError
|
module SMTPError
|
||||||
# This *class* is module for some reason.
|
# This *class* is a module for backward compatibility.
|
||||||
# In ruby 1.9.x, this module becomes a class.
|
# In later release, this module becomes a class.
|
||||||
end
|
end
|
||||||
|
|
||||||
# Represents an SMTP authentication error.
|
# Represents an SMTP authentication error.
|
||||||
@ -169,73 +169,27 @@ module Net
|
|||||||
|
|
||||||
Revision = %q$Revision$.split[1]
|
Revision = %q$Revision$.split[1]
|
||||||
|
|
||||||
# The default SMTP port, port 25.
|
# The default SMTP port number, 25.
|
||||||
def SMTP.default_port
|
def SMTP.default_port
|
||||||
25
|
25
|
||||||
end
|
end
|
||||||
|
|
||||||
# The default SMTP/SSL port, port 465.
|
# The default mail submission port number, 587.
|
||||||
def SMTP.default_ssl_port
|
def SMTP.default_submission_port
|
||||||
465
|
|
||||||
end
|
|
||||||
|
|
||||||
# The default SMTP/TLS (STARTTLS) port, port 587.
|
|
||||||
def SMTP.default_tls_port
|
|
||||||
587
|
587
|
||||||
end
|
end
|
||||||
|
|
||||||
@ssl = false
|
# The default SMTPS port number, 465.
|
||||||
@tls = false
|
def SMTP.default_tls_port
|
||||||
@ssl_context = nil
|
465
|
||||||
|
|
||||||
# Enables SMTP/SSL for all new objects.
|
|
||||||
# +context+ is a OpenSSL::SSL::SSLContext object.
|
|
||||||
def SMTP.enable_ssl(context = SMTP.default_ssl_context)
|
|
||||||
raise 'openssl library not installed' unless defined?(OpenSSL)
|
|
||||||
raise ArgumentError, "SSL and TLS is exclusive" if @tls
|
|
||||||
@ssl = true
|
|
||||||
@ssl_context = context
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Disables SMTP/SSL for all new objects.
|
class << self
|
||||||
def SMTP.disable_ssl
|
alias default_ssl_port default_tls_port
|
||||||
@ssl = false
|
|
||||||
@ssl_context = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
# true if new objects use SMTP/SSL.
|
|
||||||
def SMTP.use_ssl?
|
|
||||||
@ssl
|
|
||||||
end
|
|
||||||
|
|
||||||
# Enables SMTP/SSL for all new objects.
|
|
||||||
# +context+ is a OpenSSL::SSL::Context object.
|
|
||||||
def SMTP.enable_tls(context = SMTP.default_ssl_context)
|
|
||||||
raise 'openssl library not installed' unless defined?(OpenSSL)
|
|
||||||
raise ArgumentError, "SSL and TLS is exclusive" if @ssl
|
|
||||||
@tls = false
|
|
||||||
@ssl_context = context
|
|
||||||
end
|
|
||||||
|
|
||||||
# Disable SMTP/TLS for all new objects.
|
|
||||||
def SMTP.disable_tls
|
|
||||||
@tls = false
|
|
||||||
@ssl_context = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
# true if new objects use SMTP/TLS.
|
|
||||||
def SMTP.use_tls?
|
|
||||||
@tls
|
|
||||||
end
|
|
||||||
|
|
||||||
def SMTP.ssl_context
|
|
||||||
@ssl_context
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def SMTP.default_ssl_context
|
def SMTP.default_ssl_context
|
||||||
ctx = OpenSSL::SSL::SSLContext.new
|
OpenSSL::SSL::SSLContext.new
|
||||||
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
||||||
ctx
|
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -259,16 +213,9 @@ module Net
|
|||||||
@read_timeout = 60
|
@read_timeout = 60
|
||||||
@error_occured = false
|
@error_occured = false
|
||||||
@debug_output = nil
|
@debug_output = nil
|
||||||
if SMTP.use_ssl? or SMTP.use_tls?
|
@tls = false
|
||||||
@ssl = true
|
@starttls = false
|
||||||
if SMTP.use_ssl?
|
@ssl_context = nil
|
||||||
@ssl_mode = :ssl
|
|
||||||
else
|
|
||||||
@ssl_mode = :tls
|
|
||||||
end
|
|
||||||
@certs = SMTP.certs
|
|
||||||
@verify = SMTP.verify
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Provide human-readable stringification of class state.
|
# Provide human-readable stringification of class state.
|
||||||
@ -294,46 +241,63 @@ module Net
|
|||||||
|
|
||||||
alias esmtp esmtp?
|
alias esmtp esmtp?
|
||||||
|
|
||||||
# true if this object uses SMTP/SSL.
|
# true if this object uses SMTPS.
|
||||||
def use_ssl?
|
def tls?
|
||||||
@ssl
|
|
||||||
end
|
|
||||||
|
|
||||||
# true if this object uses SMTP/TLS
|
|
||||||
def use_tls?
|
|
||||||
@tls
|
@tls
|
||||||
end
|
end
|
||||||
|
|
||||||
# Enables SMTP/SSL for this object. Must be called before the
|
alias ssl? tls?
|
||||||
# connection is established to have any effect.
|
|
||||||
# +context+ is a OpenSSL::SSL::SSLContext object.
|
# Enables SMTP/TLS (SMTPS: SMTP over direct TLS connection) for
|
||||||
def enable_ssl(context = SMTP.default_ssl_context)
|
# this object. Must be called before the connection is established
|
||||||
|
# to have any effect. +context+ is a OpenSSL::SSL::SSLContext object.
|
||||||
|
def enable_tls(context = SMTP.default_ssl_context)
|
||||||
raise 'openssl library not installed' unless defined?(OpenSSL)
|
raise 'openssl library not installed' unless defined?(OpenSSL)
|
||||||
raise ArgumentError, "SSL and TLS is exclusive" if @tls
|
raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @starttls
|
||||||
@ssl = true
|
@tls = true
|
||||||
@ssl_context = context
|
@ssl_context = context
|
||||||
end
|
end
|
||||||
|
|
||||||
# Disables SMTP/SSL for this object. Must be called before the
|
alias enable_ssl enable_tls
|
||||||
|
|
||||||
|
# Disables SMTP/TLS for this object. Must be called before the
|
||||||
# connection is established to have any effect.
|
# connection is established to have any effect.
|
||||||
def disable_ssl
|
def disable_tls
|
||||||
@ssl = false
|
@tls = false
|
||||||
@ssl_context = nil
|
@ssl_context = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
alias disable_ssl disable_tls
|
||||||
|
|
||||||
|
# Returns truth value if this object uses STARTTLS.
|
||||||
|
# If this object always uses STARTTLS, returns :always.
|
||||||
|
# If this object uses STARTTLS when the server support TLS, returns :auto.
|
||||||
|
def starttls?
|
||||||
|
@starttls
|
||||||
|
end
|
||||||
|
|
||||||
# Enables SMTP/TLS (STARTTLS) for this object.
|
# Enables SMTP/TLS (STARTTLS) for this object.
|
||||||
# +context+ is a OpenSSL::SSL::SSLContext object.
|
# +context+ is a OpenSSL::SSL::SSLContext object.
|
||||||
def enable_tls(context = SMTP.default_ssl_context)
|
def enable_starttls(context = SMTP.default_ssl_context)
|
||||||
raise 'openssl library not installed' unless defined?(OpenSSL)
|
raise 'openssl library not installed' unless defined?(OpenSSL)
|
||||||
raise ArgumentError, "SSL and TLS is exclusive" if @ssl
|
raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @tls
|
||||||
@tls = true
|
@starttls = :always
|
||||||
|
@ssl_context = context
|
||||||
|
end
|
||||||
|
|
||||||
|
# Enables SMTP/TLS (STARTTLS) for this object if server accepts.
|
||||||
|
# +context+ is a OpenSSL::SSL::SSLContext object.
|
||||||
|
def enable_starttls_auto(context = SMTP.default_ssl_context)
|
||||||
|
raise 'openssl library not installed' unless defined?(OpenSSL)
|
||||||
|
raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @tls
|
||||||
|
@starttls = :auto
|
||||||
@ssl_context = context
|
@ssl_context = context
|
||||||
end
|
end
|
||||||
|
|
||||||
# Disables SMTP/TLS (STARTTLS) for this object. Must be called
|
# Disables SMTP/TLS (STARTTLS) for this object. Must be called
|
||||||
# before the connection is established to have any effect.
|
# before the connection is established to have any effect.
|
||||||
def disable_tls
|
def disable_starttls
|
||||||
@ssl = false
|
@starttls = false
|
||||||
@ssl_context = nil
|
@ssl_context = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -525,20 +489,12 @@ module Net
|
|||||||
end
|
end
|
||||||
s = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
|
s = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
|
||||||
logging "Connection opened: #{@address}:#{@port}"
|
logging "Connection opened: #{@address}:#{@port}"
|
||||||
if use_ssl?
|
@socket = new_internet_message_io(tls? ? tlsconnect(s) : s)
|
||||||
s = new_ssl_socket(s)
|
|
||||||
s.connect
|
|
||||||
logging "SMTP/SSL started"
|
|
||||||
end
|
|
||||||
@socket = new_internet_message_io(s)
|
|
||||||
check_response(critical { recv_response() })
|
check_response(critical { recv_response() })
|
||||||
do_helo helo_domain
|
do_helo helo_domain
|
||||||
if use_tls?
|
if starttls?
|
||||||
s = new_ssl_socket(s)
|
|
||||||
starttls
|
starttls
|
||||||
s.connect
|
@socket = new_internet_message_io(tlsconnect(s))
|
||||||
logging "SMTP/TLS started"
|
|
||||||
@socket = new_internet_message_io(s)
|
|
||||||
# helo response may be different after STARTTLS
|
# helo response may be different after STARTTLS
|
||||||
do_helo helo_domain
|
do_helo helo_domain
|
||||||
end
|
end
|
||||||
@ -552,6 +508,14 @@ module Net
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def tlsconnect(s)
|
||||||
|
s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
|
||||||
|
logging "TLS connection started"
|
||||||
|
s.sync_close = true
|
||||||
|
s.connect
|
||||||
|
s
|
||||||
|
end
|
||||||
|
|
||||||
def new_internet_message_io(s)
|
def new_internet_message_io(s)
|
||||||
io = InternetMessageIO.new(s)
|
io = InternetMessageIO.new(s)
|
||||||
io.read_timeout = @read_timeout
|
io.read_timeout = @read_timeout
|
||||||
@ -559,12 +523,6 @@ module Net
|
|||||||
io
|
io
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_ssl_socket(s)
|
|
||||||
s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
|
|
||||||
s.sync_close = true
|
|
||||||
s
|
|
||||||
end
|
|
||||||
|
|
||||||
def do_helo(helo_domain)
|
def do_helo(helo_domain)
|
||||||
begin
|
begin
|
||||||
if @esmtp
|
if @esmtp
|
||||||
@ -872,7 +830,7 @@ module Net
|
|||||||
while true
|
while true
|
||||||
line = @socket.readline
|
line = @socket.readline
|
||||||
res << line << "\n"
|
res << line << "\n"
|
||||||
break unless line[3] == ?- # "210-PIPELINING"
|
break unless line[3,1] == '-' # "210-PIPELINING"
|
||||||
end
|
end
|
||||||
res
|
res
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user