diff --git a/lib/net/imap.rb b/lib/net/imap.rb
index e1ce6300..fb03c091 100644
--- a/lib/net/imap.rb
+++ b/lib/net/imap.rb
@@ -802,8 +802,21 @@ def idle_response_timeout; config.idle_response_timeout end
# Returns +false+ for a plaintext connection.
attr_reader :ssl_ctx_params
- # Creates a new Net::IMAP object and connects it to the specified
- # +host+.
+ # Creates a new Net::IMAP object and connects it to the specified +host+.
+ #
+ # ==== Default port and SSL
+ #
+ # When both both +port+ and +ssl+ are unspecified or +nil+,
+ # +ssl+ is determined by {config.default_ssl}[rdoc-ref:Config#default_ssl]
+ # and +port+ is based on that implicit value for +ssl+.
+ #
+ # When only one of the two is specified:
+ # * When +ssl+ is truthy, +port+ defaults to +993+.
+ # * When +ssl+ is +false+, +port+ defaults to +143+.
+ # * When +port+ is +993+, +ssl+ defaults to +true+.
+ # * When +port+ is +143+, +ssl+ defaults to +false+.
+ # * When +port+ is nonstandard, the default for +ssl+ is determined
+ # by {config.default_ssl}[rdoc-ref:Config#default_ssl].
#
# ==== Options
#
@@ -831,7 +844,9 @@ def idle_response_timeout; config.idle_response_timeout end
# SSL session verification mode. Valid modes include
# +OpenSSL::SSL::VERIFY_PEER+ and +OpenSSL::SSL::VERIFY_NONE+.
#
- # See {OpenSSL::SSL::SSLContext}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html] for other valid SSL context params.
+ # See
+ # {OpenSSL::SSL::SSLContext}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html]
+ # for other valid SSL context params.
#
# See DeprecatedClientOptions.new for deprecated SSL arguments.
#
@@ -912,7 +927,7 @@ def initialize(host, port: nil, ssl: nil,
# Config options
@host = host
@config = Config.new(config, **config_options)
- @port = port || (ssl ? SSL_PORT : PORT)
+ ssl, @port = default_ssl_and_port(ssl, port)
@ssl_ctx_params, @ssl_ctx = build_ssl_ctx(ssl)
# Basic Client State
@@ -2654,6 +2669,27 @@ def remove_response_handler(handler)
PORT = 143 # :nodoc:
SSL_PORT = 993 # :nodoc:
+ def default_ssl_and_port(tls, port)
+ if tls.nil? && port
+ tls = true if port == SSL_PORT || /\Aimaps\z/i === port
+ tls = false if port == PORT
+ elsif port.nil? && !tls.nil?
+ port = tls ? SSL_PORT : PORT
+ end
+ if tls.nil? && port.nil?
+ tls = config.default_tls.dup.freeze
+ port = tls ? SSL_PORT : PORT
+ if tls.nil?
+ warn "A future version of Net::IMAP::Config#default_tls " \
+ "will default to 'true', for secure connections by default. " \
+ "Use 'Net::IMAP.new(host, ssl: false)' or " \
+ "Net::IMAP.config.default_tls = false' to silence this warning."
+ end
+ end
+ tls &&= tls.respond_to?(:to_hash) ? tls.to_hash : {}
+ [tls, port]
+ end
+
def start_imap_connection
@greeting = get_server_greeting
@capabilities = capabilities_from_resp_code @greeting
diff --git a/lib/net/imap/config.rb b/lib/net/imap/config.rb
index bcf5b72d..2100ebd5 100644
--- a/lib/net/imap/config.rb
+++ b/lib/net/imap/config.rb
@@ -200,6 +200,29 @@ def self.[](config)
# The default value is +5+ seconds.
attr_accessor :idle_response_timeout, type: Integer
+ # :markup: markdown
+ #
+ # The default value for the +ssl+ option of Net::IMAP.new, when +port+ is
+ # unspecified or non-standard.
+ #
+ # *Note*: A future release of Net::IMAP will set the default to +true+, as
+ # per RFC7525[https://tools.ietf.org/html/rfc7525],
+ # RFC7817[https://tools.ietf.org/html/rfc7817], and
+ # RFC8314[https://tools.ietf.org/html/rfc8314].
+ #
+ # * Set to +true+ for the secure default without warnings.
+ # * Set to +:warn+ for the secure default _with_ warnings.
+ # * Set to +nil+ to use insecure defaults with warnings.
+ # * Set to +false+ to silence warnings and use insecure defaults.
+ #
+ # | Starting with version | The default value is |
+ # |-------------------------|------------------------|
+ # | _original_ | +false+ |
+ # | v0.6 (planned) | +nil+ |
+ # | v0.7 (planned) | +:warn+ |
+ # | _eventually_ | +true+ |
+ attr_accessor :default_ssl
+
# :markup: markdown
#
# Whether to use the +SASL-IR+ extension when the server and \SASL
@@ -331,6 +354,7 @@ def defaults_hash
debug: false,
open_timeout: 30,
idle_response_timeout: 5,
+ default_ssl: nil,
sasl_ir: true,
enforce_logindisabled: true,
responses_without_block: :warn,