Skip to content

Commit 805111e

Browse files
committed
♻️ Simplify and organize Net::IMAP#initialize
* Extract four methods: * `convert_deprecated_options` * `start_imap_connection`: begins IMAP protocol on connected socket * `get_server_greeting`: wraps `get_response` with greeting specifics * `start_receiver_thread` * Various other small stylistic tweaks, e.g: grouped similar ivars. This _should_ be the result of a series of "pure" safe refactorings. All existing behavior should remain unchanged.
1 parent 7727383 commit 805111e

File tree

1 file changed

+77
-56
lines changed

1 file changed

+77
-56
lines changed

lib/net/imap.rb

Lines changed: 77 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -795,70 +795,50 @@ class << self
795795
# [Net::IMAP::ByeResponseError]
796796
# Connected to the host successfully, but it immediately said goodbye.
797797
#
798-
def initialize(host, port_or_options = {},
799-
usessl = false, certs = nil, verify = true)
798+
def initialize(host, options = {}, *deprecated)
800799
super()
800+
options = convert_deprecated_options(options, *deprecated)
801+
802+
# Config options
801803
@host = host
802-
begin
803-
options = port_or_options.to_hash
804-
rescue NoMethodError
805-
# for backward compatibility
806-
options = {}
807-
options[:port] = port_or_options
808-
if usessl
809-
options[:ssl] = create_ssl_params(certs, verify)
810-
end
811-
end
812804
@port = options[:port] || (options[:ssl] ? SSL_PORT : PORT)
813-
@tag_prefix = "RUBY"
814-
@tagno = 0
815-
@utf8_strings = false
816805
@open_timeout = options[:open_timeout] || 30
817806
@idle_response_timeout = options[:idle_response_timeout] || 5
818-
@tls_verified = false
807+
ssl_ctx_params = options[:ssl]
808+
809+
# Basic Client State
810+
@utf8_strings = false
811+
@debug_output_bol = true
812+
@exception = nil
813+
@greeting = nil
814+
@capabilities = nil
815+
816+
# Client Protocol Reciever
819817
@parser = ResponseParser.new
818+
@responses = Hash.new {|h, k| h[k] = [] }
819+
@response_handlers = []
820+
@receiver_thread = nil
821+
@receiver_thread_exception = nil
822+
@receiver_thread_terminating = false
823+
824+
# Client Protocol Sender (including state for currently running commands)
825+
@tag_prefix = "RUBY"
826+
@tagno = 0
827+
@tagged_responses = {}
828+
@tagged_response_arrival = new_cond
829+
@continued_command_tag = nil
830+
@continuation_request_arrival = new_cond
831+
@continuation_request_exception = nil
832+
@idle_done_cond = nil
833+
@logout_command_tag = nil
834+
835+
# Connection
836+
@tls_verified = false
820837
@sock = tcp_socket(@host, @port)
821-
begin
822-
if options[:ssl]
823-
start_tls_session(options[:ssl])
824-
@usessl = true
825-
else
826-
@usessl = false
827-
end
828-
@responses = Hash.new {|h, k| h[k] = [] }
829-
@tagged_responses = {}
830-
@response_handlers = []
831-
@tagged_response_arrival = new_cond
832-
@continued_command_tag = nil
833-
@continuation_request_arrival = new_cond
834-
@continuation_request_exception = nil
835-
@idle_done_cond = nil
836-
@logout_command_tag = nil
837-
@debug_output_bol = true
838-
@exception = nil
839-
840-
@greeting = get_response
841-
if @greeting.nil?
842-
raise Error, "connection closed"
843-
end
844-
record_untagged_response_code @greeting
845-
@capabilities = capabilities_from_resp_code @greeting
846-
if @greeting.name == "BYE"
847-
raise ByeResponseError, @greeting
848-
end
838+
start_imap_connection(ssl_ctx_params)
849839

850-
@client_thread = Thread.current
851-
@receiver_thread = Thread.start {
852-
begin
853-
receive_responses
854-
rescue Exception
855-
end
856-
}
857-
@receiver_thread_terminating = false
858-
rescue Exception
859-
@sock.close
860-
raise
861-
end
840+
# DEPRECATED: to remove in next version
841+
@client_thread = Thread.current
862842
end
863843

864844
# Returns true after the TLS negotiation has completed and the remote
@@ -2357,6 +2337,47 @@ def remove_response_handler(handler)
23572337

23582338
@@debug = false
23592339

2340+
def convert_deprecated_options(
2341+
port_or_options = {}, usessl = false, certs = nil, verify = true
2342+
)
2343+
port_or_options.to_hash
2344+
rescue NoMethodError
2345+
# for backward compatibility
2346+
options = {}
2347+
options[:port] = port_or_options
2348+
if usessl
2349+
options[:ssl] = create_ssl_params(certs, verify)
2350+
end
2351+
options
2352+
end
2353+
2354+
def start_imap_connection(ssl_ctx_params)
2355+
start_tls_session(ssl_ctx_params) if ssl_ctx_params
2356+
@greeting = get_server_greeting
2357+
@capabilities = capabilities_from_resp_code @greeting
2358+
@receiver_thread = start_receiver_thread
2359+
rescue Exception
2360+
@sock.close
2361+
raise
2362+
end
2363+
2364+
def get_server_greeting
2365+
greeting = get_response
2366+
raise Error, "No server greeting - connection closed" unless greeting
2367+
record_untagged_response_code greeting
2368+
raise ByeResponseError, greeting if greeting.name == "BYE"
2369+
greeting
2370+
end
2371+
2372+
def start_receiver_thread
2373+
Thread.start do
2374+
receive_responses
2375+
rescue Exception => ex
2376+
@receiver_thread_exception = ex
2377+
# don't exit the thread with an exception
2378+
end
2379+
end
2380+
23602381
def tcp_socket(host, port)
23612382
s = Socket.tcp(host, port, :connect_timeout => @open_timeout)
23622383
s.setsockopt(:SOL_SOCKET, :SO_KEEPALIVE, true)

0 commit comments

Comments
 (0)