lib/net/smtp.rb in net-smtp-0.4.0.1 vs lib/net/smtp.rb in net-smtp-0.5.0
- old
+ new
@@ -77,46 +77,48 @@
#
# == What is This Library?
#
# This library provides functionality to send internet
- # mail via SMTP, the Simple Mail Transfer Protocol. For details of
- # SMTP itself, see [RFC5321] (http://www.ietf.org/rfc/rfc5321.txt).
- # This library also implements SMTP authentication, which is often
+ # mail via \SMTP, the Simple Mail Transfer Protocol. For details of
+ # \SMTP itself, see [RFC5321[https://www.rfc-editor.org/rfc/rfc5321.txt]].
+ # This library also implements \SMTP authentication, which is often
# necessary for message composers to submit messages to their
- # outgoing SMTP server, see
- # [RFC6409](http://www.ietf.org/rfc/rfc6503.txt),
- # and [SMTPUTF8](http://www.ietf.org/rfc/rfc6531.txt), which is
+ # outgoing \SMTP server, see
+ # [RFC6409[https://www.rfc-editor.org/rfc/rfc6409.html]],
+ # and [SMTPUTF8[https://www.rfc-editor.org/rfc/rfc6531.txt]], which is
# necessary to send messages to/from addresses containing characters
# outside the ASCII range.
#
# == What is This Library NOT?
#
# This library does NOT provide functions to compose internet mails.
# You must create them by yourself. If you want better mail support,
- # try RubyMail or TMail or search for alternatives in
+ # try the mail[https://rubygems.org/gems/mail] or
+ # rmail[https://rubygems.org/gems/rmail] gems, or search for alternatives in
# {RubyGems.org}[https://rubygems.org/] or {The Ruby
# Toolbox}[https://www.ruby-toolbox.com/].
#
- # FYI: the official specification on internet mail is: [RFC5322] (http://www.ietf.org/rfc/rfc5322.txt).
+ # FYI: the official specification on internet mail is:
+ # [RFC5322[https://www.rfc-editor.org/rfc/rfc5322.txt]].
#
# == Examples
#
# === Sending Messages
#
- # You must open a connection to an SMTP server before sending messages.
- # The first argument is the address of your SMTP server, and the second
+ # You must open a connection to an \SMTP server before sending messages.
+ # The first argument is the address of your \SMTP server, and the second
# argument is the port number. Using SMTP.start with a block is the simplest
# way to do this. This way, the SMTP connection is closed automatically
# after the block is executed.
#
# require 'net/smtp'
# Net::SMTP.start('your.smtp.server', 25) do |smtp|
# # Use the SMTP object smtp only in this block.
# end
#
- # Replace 'your.smtp.server' with your SMTP server. Normally
+ # Replace 'your.smtp.server' with your \SMTP server. Normally
# your system manager or internet provider supplies a server
# for you.
#
# Then you can send messages.
#
@@ -145,11 +147,11 @@
# # using SMTP#finish
# smtp = Net::SMTP.start('your.smtp.server', 25)
# smtp.send_message msgstr, 'from@address', 'to@address'
# smtp.finish
#
- # You can also use the block form of SMTP.start/SMTP#start. This closes
+ # You can also use the block form of SMTP.start or SMTP#start. This closes
# the SMTP session automatically:
#
# # using block form of SMTP.start
# Net::SMTP.start('your.smtp.server', 25) do |smtp|
# smtp.send_message msgstr, 'from@address', 'to@address'
@@ -158,38 +160,41 @@
# I strongly recommend this scheme. This form is simpler and more robust.
#
# === HELO domain
#
# In almost all situations, you must provide a third argument
- # to SMTP.start/SMTP#start. This is the domain name which you are on
+ # to SMTP.start or SMTP#start. This is the domain name which you are on
# (the host to send mail from). It is called the "HELO domain".
- # The SMTP server will judge whether it should send or reject
+ # The \SMTP server will judge whether it should send or reject
# the SMTP session by inspecting the HELO domain.
#
- # Net::SMTP.start('your.smtp.server', 25
- # helo: 'mail.from.domain') { |smtp| ... }
+ # Net::SMTP.start('your.smtp.server', 25, helo: 'mail.from.domain') do |smtp|
+ # smtp.send_message msgstr, 'from@address', 'to@address'
+ # end
#
- # === SMTP Authentication
+ # === \SMTP Authentication
#
- # The Net::SMTP class supports three authentication schemes;
- # PLAIN, LOGIN and CRAM MD5. (SMTP Authentication: [RFC2554])
- # To use SMTP authentication, pass extra arguments to
- # SMTP.start/SMTP#start.
+ # The Net::SMTP class supports the \SMTP extension for SASL Authentication
+ # [RFC4954[https://www.rfc-editor.org/rfc/rfc4954.html]] and the following
+ # SASL mechanisms: +PLAIN+, +LOGIN+ _(deprecated)_, and +CRAM-MD5+
+ # _(deprecated)_.
#
+ # To use \SMTP authentication, pass extra arguments to
+ # SMTP.start or SMTP#start.
+ #
# # PLAIN
- # Net::SMTP.start('your.smtp.server', 25
+ # Net::SMTP.start('your.smtp.server', 25,
# user: 'Your Account', secret: 'Your Password', authtype: :plain)
- # # LOGIN
- # Net::SMTP.start('your.smtp.server', 25
- # user: 'Your Account', secret: 'Your Password', authtype: :login)
#
- # # CRAM MD5
- # Net::SMTP.start('your.smtp.server', 25
- # user: 'Your Account', secret: 'Your Password', authtype: :cram_md5)
+ # Support for other SASL mechanisms-such as +EXTERNAL+, +OAUTHBEARER+,
+ # +SCRAM-SHA-256+, and +XOAUTH2+-will be added in a future release.
#
+ # The +LOGIN+ and +CRAM-MD5+ mechanisms are still available for backwards
+ # compatibility, but are deprecated and should be avoided.
+ #
class SMTP < Protocol
- VERSION = "0.4.0.1"
+ VERSION = "0.5.0"
# The default SMTP port number, 25.
def SMTP.default_port
25
end
@@ -227,14 +232,17 @@
#
# If +tls_verify+ is true, verify the server's certificate. The default is true.
# If the hostname in the server certificate is different from +address+,
# it can be specified with +tls_hostname+.
#
- # Additional SSLContext params can be added to +ssl_context_params+ hash argument and are passed to
- # +OpenSSL::SSL::SSLContext#set_params+
+ # Additional SSLContext[https://ruby.github.io/openssl/OpenSSL/SSL/SSLContext.html]
+ # params can be added to the +ssl_context_params+ hash argument and are
+ # passed to {OpenSSL::SSL::SSLContext#set_params}[https://ruby.github.io/openssl/OpenSSL/SSL/SSLContext.html#method-i-set_params].
#
- # +tls_verify: true+ is equivalent to +ssl_context_params: { verify_mode: OpenSSL::SSL::VERIFY_PEER }+.
+ # <tt>tls_verify: true</tt> is equivalent to <tt>ssl_context_params: {
+ # verify_mode: OpenSSL::SSL::VERIFY_PEER }</tt>.
+ #
# This method does not open the TCP connection. You can use
# SMTP.start instead of SMTP.new if you want to do everything
# at once. Otherwise, follow SMTP.new with SMTP#start.
#
def initialize(address, port = nil, tls: false, starttls: :auto, tls_verify: true, tls_hostname: nil, ssl_context_params: nil)
@@ -314,16 +322,17 @@
# You cannot get valid value before opening SMTP session.
def capable_cram_md5_auth?
auth_capable?('CRAM-MD5')
end
+ # Returns whether the server advertises support for the authentication type.
+ # You cannot get valid result before opening SMTP session.
def auth_capable?(type)
return nil unless @capabilities
return false unless @capabilities['AUTH']
@capabilities['AUTH'].include?(type)
end
- private :auth_capable?
# Returns supported authentication methods on this server.
# You cannot get valid value before opening SMTP session.
def capable_auth_types
return [] unless @capabilities
@@ -336,11 +345,11 @@
@tls
end
alias ssl? tls?
- # Enables SMTP/TLS (SMTPS: SMTP over direct TLS connection) for
+ # Enables SMTP/TLS (SMTPS: \SMTP over direct TLS connection) for
# 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 = nil)
raise 'openssl library not installed' unless defined?(OpenSSL::VERSION)
raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @starttls == :always
@@ -455,12 +464,15 @@
#
# Creates a new Net::SMTP object and connects to the server.
#
# This method is equivalent to:
#
- # Net::SMTP.new(address, port).start(helo: helo_domain, user: account, secret: password, authtype: authtype, tls_verify: flag, tls_hostname: hostname, ssl_context_params: nil)
+ # Net::SMTP.new(address, port, tls_verify: flag, tls_hostname: hostname, ssl_context_params: nil)
+ # .start(helo: helo_domain, user: account, secret: password, authtype: authtype)
#
+ # See also: Net::SMTP.new, #start
+ #
# === Example
#
# Net::SMTP.start('your.smtp.server') do |smtp|
# smtp.send_message msgstr, 'from@example.com', ['dest@example.com']
# end
@@ -480,29 +492,39 @@
# +port+ is the port to connect to; it defaults to port 25.
#
# +helo+ is the _HELO_ _domain_ provided by the client to the
# server (see overview comments); it defaults to 'localhost'.
#
- # The remaining arguments are used for SMTP authentication, if required
- # or desired. +user+ is the account name; +secret+ is your password
- # or other authentication token; and +authtype+ is the authentication
- # type, one of :plain, :login, or :cram_md5. See the discussion of
- # SMTP Authentication in the overview notes.
- #
# If +tls+ is true, enable TLS. The default is false.
# If +starttls+ is :always, enable STARTTLS, if +:auto+, use STARTTLS when the server supports it,
# if false, disable STARTTLS.
#
# If +tls_verify+ is true, verify the server's certificate. The default is true.
# If the hostname in the server certificate is different from +address+,
# it can be specified with +tls_hostname+.
#
- # Additional SSLContext params can be added to +ssl_context_params+ hash argument and are passed to
- # +OpenSSL::SSL::SSLContext#set_params+
+ # Additional SSLContext[https://ruby.github.io/openssl/OpenSSL/SSL/SSLContext.html]
+ # params can be added to the +ssl_context_params+ hash argument and are
+ # passed to {OpenSSL::SSL::SSLContext#set_params}[https://ruby.github.io/openssl/OpenSSL/SSL/SSLContext.html#method-i-set_params].
#
- # +tls_verify: true+ is equivalent to +ssl_context_params: { verify_mode: OpenSSL::SSL::VERIFY_PEER }+.
+ # <tt>tls_verify: true</tt> is equivalent to <tt>ssl_context_params: {
+ # verify_mode: OpenSSL::SSL::VERIFY_PEER }</tt>.
#
+ # The remaining arguments are used for \SMTP authentication, if required or
+ # desired.
+ #
+ # +authtype+ is the SASL authentication mechanism.
+ #
+ # +user+ is the authentication or authorization identity.
+ #
+ # +secret+ or +password+ is your password or other authentication token.
+ #
+ # These will be sent to #authenticate as positional arguments-the exact
+ # semantics are dependent on the +authtype+.
+ #
+ # See the discussion of Net::SMTP@SMTP+Authentication in the overview notes.
+ #
# === Errors
#
# This method may raise:
#
# * Net::SMTPAuthenticationError
@@ -525,11 +547,11 @@
secret ||= password || args[2]
authtype ||= args[3]
new(address, port, tls: tls, starttls: starttls, tls_verify: tls_verify, tls_hostname: tls_hostname, ssl_context_params: ssl_context_params).start(helo: helo, user: user, secret: secret, authtype: authtype, &block)
end
- # +true+ if the SMTP session has been started.
+ # +true+ if the \SMTP session has been started.
def started?
@started
end
#
@@ -542,16 +564,26 @@
# === Parameters
#
# +helo+ is the _HELO_ _domain_ that you'll dispatch mails from; see
# the discussion in the overview notes.
#
- # If both of +user+ and +secret+ are given, SMTP authentication
- # will be attempted using the AUTH command. +authtype+ specifies
- # the type of authentication to attempt; it must be one of
- # :login, :plain, and :cram_md5. See the notes on SMTP Authentication
- # in the overview.
+ # The remaining arguments are used for \SMTP authentication, if required or
+ # desired.
#
+ # +authtype+ is the SASL authentication mechanism.
+ #
+ # +user+ is the authentication or authorization identity.
+ #
+ # +secret+ or +password+ is your password or other authentication token.
+ #
+ # These will be sent to #authenticate as positional arguments-the exact
+ # semantics are dependent on the +authtype+.
+ #
+ # See the discussion of Net::SMTP@SMTP+Authentication in the overview notes.
+ #
+ # See also: Net::SMTP.start
+ #
# === Block Usage
#
# When this methods is called with a block, the newly-started SMTP
# object is yielded to the block, and automatically closed after
# the block call finishes. Otherwise, it is the caller's
@@ -631,13 +663,12 @@
TCPSocket.open address, port
end
def do_start(helo_domain, user, secret, authtype)
raise IOError, 'SMTP session already started' if @started
- if user or secret
- check_auth_method(authtype || DEFAULT_AUTH_TYPE)
- check_auth_args user, secret
+ if user || secret || authtype
+ check_auth_args authtype, user, secret
end
s = Timeout.timeout(@open_timeout, Net::OpenTimeout) do
tcp_socket(@address, @port)
end
logging "Connection opened: #{@address}:#{@port}"
@@ -829,35 +860,29 @@
# Authentication
#
DEFAULT_AUTH_TYPE = :plain
+ # Authenticates with the server, using the "AUTH" command.
+ #
+ # +authtype+ is the name of a SASL authentication mechanism.
+ #
+ # All arguments-other than +authtype+-are forwarded to the authenticator.
+ # Different authenticators may interpret the +user+ and +secret+
+ # arguments differently.
def authenticate(user, secret, authtype = DEFAULT_AUTH_TYPE)
- check_auth_method authtype
- check_auth_args user, secret
+ check_auth_args authtype, user, secret
authenticator = Authenticator.auth_class(authtype).new(self)
authenticator.auth(user, secret)
end
private
- def check_auth_method(type)
- unless Authenticator.auth_class(type)
+ def check_auth_args(type, *args, **kwargs)
+ type ||= DEFAULT_AUTH_TYPE
+ klass = Authenticator.auth_class(type) or
raise ArgumentError, "wrong authentication type #{type}"
- end
- end
-
- def auth_method(type)
- "auth_#{type.to_s.downcase}".intern
- end
-
- def check_auth_args(user, secret, authtype = DEFAULT_AUTH_TYPE)
- unless user
- raise ArgumentError, 'SMTP-AUTH requested but missing user name'
- end
- unless secret
- raise ArgumentError, 'SMTP-AUTH requested but missing secret phrase'
- end
+ klass.check_args(*args, **kwargs)
end
#
# SMTP command dispatcher
#