Skip to content

Commit

Permalink
Extract public quit!/disconnect from do_finish
Browse files Browse the repository at this point in the history
This renames `#do_finish` to `#quit!`, makes it public, adds an option
to convert exceptions into warnings, and extracts the contents of the
ensure block into a new public `#disconnect` method.  The motivation for
making these public is given in the rdoc.

As documented in the rdoc, `#quit!`:
> Calls #quit and ensures that #disconnect is called.  Returns the
> result from #quit.  Returns +nil+ when the client is already
> disconnected or when a prior error prevents the client from calling
> #quit.  Unlike #finish, this an exception will not be raised when the
> client has not started.
>
> When <tt>exception: :warn</tt> is specified, when #quit raises a
> StandardError, a warning will be printed and the exception is
> returned, not re-raised.  When <tt>exception: false</tt> is specified,
> a warning will not be printed.  This is useful when the connection
> must be dropped, for example in a test suite or due to security
> concerns.

As documented in the rdoc, `#disconnect`:
> Disconnects the socket without checking if the connection has started
> yet, and without sending a final QUIT message to the server.
>
> Generally, either #finish or #quit! should be used instead.
  • Loading branch information
nevans committed May 5, 2024
1 parent 5b60464 commit d87b126
Showing 1 changed file with 34 additions and 3 deletions.
37 changes: 34 additions & 3 deletions lib/net/smtp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ def start(*args, helo: nil, user: nil, secret: nil, password: nil, authtype: nil
do_start helo, user, secret, authtype
return yield(self)
ensure
do_finish
quit!
end
else
do_start helo, user, secret, authtype
Expand All @@ -654,7 +654,7 @@ def start(*args, helo: nil, user: nil, secret: nil, password: nil, authtype: nil
# Raises IOError if not started.
def finish
raise IOError, 'not yet started' unless started?
do_finish
quit!
end

private
Expand Down Expand Up @@ -728,15 +728,46 @@ def do_helo(helo_domain)
raise
end

def do_finish
public

# Calls #quit and ensures that #disconnect is called. Returns the result
# from #quit. Returns +nil+ when the client is already disconnected or when
# a prior error prevents the client from calling #quit. Unlike #finish,
# this an exception will not be raised when the client has not started.
#
# When <tt>exception: :warn</tt> is specified, when #quit raises a
# StandardError, a warning will be printed and the exception is returned,
# not re-raised. When <tt>exception: false</tt> is specified, a warning
# will not be printed. This is useful when the connection must be dropped,
# for example in a test suite or due to security concerns.
#
# Related: #finish, #quit, #disconnect
def quit!(exception: true)
quit if @socket and not @socket.closed? and not @error_occurred
rescue => ex
if exception == :warn
warn "%s during %p #%s: %s" % [ex.class, self, __method__, ex]
elsif exception
raise ex
end
ex
ensure
disconnect
end

# Disconnects the socket without checking if the connection has started yet,
# and without sending a final QUIT message to the server.
#
# Generally, either #finish or #quit! should be used instead.
def disconnect
@started = false
@error_occurred = false
@socket.close if @socket
@socket = nil
end

private

def requires_smtputf8(address)
if address.kind_of? Address
!address.address.ascii_only?
Expand Down

0 comments on commit d87b126

Please sign in to comment.