diff --git a/lib/net/imap.rb b/lib/net/imap.rb
index 2f44d8a4..19dd89a1 100644
--- a/lib/net/imap.rb
+++ b/lib/net/imap.rb
@@ -2498,11 +2498,13 @@ def idle_done
RESPONSES_DEPRECATION_MSG =
"Pass a type or block to #responses, " \
- "set config.responses_without_block to :silence_deprecation_warning, " \
+ "set config.responses_without_block to :frozen_dup " \
+ "or :silence_deprecation_warning, " \
"or use #extract_responses or #clear_responses."
private_constant :RESPONSES_DEPRECATION_MSG
# :call-seq:
+ # responses -> hash of {String => Array} (see config.responses_without_block)
# responses(type) -> frozen array
# responses {|hash| ...} -> block result
# responses(type) {|array| ...} -> block result
@@ -2532,6 +2534,10 @@ def idle_done
# Prints a warning and returns the mutable responses hash.
# This is not thread-safe.
#
+ # [+:frozen_dup+]
+ # Returns a frozen copy of the unhandled responses hash, with frozen
+ # array values.
+ #
# [+:raise+ (planned future default)]
# Raise an +ArgumentError+ with the deprecation warning.
#
@@ -2603,6 +2609,13 @@ def responses(type = nil)
raise ArgumentError, RESPONSES_DEPRECATION_MSG
when :warn
warn(RESPONSES_DEPRECATION_MSG, uplevel: 1)
+ when :frozen_dup
+ synchronize {
+ responses = @responses.transform_values(&:freeze)
+ responses.default_proc = nil
+ responses.default = [].freeze
+ return responses.freeze
+ }
end
@responses
end
diff --git a/lib/net/imap/config.rb b/lib/net/imap/config.rb
index c7be267b..4f2ae899 100644
--- a/lib/net/imap/config.rb
+++ b/lib/net/imap/config.rb
@@ -237,6 +237,15 @@ def self.[](config)
# Prints a warning and returns the mutable responses hash.
# This is not thread-safe.
#
+ # [+:frozen_dup+]
+ # Returns a frozen copy of the unhandled responses hash, with frozen
+ # array values.
+ #
+ # Note that calling IMAP#responses with a +type+ and without a block is
+ # not configurable and always behaves like +:frozen_dup+.
+ #
+ # (+:frozen_dup+ config option was added in +v0.4.17+)
+ #
# [+:raise+ (planned future default)]
# Raise an ArgumentError with the deprecation warning.
#
diff --git a/test/net/imap/test_imap_responses.rb b/test/net/imap/test_imap_responses.rb
index 911a3434..aaa61d43 100644
--- a/test/net/imap/test_imap_responses.rb
+++ b/test/net/imap/test_imap_responses.rb
@@ -166,6 +166,15 @@ def assert_responses_warn
assert_equal [], imap.responses["FAKE"]
end
assert_empty stderr
+ # opt-in to future behavior
+ imap.config.responses_without_block = :frozen_dup
+ stderr = EnvUtil.verbose_warning do
+ assert imap.responses.frozen?
+ assert imap.responses["CAPABILITY"].frozen?
+ assert_equal(%w[IMAP4REV1 NAMESPACE MOVE IDLE UTF8=ACCEPT],
+ imap.responses["CAPABILITY"].last)
+ end
+ assert_empty stderr
end
end