Skip to content

Commit fe4928c

Browse files
committed
Merge branch 'master-3.3' into dist/3.3/jammy
2 parents f07b469 + dd2f417 commit fe4928c

File tree

139 files changed

+2275
-745
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

139 files changed

+2275
-745
lines changed
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

.bundle/gems/net-imap-0.4.19/lib/net/imap.rb renamed to .bundle/gems/net-imap-0.4.21/lib/net/imap.rb

Lines changed: 105 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,16 @@ module Net
4343
# To work on the messages within a mailbox, the client must
4444
# first select that mailbox, using either #select or #examine
4545
# (for read-only access). Once the client has successfully
46-
# selected a mailbox, they enter the "_selected_" state, and that
46+
# selected a mailbox, they enter the +selected+ state, and that
4747
# mailbox becomes the _current_ mailbox, on which mail-item
4848
# related commands implicitly operate.
4949
#
50+
# === Connection state
51+
#
52+
# Once an IMAP connection is established, the connection is in one of four
53+
# states: <tt>not authenticated</tt>, +authenticated+, +selected+, and
54+
# +logout+. Most commands are valid only in certain states.
55+
#
5056
# === Sequence numbers and UIDs
5157
#
5258
# Messages have two sorts of identifiers: message sequence
@@ -199,6 +205,42 @@ module Net
199205
#
200206
# This script invokes the FETCH command and the SEARCH command concurrently.
201207
#
208+
# When running multiple commands, care must be taken to avoid ambiguity. For
209+
# example, SEARCH responses are ambiguous about which command they are
210+
# responding to, so search commands should not run simultaneously, unless the
211+
# server supports +ESEARCH+ {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731] or
212+
# IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051]. See {RFC9051
213+
# §5.5}[https://www.rfc-editor.org/rfc/rfc9051.html#section-5.5] for
214+
# other examples of command sequences which should not be pipelined.
215+
#
216+
# == Unbounded memory use
217+
#
218+
# Net::IMAP reads server responses in a separate receiver thread per client.
219+
# Unhandled response data is saved to #responses, and response_handlers run
220+
# inside the receiver thread. See the list of methods for {handling server
221+
# responses}[rdoc-ref:Net::IMAP@Handling+server+responses], below.
222+
#
223+
# Because the receiver thread continuously reads and saves new responses, some
224+
# scenarios must be careful to avoid unbounded memory use:
225+
#
226+
# * Commands such as #list or #fetch can have an enormous number of responses.
227+
# * Commands such as #fetch can result in an enormous size per response.
228+
# * Long-lived connections will gradually accumulate unsolicited server
229+
# responses, especially +EXISTS+, +FETCH+, and +EXPUNGE+ responses.
230+
# * A buggy or untrusted server could send inappropriate responses, which
231+
# could be very numerous, very large, and very rapid.
232+
#
233+
# Use paginated or limited versions of commands whenever possible.
234+
#
235+
# Use Config#max_response_size to impose a limit on incoming server responses
236+
# as they are being read. <em>This is especially important for untrusted
237+
# servers.</em>
238+
#
239+
# Use #add_response_handler to handle responses after each one is received.
240+
# Use the +response_handlers+ argument to ::new to assign response handlers
241+
# before the receiver thread is started. Use #extract_responses,
242+
# #clear_responses, or #responses (with a block) to prune responses.
243+
#
202244
# == Errors
203245
#
204246
# An \IMAP server can send three different types of responses to indicate
@@ -260,8 +302,9 @@ module Net
260302
#
261303
# - Net::IMAP.new: Creates a new \IMAP client which connects immediately and
262304
# waits for a successful server greeting before the method returns.
305+
# - #connection_state: Returns the connection state.
263306
# - #starttls: Asks the server to upgrade a clear-text connection to use TLS.
264-
# - #logout: Tells the server to end the session. Enters the "_logout_" state.
307+
# - #logout: Tells the server to end the session. Enters the +logout+ state.
265308
# - #disconnect: Disconnects the connection (without sending #logout first).
266309
# - #disconnected?: True if the connection has been closed.
267310
#
@@ -317,37 +360,36 @@ module Net
317360
# <em>In general, #capable? should be used rather than explicitly sending a
318361
# +CAPABILITY+ command to the server.</em>
319362
# - #noop: Allows the server to send unsolicited untagged #responses.
320-
# - #logout: Tells the server to end the session. Enters the "_logout_" state.
363+
# - #logout: Tells the server to end the session. Enters the +logout+ state.
321364
#
322365
# ==== Not Authenticated state
323366
#
324367
# In addition to the commands for any state, the following commands are valid
325-
# in the "<em>not authenticated</em>" state:
368+
# in the +not_authenticated+ state:
326369
#
327370
# - #starttls: Upgrades a clear-text connection to use TLS.
328371
#
329372
# <em>Requires the +STARTTLS+ capability.</em>
330373
# - #authenticate: Identifies the client to the server using the given
331374
# {SASL mechanism}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml]
332-
# and credentials. Enters the "_authenticated_" state.
375+
# and credentials. Enters the +authenticated+ state.
333376
#
334377
# <em>The server should list <tt>"AUTH=#{mechanism}"</tt> capabilities for
335378
# supported mechanisms.</em>
336379
# - #login: Identifies the client to the server using a plain text password.
337-
# Using #authenticate is generally preferred. Enters the "_authenticated_"
338-
# state.
380+
# Using #authenticate is preferred. Enters the +authenticated+ state.
339381
#
340382
# <em>The +LOGINDISABLED+ capability</em> <b>must NOT</b> <em>be listed.</em>
341383
#
342384
# ==== Authenticated state
343385
#
344386
# In addition to the commands for any state, the following commands are valid
345-
# in the "_authenticated_" state:
387+
# in the +authenticated+ state:
346388
#
347389
# - #enable: Enables backwards incompatible server extensions.
348390
# <em>Requires the +ENABLE+ or +IMAP4rev2+ capability.</em>
349-
# - #select: Open a mailbox and enter the "_selected_" state.
350-
# - #examine: Open a mailbox read-only, and enter the "_selected_" state.
391+
# - #select: Open a mailbox and enter the +selected+ state.
392+
# - #examine: Open a mailbox read-only, and enter the +selected+ state.
351393
# - #create: Creates a new mailbox.
352394
# - #delete: Permanently remove a mailbox.
353395
# - #rename: Change the name of a mailbox.
@@ -369,12 +411,12 @@ module Net
369411
#
370412
# ==== Selected state
371413
#
372-
# In addition to the commands for any state and the "_authenticated_"
373-
# commands, the following commands are valid in the "_selected_" state:
414+
# In addition to the commands for any state and the +authenticated+
415+
# commands, the following commands are valid in the +selected+ state:
374416
#
375-
# - #close: Closes the mailbox and returns to the "_authenticated_" state,
417+
# - #close: Closes the mailbox and returns to the +authenticated+ state,
376418
# expunging deleted messages, unless the mailbox was opened as read-only.
377-
# - #unselect: Closes the mailbox and returns to the "_authenticated_" state,
419+
# - #unselect: Closes the mailbox and returns to the +authenticated+ state,
378420
# without expunging any messages.
379421
# <em>Requires the +UNSELECT+ or +IMAP4rev2+ capability.</em>
380422
# - #expunge: Permanently removes messages which have the Deleted flag set.
@@ -395,7 +437,7 @@ module Net
395437
#
396438
# ==== Logout state
397439
#
398-
# No \IMAP commands are valid in the "_logout_" state. If the socket is still
440+
# No \IMAP commands are valid in the +logout+ state. If the socket is still
399441
# open, Net::IMAP will close it after receiving server confirmation.
400442
# Exceptions will be raised by \IMAP commands that have already started and
401443
# are waiting for a response, as well as any that are called after logout.
@@ -449,7 +491,7 @@ module Net
449491
# ==== RFC3691: +UNSELECT+
450492
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051] and also included
451493
# above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
452-
# - #unselect: Closes the mailbox and returns to the "_authenticated_" state,
494+
# - #unselect: Closes the mailbox and returns to the +authenticated+ state,
453495
# without expunging any messages.
454496
#
455497
# ==== RFC4314: +ACL+
@@ -719,14 +761,15 @@ module Net
719761
# * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
720762
#
721763
class IMAP < Protocol
722-
VERSION = "0.4.19"
764+
VERSION = "0.4.21"
723765

