diff --git a/lib/net/imap.rb b/lib/net/imap.rb
index e7e127e3..2f44d8a4 100644
--- a/lib/net/imap.rb
+++ b/lib/net/imap.rb
@@ -2503,17 +2503,21 @@ def idle_done
private_constant :RESPONSES_DEPRECATION_MSG
# :call-seq:
+ # responses(type) -> frozen array
# responses {|hash| ...} -> block result
# responses(type) {|array| ...} -> block result
#
- # Yields unhandled server responses and returns the result of the block.
- # Unhandled responses are stored in a hash, with arrays of
- # non-+nil+ UntaggedResponse#data keyed by UntaggedResponse#name
- # and ResponseCode#data keyed by ResponseCode#name.
+ # Yields or returns unhandled server responses. Unhandled responses are
+ # stored in a hash, with arrays of UntaggedResponse#data keyed by
+ # UntaggedResponse#name and non-+nil+ untagged ResponseCode#data
+ # keyed by ResponseCode#name.
+ #
+ # When a block is given, yields unhandled responses and returns the block's
+ # result. Without a block, returns the unhandled responses.
#
# [With +type+]
- # Yield only the array of responses for that +type+.
- # When no block is given, an +ArgumentError+ is raised.
+ # Yield or return only the array of responses for that +type+.
+ # When no block is given, the returned array is a frozen copy.
# [Without +type+]
# Yield or return the entire responses hash.
#
@@ -2534,7 +2538,7 @@ def idle_done
# For example:
#
# imap.select("inbox")
- # p imap.responses("EXISTS", &:last)
+ # p imap.responses("EXISTS").last
# #=> 2
# p imap.responses("UIDNEXT", &:last)
# #=> 123456
@@ -2592,7 +2596,7 @@ def responses(type = nil)
if block_given?
synchronize { yield(type ? @responses[type.to_s.upcase] : @responses) }
elsif type
- raise ArgumentError, "Pass a block or use #clear_responses"
+ synchronize { @responses[type.to_s.upcase].dup.freeze }
else
case config.responses_without_block
when :raise
diff --git a/lib/net/imap/config.rb b/lib/net/imap/config.rb
index 972a5b26..c7be267b 100644
--- a/lib/net/imap/config.rb
+++ b/lib/net/imap/config.rb
@@ -240,10 +240,19 @@ def self.[](config)
# [+:raise+ (planned future default)]
# Raise an ArgumentError with the deprecation warning.
#
+ # Note: #responses_without_args is an alias for #responses_without_block.
attr_accessor :responses_without_block, type: [
- :silence_deprecation_warning, :warn, :raise,
+ :silence_deprecation_warning, :warn, :frozen_dup, :raise,
]
+ alias responses_without_args responses_without_block # :nodoc:
+ alias responses_without_args= responses_without_block= # :nodoc:
+
+ ##
+ # :attr_accessor: responses_without_args
+ #
+ # Alias for responses_without_block
+
# Creates a new config object and initialize its attribute with +attrs+.
#
# If +parent+ is not given, the global config is used by default.
diff --git a/test/net/imap/test_imap_responses.rb b/test/net/imap/test_imap_responses.rb
index 07e2c9a8..911a3434 100644
--- a/test/net/imap/test_imap_responses.rb
+++ b/test/net/imap/test_imap_responses.rb
@@ -89,12 +89,35 @@ def for_each_config_option(imap)
end
end
- # with with a type and no block: always raise an exception
+ # with with a type and no block: always returns a frozen duplicate
test "#responses(type, &nil)" do
with_fake_server do |server, imap|
- for_each_config_option(imap) do
- assert_raise(ArgumentError) do imap.responses("CAPABILITY") end
+ stderr = EnvUtil.verbose_warning do
+ # Config options make no difference to responses(type)
+ for_each_config_option(imap) do
+ # responses available before SELECT/EXAMINE
+ assert imap.responses("CAPABILITY").frozen?
+ assert_equal(%w[IMAP4REV1 NAMESPACE MOVE IDLE UTF8=ACCEPT],
+ imap.responses("CAPABILITY").last)
+ end
+ # responses are cleared after SELECT/EXAMINE
+ imap.select "INBOX"
+ for_each_config_option(imap) do
+ assert imap.responses("CAPABILITY").frozen?
+ assert imap.responses("EXISTS").frozen?
+ assert imap.responses("UIDVALIDITIY").frozen?
+ assert_equal [], imap.responses("CAPABILITY")
+ assert_equal [172], imap.responses("EXISTS")
+ assert_equal [3857529045], imap.responses("UIDVALIDITY")
+ assert_equal 1, imap.responses("RECENT").last
+ assert imap.responses("UIDNEXT").frozen?
+ assert_equal [4392], imap.responses("UIDNEXT")
+ assert imap.responses("FLAGS").frozen?
+ assert_equal(%i[Answered Flagged Deleted Seen Draft],
+ imap.responses("FLAGS").last)
+ end
end
+ assert_empty stderr # never warn when type is given
end
end