Skip to content

Commit

Permalink
🗑️ Add deprecation warnings to .new and #starttls [🚧 WIP]
Browse files Browse the repository at this point in the history
* `ssl` was renamed to `tls` in most places, with backwards compatible
  aliases.  Using `ssl` does not print any deprecation warnings.  Using
  both `tls` and `ssl` keywords raises an ArgumentError.

* Preparing for a (backwards-incompatible) secure-by-default
  configuration, `Net::IMAP.default_tls` will determine the value for
  `tls` when no explicit port or tls setting is provided.  Using port
  143 will be insecure by default.  Using port 993 will be secure by
  default.  Providing no explicit port will use `Net::IMAP.default_tls`
  with the appropriate port.  And providing any other unknown port will
  use `default_tls` with a warning.

  🚧 TODO: should we use a different config var for default tls params
  when port is 993 and `tls` is unspecified?

  🚧 TODO: should we use a different config var for choosing `tls` when
  `port` is non-standard vs choosing `port` and `tls` when neither are
  specified?

  🚧 TODO: should we use a different var for `default_tls` be used to
  config params when port is 993 but tls is implicit? Another var?
  • Loading branch information
nevans committed Oct 29, 2024
1 parent 5a0e5cb commit 78a5bba
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 5 deletions.
44 changes: 40 additions & 4 deletions lib/net/imap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
#
Expand Down Expand Up @@ -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.
#
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -2695,6 +2710,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
Expand Down
40 changes: 39 additions & 1 deletion lib/net/imap/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,35 @@ def self.[](config)
# The default value is +5+ seconds.
attr_accessor :idle_response_timeout, type: Integer

# The default value for the +ssl+ option of Net::IMAP.new, when +port+ is
# unspecified or non-standard and +ssl+ is unspecified. default_ssl is
# ignored when Net::IMAP.new is called with any value for +ssl+ besides
# +nil+,
#
# *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].
#
# <em>(The default_ssl config attribute was added in +v0.5.?+.)</em>
#
# ==== Valid options
#
# [+false+ <em>(original behavior)</em>]
# Plaintext by default, with no warnings.
# [+nil+ <em>(planned default for +v0.6+)</em>]
# Plaintext by default, and prints a warning.
#
# <em>This option will be removed in +v0.7+, when +:warn+ becomes the
# default.</em>
# [+:warn+ <em>(planned default for +v0.7+)</em>]
# A warning will be printed, and behave as if the default were +true+.
# [+true+ <em>(planned future default)</em>]
# Use TLS by default, with the default SSL context params set by calling
# {OpenSSL::SSL::SSLContext#set_params}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-set_params]
# with no params.
attr_accessor :default_ssl, type: [false, nil, :warn, true]

# Whether to use the +SASL-IR+ extension when the server and \SASL
# mechanism both support it. Can be overridden by the +sasl_ir+ keyword
# parameter to Net::IMAP#authenticate.
Expand Down Expand Up @@ -362,6 +391,7 @@ def defaults_hash
debug: false,
open_timeout: 30,
idle_response_timeout: 5,
default_ssl: false,
sasl_ir: true,
enforce_logindisabled: true,
responses_without_block: :warn,
Expand Down Expand Up @@ -390,9 +420,17 @@ def defaults_hash

version_defaults[0.6] = Config[0.5].dup.update(
responses_without_block: :frozen_dup,
default_ssl: nil,
).freeze
version_defaults[:next] = Config[0.6]
version_defaults[:future] = Config[:next]

version_defaults[0.7] = Config[0.6].dup.update(
default_ssl: :warn,
).freeze

version_defaults[:future] = Config[0.7].dup.update(
default_ssl: true,
).freeze

version_defaults.freeze
end
Expand Down

0 comments on commit 78a5bba

Please sign in to comment.