724766
# Aliases for supported capabilities, to be used with the #enable command.
725767
ENABLE_ALIASES = {
726768
utf8: "UTF8=ACCEPT",
727769
"UTF8=ONLY" => "UTF8=ACCEPT",
728770
}.freeze
729771

772+
autoload :ResponseReader, File.expand_path("imap/response_reader", __dir__)
730773
autoload :SASL, File.expand_path("imap/sasl", __dir__)
731774
autoload :SASLAdapter, File.expand_path("imap/sasl_adapter", __dir__)
732775
autoload :StringPrep, File.expand_path("imap/stringprep", __dir__)
@@ -741,9 +784,11 @@ class IMAP < Protocol
741784
def self.config; Config.global end
742785

743786
# Returns the global debug mode.
787+
# Delegates to {Net::IMAP.config.debug}[rdoc-ref:Config#debug].
744788
def self.debug; config.debug end
745789

746790
# Sets the global debug mode.
791+
# Delegates to {Net::IMAP.config.debug=}[rdoc-ref:Config#debug=].
747792
def self.debug=(val)
748793
config.debug = val
749794
end
@@ -764,7 +809,7 @@ class << self
764809
alias default_ssl_port default_tls_port
765810
end
766811

767-
# Returns the initial greeting the server, an UntaggedResponse.
812+
# Returns the initial greeting sent by the server, an UntaggedResponse.
768813
attr_reader :greeting
769814

