net-imap 0.5.6 → 0.5.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +6 -4
- data/lib/net/imap/config/attr_type_coercion.rb +35 -22
- data/lib/net/imap/config/attr_version_defaults.rb +93 -0
- data/lib/net/imap/config.rb +90 -60
- data/lib/net/imap/connection_state.rb +48 -0
- data/lib/net/imap/errors.rb +33 -0
- data/lib/net/imap/esearch_result.rb +42 -3
- data/lib/net/imap/flags.rb +1 -1
- data/lib/net/imap/response_data.rb +0 -1
- data/lib/net/imap/response_reader.rb +73 -0
- data/lib/net/imap/search_result.rb +2 -3
- data/lib/net/imap/sequence_set.rb +577 -190
- data/lib/net/imap/vanished_data.rb +10 -1
- data/lib/net/imap.rb +278 -61
- data/rakelib/string_prep_tables_generator.rb +4 -2
- metadata +6 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1da7db7eb1545ee4a81555ef7f46c65e82e48ad8e4b64a4112881698df4ebc5d
|
|
4
|
+
data.tar.gz: b3a668019d4d36c2a9cfc8d41c5e65d1054a630dc2c5cb8ea7050fbaaf264f6b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 731921ff022993cd51ada037fa764067d4da07e6a8119545f7b225354b32f19c3936a8c807c3badd3664dde424c924842ecb0ac9851d74bb9bf568ebbbb800e6
|
|
7
|
+
data.tar.gz: da993296fd57d59c56c483920d901c9b6b44329c0bb5812c495de2024f01e449b0117be5900013875902ff1101ac0dfeaf177f407ea34e69ae210bd87f91e86a
|
data/Gemfile
CHANGED
|
@@ -4,7 +4,7 @@ source "https://rubygems.org"
|
|
|
4
4
|
|
|
5
5
|
gemspec
|
|
6
6
|
|
|
7
|
-
gem "digest"
|
|
7
|
+
# gem "digest" # not included as a workaround for #576
|
|
8
8
|
gem "strscan"
|
|
9
9
|
gem "base64"
|
|
10
10
|
|
|
@@ -14,10 +14,12 @@ gem "rdoc"
|
|
|
14
14
|
gem "test-unit"
|
|
15
15
|
gem "test-unit-ruby-core", git: "https://github.com/ruby/test-unit-ruby-core"
|
|
16
16
|
|
|
17
|
+
gem "benchmark", require: false
|
|
17
18
|
gem "benchmark-driver", require: false
|
|
19
|
+
gem "vernier", require: false, platform: :mri
|
|
18
20
|
|
|
19
21
|
group :test do
|
|
20
|
-
gem "simplecov", require: false
|
|
21
|
-
gem "simplecov-html", require: false
|
|
22
|
-
gem "simplecov-json", require: false
|
|
22
|
+
gem "simplecov", require: false, platforms: %i[mri windows]
|
|
23
|
+
gem "simplecov-html", require: false, platforms: %i[mri windows]
|
|
24
|
+
gem "simplecov-json", require: false, platforms: %i[mri windows]
|
|
23
25
|
end
|
|
@@ -18,6 +18,8 @@ module Net
|
|
|
18
18
|
super(attr)
|
|
19
19
|
AttrTypeCoercion.attr_accessor(attr, type: type)
|
|
20
20
|
end
|
|
21
|
+
|
|
22
|
+
module_function def Integer? = NilOrInteger
|
|
21
23
|
end
|
|
22
24
|
private_constant :Macros
|
|
23
25
|
|
|
@@ -26,34 +28,45 @@ module Net
|
|
|
26
28
|
end
|
|
27
29
|
private_class_method :included
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
if defined?(Ractor.shareable_proc)
|
|
32
|
+
def self.safe(&b)
|
|
33
|
+
case obj = b.call
|
|
34
|
+
when Proc
|
|
35
|
+
Ractor.shareable_proc(&obj)
|
|
36
|
+
else
|
|
37
|
+
Ractor.make_shareable obj
|
|
38
|
+
end
|
|
35
39
|
end
|
|
40
|
+
elsif defined?(Ractor.make_shareable)
|
|
41
|
+
def self.safe(&b)
|
|
42
|
+
obj = nil.instance_eval(&b).freeze
|
|
43
|
+
Ractor.make_shareable obj
|
|
44
|
+
end
|
|
45
|
+
else
|
|
46
|
+
def self.safe(&b) nil.instance_eval(&b).freeze end
|
|
36
47
|
end
|
|
48
|
+
private_class_method :safe
|
|
37
49
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
end
|
|
50
|
+
Types = Hash.new do |h, type| type => Proc | nil; safe{type} end
|
|
51
|
+
Types[:boolean] = Boolean = safe{-> {!!_1}}
|
|
52
|
+
Types[Integer] = safe{->{Integer(_1)}}
|
|
42
53
|
|
|
43
|
-
def self.
|
|
44
|
-
|
|
54
|
+
def self.attr_accessor(attr, type: nil)
|
|
55
|
+
type = Types[type] or return
|
|
56
|
+
define_method :"#{attr}=" do |val| super type[val] end
|
|
57
|
+
define_method :"#{attr}?" do send attr end if type == Boolean
|
|
45
58
|
end
|
|
46
59
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
NilOrInteger = safe{->val { Integer val unless val.nil? }}
|
|
61
|
+
|
|
62
|
+
Enum = ->(*enum) {
|
|
63
|
+
safe_enum = safe{enum}
|
|
64
|
+
expected = -"one of #{safe_enum.map(&:inspect).join(", ")}"
|
|
65
|
+
safe{->val {
|
|
66
|
+
return val if safe_enum.include?(val)
|
|
67
|
+
raise ArgumentError, "expected %s, got %p" % [expected, val]
|
|
68
|
+
}}
|
|
69
|
+
}
|
|
57
70
|
|
|
58
71
|
end
|
|
59
72
|
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "forwardable"
|
|
4
|
+
|
|
5
|
+
module Net
|
|
6
|
+
class IMAP
|
|
7
|
+
class Config
|
|
8
|
+
# >>>
|
|
9
|
+
# *NOTE:* This module is an internal implementation detail, with no
|
|
10
|
+
# guarantee of backward compatibility.
|
|
11
|
+
#
|
|
12
|
+
# Adds a +defaults+ parameter to +attr_accessor+, which is used to compile
|
|
13
|
+
# Config.version_defaults.
|
|
14
|
+
module AttrVersionDefaults
|
|
15
|
+
# The <tt>x.y</tt> part of Net::IMAP::VERSION, as a Rational number.
|
|
16
|
+
CURRENT_VERSION = VERSION.to_r
|
|
17
|
+
|
|
18
|
+
# The config version used for <tt>Config[:next]</tt>.
|
|
19
|
+
NEXT_VERSION = CURRENT_VERSION + 0.1r
|
|
20
|
+
|
|
21
|
+
# The config version used for <tt>Config[:future]</tt>.
|
|
22
|
+
FUTURE_VERSION = 1.0r
|
|
23
|
+
|
|
24
|
+
VERSIONS = ((0.0r..FUTURE_VERSION) % 0.1r).to_a.freeze
|
|
25
|
+
|
|
26
|
+
# See Config.version_defaults.
|
|
27
|
+
singleton_class.attr_accessor :version_defaults
|
|
28
|
+
|
|
29
|
+
@version_defaults = Hash.new {|h, k|
|
|
30
|
+
# NOTE: String responds to both so the order is significant.
|
|
31
|
+
# And ignore non-numeric conversion to zero, because: "wat!?".to_r == 0
|
|
32
|
+
(h.fetch(k.to_r, nil) || h.fetch(k.to_f, nil) if k.is_a?(Numeric)) ||
|
|
33
|
+
(h.fetch(k.to_sym, nil) if k.respond_to?(:to_sym)) ||
|
|
34
|
+
(h.fetch(k.to_r, nil) if k.respond_to?(:to_r) && k.to_r != 0r) ||
|
|
35
|
+
(h.fetch(k.to_f, nil) if k.respond_to?(:to_f) && k.to_f != 0.0)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
# :stopdoc: internal APIs only
|
|
39
|
+
|
|
40
|
+
def attr_accessor(name, defaults: nil, default: (unset = true), **kw)
|
|
41
|
+
unless unset
|
|
42
|
+
version = DEFAULT_TO_INHERIT.include?(name) ? nil : 0.0r
|
|
43
|
+
defaults = { version => default }
|
|
44
|
+
end
|
|
45
|
+
defaults&.each_pair do |version, default|
|
|
46
|
+
AttrVersionDefaults.version_defaults[version] ||= {}
|
|
47
|
+
AttrVersionDefaults.version_defaults[version][name] = default
|
|
48
|
+
end
|
|
49
|
+
super(name, **kw)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.compile_default!
|
|
53
|
+
raise "Config.default already compiled" if Config.default
|
|
54
|
+
default = VERSIONS.select { _1 <= CURRENT_VERSION }
|
|
55
|
+
.filter_map { version_defaults[_1] }
|
|
56
|
+
.prepend(version_defaults.delete(nil))
|
|
57
|
+
.inject(&:merge)
|
|
58
|
+
Config.new(**default).freeze
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def self.compile_version_defaults!
|
|
62
|
+
# Temporarily assign Config.default, enabling #load_defaults(:default)
|
|
63
|
+
version_defaults[:default] = Config.default
|
|
64
|
+
# Use #load_defaults so some attributes are inherited from global.
|
|
65
|
+
version_defaults[:default] = Config.new.load_defaults(:default).freeze
|
|
66
|
+
version_defaults[0.0r] = Config[version_defaults.fetch(0.0r)]
|
|
67
|
+
|
|
68
|
+
VERSIONS.each_cons(2) do |prior, version|
|
|
69
|
+
updates = version_defaults[version]
|
|
70
|
+
version_defaults[version] = version_defaults[prior]
|
|
71
|
+
.then { updates ? _1.dup.update(**updates).freeze : _1 }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Safe conversions one way only:
|
|
75
|
+
# 0.6r.to_f == 0.6 # => true
|
|
76
|
+
# 0.6 .to_r == 0.6r # => false
|
|
77
|
+
version_defaults.to_a.each do |k, v|
|
|
78
|
+
next unless k in Rational
|
|
79
|
+
version_defaults[k.to_f] = v
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
version_defaults[:original] = Config[0.0r]
|
|
83
|
+
version_defaults[:current] = Config[CURRENT_VERSION]
|
|
84
|
+
version_defaults[:next] = Config[NEXT_VERSION]
|
|
85
|
+
version_defaults[:future] = Config[FUTURE_VERSION]
|
|
86
|
+
|
|
87
|
+
version_defaults.freeze
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
data/lib/net/imap/config.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative "config/attr_accessors"
|
|
4
4
|
require_relative "config/attr_inheritance"
|
|
5
5
|
require_relative "config/attr_type_coercion"
|
|
6
|
+
require_relative "config/attr_version_defaults"
|
|
6
7
|
|
|
7
8
|
module Net
|
|
8
9
|
class IMAP
|
|
@@ -131,8 +132,17 @@ module Net
|
|
|
131
132
|
def self.global; @global if defined?(@global) end
|
|
132
133
|
|
|
133
134
|
# A hash of hard-coded configurations, indexed by version number or name.
|
|
134
|
-
|
|
135
|
-
|
|
135
|
+
# Values can be accessed with any object that responds to +to_sym+ or
|
|
136
|
+
# +to_r+/+to_f+ with a non-zero number.
|
|
137
|
+
#
|
|
138
|
+
# Config::[] gets named or numbered versions from this hash.
|
|
139
|
+
#
|
|
140
|
+
# For example:
|
|
141
|
+
# Net::IMAP::Config.version_defaults[0.5] == Net::IMAP::Config[0.5]
|
|
142
|
+
# Net::IMAP::Config[0.5] == Net::IMAP::Config[0.5r] # => true
|
|
143
|
+
# Net::IMAP::Config["current"] == Net::IMAP::Config[:current] # => true
|
|
144
|
+
# Net::IMAP::Config["0.5.6"] == Net::IMAP::Config[0.5r] # => true
|
|
145
|
+
def self.version_defaults; AttrVersionDefaults.version_defaults end
|
|
136
146
|
|
|
137
147
|
# :call-seq:
|
|
138
148
|
# Net::IMAP::Config[number] -> versioned config
|
|
@@ -155,24 +165,24 @@ module Net
|
|
|
155
165
|
elsif config.nil? && global.nil? then nil
|
|
156
166
|
elsif config.respond_to?(:to_hash) then new(global, **config).freeze
|
|
157
167
|
else
|
|
158
|
-
version_defaults
|
|
168
|
+
version_defaults[config] or
|
|
159
169
|
case config
|
|
160
170
|
when Numeric
|
|
161
171
|
raise RangeError, "unknown config version: %p" % [config]
|
|
162
|
-
when Symbol
|
|
172
|
+
when String, Symbol
|
|
163
173
|
raise KeyError, "unknown config name: %p" % [config]
|
|
164
174
|
else
|
|
165
175
|
raise TypeError, "no implicit conversion of %s to %s" % [
|
|
166
176
|
config.class, Config
|
|
167
177
|
]
|
|
168
178
|
end
|
|
169
|
-
end
|
|
170
179
|
end
|
|
171
180
|
end
|
|
172
181
|
|
|
173
182
|
include AttrAccessors
|
|
174
183
|
include AttrInheritance
|
|
175
184
|
include AttrTypeCoercion
|
|
185
|
+
extend AttrVersionDefaults
|
|
176
186
|
|
|
177
187
|
# The debug mode (boolean). The default value is +false+.
|
|
178
188
|
#
|
|
@@ -184,7 +194,7 @@ module Net
|
|
|
184
194
|
#
|
|
185
195
|
# *NOTE:* Versioned default configs inherit #debug from Config.global, and
|
|
186
196
|
# #load_defaults will not override #debug.
|
|
187
|
-
attr_accessor :debug, type: :boolean
|
|
197
|
+
attr_accessor :debug, type: :boolean, default: false
|
|
188
198
|
|
|
189
199
|
# method: debug?
|
|
190
200
|
# :call-seq: debug? -> boolean
|
|
@@ -193,13 +203,16 @@ module Net
|
|
|
193
203
|
|
|
194
204
|
# Seconds to wait until a connection is opened.
|
|
195
205
|
#
|
|
206
|
+
# Applied separately for establishing TCP connection and starting a TLS
|
|
207
|
+
# connection.
|
|
208
|
+
#
|
|
196
209
|
# If the IMAP object cannot open a connection within this time,
|
|
197
210
|
# it raises a Net::OpenTimeout exception.
|
|
198
211
|
#
|
|
199
|
-
# See Net::IMAP.new.
|
|
212
|
+
# See Net::IMAP.new and Net::IMAP#starttls.
|
|
200
213
|
#
|
|
201
214
|
# The default value is +30+ seconds.
|
|
202
|
-
attr_accessor :open_timeout, type: Integer
|
|
215
|
+
attr_accessor :open_timeout, type: Integer, default: 30
|
|
203
216
|
|
|
204
217
|
# Seconds to wait until an IDLE response is received, after
|
|
205
218
|
# the client asks to leave the IDLE state.
|
|
@@ -207,7 +220,7 @@ module Net
|
|
|
207
220
|
# See Net::IMAP#idle and Net::IMAP#idle_done.
|
|
208
221
|
#
|
|
209
222
|
# The default value is +5+ seconds.
|
|
210
|
-
attr_accessor :idle_response_timeout, type: Integer
|
|
223
|
+
attr_accessor :idle_response_timeout, type: Integer, default: 5
|
|
211
224
|
|
|
212
225
|
# Whether to use the +SASL-IR+ extension when the server and \SASL
|
|
213
226
|
# mechanism both support it. Can be overridden by the +sasl_ir+ keyword
|
|
@@ -223,7 +236,10 @@ module Net
|
|
|
223
236
|
#
|
|
224
237
|
# [+true+ <em>(default since +v0.4+)</em>]
|
|
225
238
|
# Use +SASL-IR+ when it is supported by the server and the mechanism.
|
|
226
|
-
attr_accessor :sasl_ir, type: :boolean
|
|
239
|
+
attr_accessor :sasl_ir, type: :boolean, defaults: {
|
|
240
|
+
0.0r => false,
|
|
241
|
+
0.4r => true,
|
|
242
|
+
}
|
|
227
243
|
|
|
228
244
|
# Controls the behavior of Net::IMAP#login when the +LOGINDISABLED+
|
|
229
245
|
# capability is present. When enforced, Net::IMAP will raise a
|
|
@@ -245,9 +261,49 @@ module Net
|
|
|
245
261
|
# present. When capabilities are unknown, Net::IMAP will automatically
|
|
246
262
|
# send a +CAPABILITY+ command first before sending +LOGIN+.
|
|
247
263
|
#
|
|
248
|
-
attr_accessor :enforce_logindisabled, type: [
|
|
264
|
+
attr_accessor :enforce_logindisabled, type: Enum[
|
|
249
265
|
false, :when_capabilities_cached, true
|
|
250
|
-
]
|
|
266
|
+
], defaults: {
|
|
267
|
+
0.0r => false,
|
|
268
|
+
0.5r => true,
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
# The maximum allowed server response size. When +nil+, there is no limit
|
|
272
|
+
# on response size.
|
|
273
|
+
#
|
|
274
|
+
# The default value (512 MiB, since +v0.5.7+) is <em>very high</em> and
|
|
275
|
+
# unlikely to be reached. A _much_ lower value should be used with
|
|
276
|
+
# untrusted servers (for example, when connecting to a user-provided
|
|
277
|
+
# hostname). When using a lower limit, message bodies should be fetched
|
|
278
|
+
# in chunks rather than all at once.
|
|
279
|
+
#
|
|
280
|
+
# <em>Please Note:</em> this only limits the size per response. It does
|
|
281
|
+
# not prevent a flood of individual responses and it does not limit how
|
|
282
|
+
# many unhandled responses may be stored on the responses hash. See
|
|
283
|
+
# Net::IMAP@Unbounded+memory+use.
|
|
284
|
+
#
|
|
285
|
+
# Socket reads are limited to the maximum remaining bytes for the current
|
|
286
|
+
# response: max_response_size minus the bytes that have already been read.
|
|
287
|
+
# When the limit is reached, or reading a +literal+ _would_ go over the
|
|
288
|
+
# limit, ResponseTooLargeError is raised and the connection is closed.
|
|
289
|
+
#
|
|
290
|
+
# Note that changes will not take effect immediately, because the receiver
|
|
291
|
+
# thread may already be waiting for the next response using the previous
|
|
292
|
+
# value. Net::IMAP#noop can force a response and enforce the new setting
|
|
293
|
+
# immediately.
|
|
294
|
+
#
|
|
295
|
+
# ==== Versioned Defaults
|
|
296
|
+
#
|
|
297
|
+
# Net::IMAP#max_response_size <em>was added in +v0.2.5+ and +v0.3.9+ as an
|
|
298
|
+
# attr_accessor, and in +v0.4.20+ and +v0.5.7+ as a delegator to this
|
|
299
|
+
# config attribute.</em>
|
|
300
|
+
#
|
|
301
|
+
# * original: +nil+ <em>(no limit)</em>
|
|
302
|
+
# * +0.5+: 512 MiB
|
|
303
|
+
attr_accessor :max_response_size, type: Integer?, defaults: {
|
|
304
|
+
0.0r => nil,
|
|
305
|
+
0.5r => 512 << 20, # 512 MiB
|
|
306
|
+
}
|
|
251
307
|
|
|
252
308
|
# Controls the behavior of Net::IMAP#responses when called without any
|
|
253
309
|
# arguments (+type+ or +block+).
|
|
@@ -275,9 +331,13 @@ module Net
|
|
|
275
331
|
# Raise an ArgumentError with the deprecation warning.
|
|
276
332
|
#
|
|
277
333
|
# Note: #responses_without_args is an alias for #responses_without_block.
|
|
278
|
-
attr_accessor :responses_without_block, type: [
|
|
334
|
+
attr_accessor :responses_without_block, type: Enum[
|
|
279
335
|
:silence_deprecation_warning, :warn, :frozen_dup, :raise,
|
|
280
|
-
]
|
|
336
|
+
], defaults: {
|
|
337
|
+
0.0r => :silence_deprecation_warning,
|
|
338
|
+
0.5r => :warn,
|
|
339
|
+
0.6r => :frozen_dup,
|
|
340
|
+
}
|
|
281
341
|
|
|
282
342
|
alias responses_without_args responses_without_block # :nodoc:
|
|
283
343
|
alias responses_without_args= responses_without_block= # :nodoc:
|
|
@@ -320,9 +380,13 @@ module Net
|
|
|
320
380
|
#
|
|
321
381
|
# [+false+ <em>(planned default for +v0.6+)</em>]
|
|
322
382
|
# ResponseParser _only_ uses AppendUIDData and CopyUIDData.
|
|
323
|
-
attr_accessor :parser_use_deprecated_uidplus_data, type: [
|
|
383
|
+
attr_accessor :parser_use_deprecated_uidplus_data, type: Enum[
|
|
324
384
|
true, :up_to_max_size, false
|
|
325
|
-
]
|
|
385
|
+
], defaults: {
|
|
386
|
+
0.0r => true,
|
|
387
|
+
0.5r => :up_to_max_size,
|
|
388
|
+
0.6r => false,
|
|
389
|
+
}
|
|
326
390
|
|
|
327
391
|
# The maximum +uid-set+ size that ResponseParser will parse into
|
|
328
392
|
# deprecated UIDPlusData. This limit only applies when
|
|
@@ -346,7 +410,13 @@ module Net
|
|
|
346
410
|
# * +0.5+: <tt>100</tt>
|
|
347
411
|
# * +0.6+: <tt>0</tt>
|
|
348
412
|
#
|
|
349
|
-
attr_accessor :parser_max_deprecated_uidplus_data_size, type: Integer
|
|
413
|
+
attr_accessor :parser_max_deprecated_uidplus_data_size, type: Integer,
|
|
414
|
+
defaults: {
|
|
415
|
+
0.0r => 10_000,
|
|
416
|
+
0.4r => 1_000,
|
|
417
|
+
0.5r => 100,
|
|
418
|
+
0.6r => 0,
|
|
419
|
+
}
|
|
350
420
|
|
|
351
421
|
# Creates a new config object and initialize its attribute with +attrs+.
|
|
352
422
|
#
|
|
@@ -421,50 +491,10 @@ module Net
|
|
|
421
491
|
to_h.reject {|k,v| DEFAULT_TO_INHERIT.include?(k) }
|
|
422
492
|
end
|
|
423
493
|
|
|
424
|
-
@default =
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
idle_response_timeout: 5,
|
|
428
|
-
sasl_ir: true,
|
|
429
|
-
enforce_logindisabled: true,
|
|
430
|
-
responses_without_block: :warn,
|
|
431
|
-
parser_use_deprecated_uidplus_data: :up_to_max_size,
|
|
432
|
-
parser_max_deprecated_uidplus_data_size: 100,
|
|
433
|
-
).freeze
|
|
434
|
-
|
|
435
|
-
@global = default.new
|
|
436
|
-
|
|
437
|
-
version_defaults[:default] = Config[default.send(:defaults_hash)]
|
|
438
|
-
version_defaults[:current] = Config[:default]
|
|
439
|
-
|
|
440
|
-
version_defaults[0] = Config[:current].dup.update(
|
|
441
|
-
sasl_ir: false,
|
|
442
|
-
responses_without_block: :silence_deprecation_warning,
|
|
443
|
-
enforce_logindisabled: false,
|
|
444
|
-
parser_use_deprecated_uidplus_data: true,
|
|
445
|
-
parser_max_deprecated_uidplus_data_size: 10_000,
|
|
446
|
-
).freeze
|
|
447
|
-
version_defaults[0.0] = Config[0]
|
|
448
|
-
version_defaults[0.1] = Config[0]
|
|
449
|
-
version_defaults[0.2] = Config[0]
|
|
450
|
-
version_defaults[0.3] = Config[0]
|
|
451
|
-
|
|
452
|
-
version_defaults[0.4] = Config[0.3].dup.update(
|
|
453
|
-
sasl_ir: true,
|
|
454
|
-
parser_max_deprecated_uidplus_data_size: 1000,
|
|
455
|
-
).freeze
|
|
456
|
-
|
|
457
|
-
version_defaults[0.5] = Config[:current]
|
|
458
|
-
|
|
459
|
-
version_defaults[0.6] = Config[0.5].dup.update(
|
|
460
|
-
responses_without_block: :frozen_dup,
|
|
461
|
-
parser_use_deprecated_uidplus_data: false,
|
|
462
|
-
parser_max_deprecated_uidplus_data_size: 0,
|
|
463
|
-
).freeze
|
|
464
|
-
version_defaults[:next] = Config[0.6]
|
|
465
|
-
version_defaults[:future] = Config[:next]
|
|
494
|
+
@default = AttrVersionDefaults.compile_default!
|
|
495
|
+
@global = default.new
|
|
496
|
+
AttrVersionDefaults.compile_version_defaults!
|
|
466
497
|
|
|
467
|
-
version_defaults.freeze
|
|
468
498
|
end
|
|
469
499
|
end
|
|
470
500
|
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Net
|
|
4
|
+
class IMAP
|
|
5
|
+
class ConnectionState < Net::IMAP::Data # :nodoc:
|
|
6
|
+
def self.define(symbol, *attrs)
|
|
7
|
+
symbol => Symbol
|
|
8
|
+
state = super(*attrs)
|
|
9
|
+
state.const_set :NAME, symbol
|
|
10
|
+
state
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def symbol; self.class::NAME end
|
|
14
|
+
def name; self.class::NAME.name end
|
|
15
|
+
alias to_sym symbol
|
|
16
|
+
|
|
17
|
+
def deconstruct; [symbol, *super] end
|
|
18
|
+
|
|
19
|
+
def deconstruct_keys(names)
|
|
20
|
+
hash = super
|
|
21
|
+
hash[:symbol] = symbol if names.nil? || names.include?(:symbol)
|
|
22
|
+
hash[:name] = name if names.nil? || names.include?(:name)
|
|
23
|
+
hash
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_h(&block)
|
|
27
|
+
hash = deconstruct_keys(nil)
|
|
28
|
+
block ? hash.to_h(&block) : hash
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def not_authenticated?; to_sym == :not_authenticated end
|
|
32
|
+
def authenticated?; to_sym == :authenticated end
|
|
33
|
+
def selected?; to_sym == :selected end
|
|
34
|
+
def logout?; to_sym == :logout end
|
|
35
|
+
|
|
36
|
+
NotAuthenticated = define(:not_authenticated)
|
|
37
|
+
Authenticated = define(:authenticated)
|
|
38
|
+
Selected = define(:selected)
|
|
39
|
+
Logout = define(:logout)
|
|
40
|
+
|
|
41
|
+
class << self
|
|
42
|
+
undef :define
|
|
43
|
+
end
|
|
44
|
+
freeze
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
end
|
data/lib/net/imap/errors.rb
CHANGED
|
@@ -17,6 +17,39 @@ module Net
|
|
|
17
17
|
class DataFormatError < Error
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
# Error raised when the socket cannot be read, due to a Config limit.
|
|
21
|
+
class ResponseReadError < Error
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Error raised when a response is larger than IMAP#max_response_size.
|
|
25
|
+
class ResponseTooLargeError < ResponseReadError
|
|
26
|
+
attr_reader :bytes_read, :literal_size
|
|
27
|
+
attr_reader :max_response_size
|
|
28
|
+
|
|
29
|
+
def initialize(msg = nil, *args,
|
|
30
|
+
bytes_read: nil,
|
|
31
|
+
literal_size: nil,
|
|
32
|
+
max_response_size: nil,
|
|
33
|
+
**kwargs)
|
|
34
|
+
@bytes_read = bytes_read
|
|
35
|
+
@literal_size = literal_size
|
|
36
|
+
@max_response_size = max_response_size
|
|
37
|
+
msg ||= [
|
|
38
|
+
"Response size", response_size_msg, "exceeds max_response_size",
|
|
39
|
+
max_response_size && "(#{max_response_size}B)",
|
|
40
|
+
].compact.join(" ")
|
|
41
|
+
super(msg, *args, **kwargs)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def response_size_msg
|
|
47
|
+
if bytes_read && literal_size
|
|
48
|
+
"(#{bytes_read}B read + #{literal_size}B literal)"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
20
53
|
# Error raised when a response from the server is non-parsable.
|
|
21
54
|
class ResponseParseError < Error
|
|
22
55
|
end
|
|
@@ -39,12 +39,49 @@ module Net
|
|
|
39
39
|
# numbers or UIDs, +to_a+ returns that set as an array of integers.
|
|
40
40
|
#
|
|
41
41
|
# When both #all and #partial are +nil+, either because the server
|
|
42
|
-
# returned no results or because +ALL+
|
|
43
|
-
# the IMAP#search +RETURN+ options, #to_a returns an empty array.
|
|
42
|
+
# returned no results or because neither +ALL+ or +PARTIAL+ were included
|
|
43
|
+
# in the IMAP#search +RETURN+ options, #to_a returns an empty array.
|
|
44
44
|
#
|
|
45
45
|
# Note that SearchResult also implements +to_a+, so it can be used without
|
|
46
46
|
# checking if the server returned +SEARCH+ or +ESEARCH+ data.
|
|
47
|
-
|
|
47
|
+
#
|
|
48
|
+
# Related: #each, #to_sequence_set, #all, #partial
|
|
49
|
+
def to_a; to_sequence_set.numbers end
|
|
50
|
+
|
|
51
|
+
# :call-seq: to_sequence_set -> SequenceSet or nil
|
|
52
|
+
#
|
|
53
|
+
# When either #all or #partial contains a SequenceSet of message sequence
|
|
54
|
+
# numbers or UIDs, +to_sequence_set+ returns that sequence set.
|
|
55
|
+
#
|
|
56
|
+
# When both #all and #partial are +nil+, either because the server
|
|
57
|
+
# returned no results or because neither +ALL+ or +PARTIAL+ were included
|
|
58
|
+
# in the IMAP#search +RETURN+ options, #to_sequence_set returns
|
|
59
|
+
# SequenceSet.empty.
|
|
60
|
+
#
|
|
61
|
+
# Note that SearchResult also implements +to_sequence_set+, so it can be
|
|
62
|
+
# used without checking if the server returned +SEARCH+ or +ESEARCH+ data.
|
|
63
|
+
#
|
|
64
|
+
# Related: #each, #to_a, #all, #partial
|
|
65
|
+
def to_sequence_set
|
|
66
|
+
all || partial&.to_sequence_set || SequenceSet.empty
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# When either #all or #partial contains a SequenceSet of message sequence
|
|
70
|
+
# numbers or UIDs, +each+ yields each integer in the set.
|
|
71
|
+
#
|
|
72
|
+
# When both #all and #partial are +nil+, either because the server
|
|
73
|
+
# returned no results or because +ALL+ and +PARTIAL+ were not included in
|
|
74
|
+
# the IMAP#search +RETURN+ options, #each does not yield.
|
|
75
|
+
#
|
|
76
|
+
# Note that SearchResult also implements +#each+, so it can be used
|
|
77
|
+
# without checking if the server returned +SEARCH+ or +ESEARCH+ data.
|
|
78
|
+
#
|
|
79
|
+
# Related: #to_sequence_set, #to_a, #all, #partial
|
|
80
|
+
def each(&)
|
|
81
|
+
return to_enum(__callee__) unless block_given?
|
|
82
|
+
to_sequence_set.each_number(&)
|
|
83
|
+
self
|
|
84
|
+
end
|
|
48
85
|
|
|
49
86
|
##
|
|
50
87
|
# attr_reader: tag
|
|
@@ -161,6 +198,8 @@ module Net
|
|
|
161
198
|
#
|
|
162
199
|
# See also: ESearchResult#to_a.
|
|
163
200
|
def to_a; results&.numbers || [] end
|
|
201
|
+
|
|
202
|
+
alias to_sequence_set results
|
|
164
203
|
end
|
|
165
204
|
|
|
166
205
|
# :call-seq: partial -> PartialResult or nil
|
data/lib/net/imap/flags.rb
CHANGED
|
@@ -6,7 +6,6 @@ module Net
|
|
|
6
6
|
autoload :FetchData, "#{__dir__}/fetch_data"
|
|
7
7
|
autoload :UIDFetchData, "#{__dir__}/fetch_data"
|
|
8
8
|
autoload :SearchResult, "#{__dir__}/search_result"
|
|
9
|
-
autoload :SequenceSet, "#{__dir__}/sequence_set"
|
|
10
9
|
autoload :UIDPlusData, "#{__dir__}/uidplus_data"
|
|
11
10
|
autoload :AppendUIDData, "#{__dir__}/uidplus_data"
|
|
12
11
|
autoload :CopyUIDData, "#{__dir__}/uidplus_data"
|