diff --git a/lib/net/imap.rb b/lib/net/imap.rb index 995e6e15..f9a474ea 100644 --- a/lib/net/imap.rb +++ b/lib/net/imap.rb @@ -2711,26 +2711,75 @@ def remove_response_handler(handler) 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 + case [tls && true, classify_port(port)] + in true, nil then return tls, SSL_PORT + in false, nil then return tls, PORT + in nil, :tls then return true, port + in nil, :plain then return false, port + in nil, nil then return use_default_ssl + in true, :tls | :other then return tls, port + in false, :plain | :other then return tls, port + in true, :plain then return warn_mismatched_port tls, port + in false, :tls then return warn_mismatched_port tls, port + in nil, :other then return warn_nonstandard_port port end + # TODO: move this wherever is appropriate tls &&= tls.respond_to?(:to_hash) ? tls.to_hash : {} + end + + # classify_port(port) -> :tls | :plain | :other | nil + def classify_port(port) + case port + in (SSL_PORT | /\Aimaps\z/i) then :tls + in (PORT | /\Aimap\z/i) then :plain + in (Integer | String) then :other + in nil then nil + end + end + + def warn_mismatched_port(tls, port) + if tls + warn "Using TLS on plaintext IMAP port" + else + warn "Using plaintext on TLS IMAP port" + end + [tls, port] + end + + def warn_nonstandard_port(port) + tls = !!config.default_ssl + if config.warn_nonstandard_port_without_ssl + warn "Using #{tls ? "TLS" : "plaintext"} on port #{port}. " \ + "Set ssl explicitly for non-standard IMAP ports." + end + # TODO: print default_ssl warning [tls, port] end + TLS_DEFAULT_WARNING = + "Net::IMAP.config.default_ssl will default to true in the future. " \ + "To silence this warning, " \ + "set Net::IMAP.config.default_ssl = (true | false)' or " \ + "use 'Net::IMAP.new(host, ssl: (true | false))'." + private_constant :TLS_DEFAULT_WARNING + + def use_default_ssl + case config.default_ssl + when true then [true, SSL_PORT] + when false then [false, PORT] + when :warn + warn TLS_DEFAULT_WARNING unless port + port ||= SSL_PORT + warn "Using TLS on port #{port}." + [true, port] + when nil + warn TLS_DEFAULT_WARNING unless port + port ||= PORT + warn "Using plain-text on port #{port}." + [false, port] + end + 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 295355aa..9a1a0949 100644 --- a/lib/net/imap/config.rb +++ b/lib/net/imap/config.rb @@ -236,6 +236,22 @@ def self.[](config) # with no params. attr_accessor :default_ssl, type: [false, nil, :warn, true] + # Whether to warn for using default_ssl when the port is non-standard. + # + # Although default_ssl is used for non-standard ports, this warning is + # different replaces the warning when default_ssl is +nil+ or +:warn+. + # When this option is false but default_ssl is +nil+ or +:warn+, that + # warning will be printed instead. + # + # ==== Valid options + # + # [+false+ (original behavior)] + # Don't print a special warning for nonstandard ports without explicit + # +ssl+. + # [+true+ (eventual future default)] + # Print a special warning for nonstandard ports without explicit +ssl+. + attr_accessor :warn_nonstandard_port_without_ssl, type: :boolean + # 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. @@ -392,6 +408,7 @@ def defaults_hash open_timeout: 30, idle_response_timeout: 5, default_ssl: false, + warn_nonstandard_port_without_ssl: false, sasl_ir: true, enforce_logindisabled: true, responses_without_block: :warn, @@ -430,6 +447,7 @@ def defaults_hash version_defaults[:future] = Config[0.7].dup.update( default_ssl: true, + warn_nonstandard_port_without_ssl: true, ).freeze version_defaults.freeze