770815
# The client configuration. See Net::IMAP::Config.
@@ -773,13 +818,28 @@ class << self
773818
# Net::IMAP.config.
774819
attr_reader :config
775820

776-
# Seconds to wait until a connection is opened.
777-
# If the IMAP object cannot open a connection within this time,
778-
# it raises a Net::OpenTimeout exception. The default value is 30 seconds.
779-
def open_timeout; config.open_timeout end
821+
##
822+
# :attr_reader: open_timeout
823+
# Seconds to wait until a connection is opened. Also used by #starttls.
824+
# Delegates to {config.open_timeout}[rdoc-ref:Config#open_timeout].
780825

826+
##
827+
# :attr_reader: idle_response_timeout
781828
# Seconds to wait until an IDLE response is received.
782-
def idle_response_timeout; config.idle_response_timeout end
829+
# Delegates to {config.idle_response_timeout}[rdoc-ref:Config#idle_response_timeout].
830+
831+
##
832+
# :attr_accessor: max_response_size
833+
#
834+
# The maximum allowed server response size, in bytes.
835+
# Delegates to {config.max_response_size}[rdoc-ref:Config#max_response_size].
836+
837+
# :stopdoc:
838+
def open_timeout; config.open_timeout end
839+
def idle_response_timeout; config.idle_response_timeout end
840+
def max_response_size; config.max_response_size end
841+
def max_response_size=(val) config.max_response_size = val end
842+
# :startdoc:
783843

784844
# The hostname this client connected to
785845
attr_reader :host
@@ -835,6 +895,12 @@ def idle_response_timeout; config.idle_response_timeout end
835895
#
836896
# See DeprecatedClientOptions.new for deprecated SSL arguments.
837897
#
898+
# [response_handlers]
899+
# A list of response handlers to be added before the receiver thread is
900+
# started. This ensures every server response is handled, including the
901+
# #greeting. Note that the greeting is handled in the current thread, but
902+
# all other responses are handled in the receiver thread.
903+
#
838904
# [config]
839905
# A Net::IMAP::Config object to use as the basis for #config. By default,
840906
# the global Net::IMAP.config is used.
@@ -906,7 +972,7 @@ def idle_response_timeout; config.idle_response_timeout end
906972
# [Net::IMAP::ByeResponseError]
907973
# Connected to the host successfully, but it immediately said goodbye.
908974
#
909-
def initialize(host, port: nil, ssl: nil,
975+
def initialize(host, port: nil, ssl: nil, response_handlers: nil,
910976
config: Config.global, **config_options)
911977
super()
912978
# Config options
@@ -929,6 +995,7 @@ def initialize(host, port: nil, ssl: nil,
929995
@receiver_thread = nil
930996
@receiver_thread_exception = nil
931997
@receiver_thread_terminating = false
998+
response_handlers&.each do add_response_handler(_1) end
932999

9331000
# Client Protocol Sender (including state for currently running commands)
9341001
@tag_prefix = "RUBY"
@@ -944,6 +1011,7 @@ def initialize(host, port: nil, ssl: nil,
9441011
# Connection
9451012
@tls_verified = false
9461013
@sock = tcp_socket(@host, @port)
1014+
@reader = ResponseReader.new(self, @sock)
9471015
start_tls_session if ssl_ctx
9481016
start_imap_connection
9491017

@@ -1204,6 +1272,10 @@ def logout!
12041272
# both successful. Any error indicates that the connection has not been
12051273
# secured.
12061274
#
1275+
# After the server agrees to start a TLS connection, this method waits up to
1276+
# {config.open_timeout}[rdoc-ref:Config#open_timeout] before raising
1277+
# +Net::OpenTimeout+.
1278+
#
12071279
# *Note:*
12081280
# >>>
12091281
# Any #response_handlers added before STARTTLS should be aware that the
@@ -2706,6 +2778,10 @@ def response_handlers
27062778
# end
27072779
# }
27082780
#
2781+
# Response handlers can also be added when the client is created before the
2782+
# receiver thread is started, by the +response_handlers+ argument to ::new.
2783+
# This ensures every server response is handled, including the #greeting.
2784+
#
27092785
# Related: #remove_response_handler, #response_handlers
27102786
def add_response_handler(handler = nil, &block)
27112787
raise ArgumentError, "two Procs are passed" if handler && block
@@ -2732,6 +2808,7 @@ def remove_response_handler(handler)
27322808
def start_imap_connection
27332809
@greeting = get_server_greeting
27342810
@capabilities = capabilities_from_resp_code @greeting
2811+
@response_handlers.each do |handler| handler.call(@greeting) end
27352812
@receiver_thread = start_receiver_thread
27362813
rescue Exception
27372814
@sock.close
@@ -2860,23 +2937,10 @@ def get_tagged_response(tag, cmd, timeout = nil)
28602937
end
28612938

28622939
def get_response
2863-
buff = String.new
2864-
while true
2865-
s = @sock.gets(CRLF)
2866-
break unless s
2867-
buff.concat(s)
2868-
if /\{(\d+)\}\r\n/n =~ s
2869-
s = @sock.read($1.to_i)
2870-
buff.concat(s)
2871-
else
2872-
break
2873-
end
2874-
end
2940+
buff = @reader.read_response_buffer
28752941
return nil if buff.length == 0
2876-
if config.debug?
2877-
$stderr.print(buff.gsub(/^/n, "S: "))
2878-
end
2879-
return @parser.parse(buff)
2942+
$stderr.print(buff.gsub(/^/n, "S: ")) if config.debug?
2943+
@parser.parse(buff)
28802944
end
28812945

28822946
#############################
@@ -3077,6 +3141,7 @@ def start_tls_session
30773141
raise "already using SSL" if @sock.kind_of?(OpenSSL::SSL::SSLSocket)
30783142
raise "cannot start TLS without SSLContext" unless ssl_ctx
30793143
@sock = SSLSocket.new(@sock, ssl_ctx)
3144+
@reader = ResponseReader.new(self, @sock)
30803145
@sock.sync_close = true
30813146
@sock.hostname = @host if @sock.respond_to? :hostname=
30823147
ssl_socket_connect(@sock, open_timeout)
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)