net-imap 0.4.12 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +7 -1
- data/lib/net/imap/authenticators.rb +2 -2
- data/lib/net/imap/command_data.rb +13 -2
- data/lib/net/imap/config/attr_accessors.rb +75 -0
- data/lib/net/imap/config/attr_inheritance.rb +90 -0
- data/lib/net/imap/config/attr_type_coercion.rb +61 -0
- data/lib/net/imap/config.rb +400 -0
- data/lib/net/imap/data_encoding.rb +3 -3
- data/lib/net/imap/deprecated_client_options.rb +8 -5
- data/lib/net/imap/errors.rb +6 -0
- data/lib/net/imap/response_data.rb +6 -93
- data/lib/net/imap/response_parser/parser_utils.rb +6 -6
- data/lib/net/imap/response_parser.rb +9 -17
- data/lib/net/imap/sasl/authentication_exchange.rb +52 -20
- data/lib/net/imap/sasl/authenticators.rb +8 -4
- data/lib/net/imap/sasl/client_adapter.rb +77 -26
- data/lib/net/imap/sasl/cram_md5_authenticator.rb +1 -1
- data/lib/net/imap/sasl/digest_md5_authenticator.rb +213 -51
- data/lib/net/imap/sasl/login_authenticator.rb +2 -1
- data/lib/net/imap/sasl/protocol_adapters.rb +60 -4
- data/lib/net/imap/sasl.rb +6 -3
- data/lib/net/imap/sasl_adapter.rb +0 -1
- data/lib/net/imap/sequence_set.rb +28 -24
- data/lib/net/imap.rb +467 -152
- data/net-imap.gemspec +3 -3
- data/rakelib/string_prep_tables_generator.rb +2 -0
- metadata +11 -10
- data/.github/dependabot.yml +0 -6
- data/.github/workflows/pages.yml +0 -46
- data/.github/workflows/push_gem.yml +0 -48
- data/.github/workflows/test.yml +0 -31
- data/.gitignore +0 -12
- data/.mailmap +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf511b8683c6931cf9ec2d3aa4a55ef634a2cc0e670590a4142d9895594b9191
|
4
|
+
data.tar.gz: db4ca0b7230553258e0d81a8a5b5cbed4273e30245200db661145ba430af20d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b61a04c6992df7d6ffcf0e5396723966c3f3a5a1c6a596caf413c63d355100c8d2c28096a2261045d52ada4d8e995bba1c4f12864bf65fe1355c331df236eb85
|
7
|
+
data.tar.gz: 0bc68ec15c5d53f0f437eab5318bf8cdd428dcdc650a98f66e961658ed361b125e866db2d41954e50ce66de5ec143d108e9135f554bd240ff0d7057724d16416
|
data/Gemfile
CHANGED
@@ -13,4 +13,10 @@ gem "rdoc"
|
|
13
13
|
gem "test-unit"
|
14
14
|
gem "test-unit-ruby-core", git: "https://github.com/ruby/test-unit-ruby-core"
|
15
15
|
|
16
|
-
gem "benchmark-driver"
|
16
|
+
gem "benchmark-driver", require: false
|
17
|
+
|
18
|
+
group :test do
|
19
|
+
gem "simplecov", require: false
|
20
|
+
gem "simplecov-html", require: false
|
21
|
+
gem "simplecov-json", require: false
|
22
|
+
end
|
@@ -9,7 +9,7 @@ module Net::IMAP::Authenticators
|
|
9
9
|
"%s.%s is deprecated. Use %s.%s instead." % [
|
10
10
|
Net::IMAP, __method__, Net::IMAP::SASL, __method__
|
11
11
|
],
|
12
|
-
uplevel: 1
|
12
|
+
uplevel: 1, category: :deprecated
|
13
13
|
)
|
14
14
|
Net::IMAP::SASL.add_authenticator(...)
|
15
15
|
end
|
@@ -20,7 +20,7 @@ module Net::IMAP::Authenticators
|
|
20
20
|
"%s.%s is deprecated. Use %s.%s instead." % [
|
21
21
|
Net::IMAP, __method__, Net::IMAP::SASL, __method__
|
22
22
|
],
|
23
|
-
uplevel: 1
|
23
|
+
uplevel: 1, category: :deprecated
|
24
24
|
)
|
25
25
|
Net::IMAP::SASL.authenticator(...)
|
26
26
|
end
|
@@ -40,10 +40,10 @@ module Net
|
|
40
40
|
send_number_data(data)
|
41
41
|
when Array
|
42
42
|
send_list_data(data, tag)
|
43
|
-
when Date
|
44
|
-
send_date_data(data)
|
45
43
|
when Time, DateTime
|
46
44
|
send_time_data(data)
|
45
|
+
when Date
|
46
|
+
send_date_data(data)
|
47
47
|
when Symbol
|
48
48
|
send_symbol_data(data)
|
49
49
|
else
|
@@ -179,6 +179,7 @@ module Net
|
|
179
179
|
end
|
180
180
|
end
|
181
181
|
|
182
|
+
# *DEPRECATED*. Replaced by SequenceSet.
|
182
183
|
class MessageSet # :nodoc:
|
183
184
|
def send_data(imap, tag)
|
184
185
|
imap.__send__(:put_string, format_internal(@data))
|
@@ -192,6 +193,16 @@ module Net
|
|
192
193
|
|
193
194
|
def initialize(data)
|
194
195
|
@data = data
|
196
|
+
warn("DEPRECATED: #{MessageSet} should be replaced with #{SequenceSet}.",
|
197
|
+
uplevel: 1, category: :deprecated)
|
198
|
+
begin
|
199
|
+
# to ensure the input works with SequenceSet, too
|
200
|
+
SequenceSet.new(data)
|
201
|
+
rescue
|
202
|
+
warn "MessageSet input is incompatible with SequenceSet: [%s] %s" % [
|
203
|
+
$!.class, $!.message
|
204
|
+
]
|
205
|
+
end
|
195
206
|
end
|
196
207
|
|
197
208
|
def format_internal(data)
|
@@ -0,0 +1,75 @@
|
|
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
|
+
# +attr_accessor+ values are stored in a struct rather than ivars, making
|
13
|
+
# it simpler to ensure that all config objects share a single object
|
14
|
+
# shape. This also simplifies iteration over all defined attributes.
|
15
|
+
module AttrAccessors
|
16
|
+
module Macros # :nodoc: internal API
|
17
|
+
def attr_accessor(name) AttrAccessors.attr_accessor(name) end
|
18
|
+
end
|
19
|
+
private_constant :Macros
|
20
|
+
|
21
|
+
def self.included(mod)
|
22
|
+
mod.extend Macros
|
23
|
+
end
|
24
|
+
private_class_method :included
|
25
|
+
|
26
|
+
extend Forwardable
|
27
|
+
|
28
|
+
def self.attr_accessor(name) # :nodoc: internal API
|
29
|
+
name = name.to_sym
|
30
|
+
def_delegators :data, name, :"#{name}="
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.attributes
|
34
|
+
instance_methods.grep(/=\z/).map { _1.to_s.delete_suffix("=").to_sym }
|
35
|
+
end
|
36
|
+
private_class_method :attributes
|
37
|
+
|
38
|
+
def self.struct # :nodoc: internal API
|
39
|
+
unless defined?(self::Struct)
|
40
|
+
const_set :Struct, Struct.new(*attributes)
|
41
|
+
end
|
42
|
+
self::Struct
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize # :notnew:
|
46
|
+
super()
|
47
|
+
@data = AttrAccessors.struct.new
|
48
|
+
end
|
49
|
+
|
50
|
+
# Freezes the internal attributes struct, in addition to +self+.
|
51
|
+
def freeze
|
52
|
+
data.freeze
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
attr_reader :data # :nodoc: internal API
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def initialize_clone(other)
|
63
|
+
super
|
64
|
+
@data = other.data.clone
|
65
|
+
end
|
66
|
+
|
67
|
+
def initialize_dup(other)
|
68
|
+
super
|
69
|
+
@data = other.data.dup
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Net
|
4
|
+
class IMAP
|
5
|
+
class Config
|
6
|
+
# >>>
|
7
|
+
# *NOTE:* The public methods on this module are part of the stable
|
8
|
+
# public API of Net::IMAP::Config. But the module itself is an internal
|
9
|
+
# implementation detail, with no guarantee of backward compatibility.
|
10
|
+
#
|
11
|
+
# +attr_accessor+ methods will delegate to their #parent when the local
|
12
|
+
# value does not contain an override. Inheritance forms a singly linked
|
13
|
+
# list, so lookup will be <tt>O(n)</tt> on the number of ancestors. In
|
14
|
+
# practice, the ancestor chain is not expected to be long. Without
|
15
|
+
# customization, it is only three deep:
|
16
|
+
# >>>
|
17
|
+
# IMAP#config → Config.global → Config.default
|
18
|
+
#
|
19
|
+
# When creating a client with the +config+ keyword, for example to use
|
20
|
+
# the appropriate defaults for an application or a library while still
|
21
|
+
# relying on global for configuration of +debug+ or +logger+, most likely
|
22
|
+
# the ancestor chain is still only four deep:
|
23
|
+
# >>>
|
24
|
+
# IMAP#config → alternate defaults → Config.global → Config.default
|
25
|
+
module AttrInheritance
|
26
|
+
INHERITED = Module.new.freeze
|
27
|
+
private_constant :INHERITED
|
28
|
+
|
29
|
+
module Macros # :nodoc: internal API
|
30
|
+
def attr_accessor(name) super; AttrInheritance.attr_accessor(name) end
|
31
|
+
end
|
32
|
+
private_constant :Macros
|
33
|
+
|
34
|
+
def self.included(mod)
|
35
|
+
mod.extend Macros
|
36
|
+
end
|
37
|
+
private_class_method :included
|
38
|
+
|
39
|
+
def self.attr_accessor(name) # :nodoc: internal API
|
40
|
+
module_eval <<~RUBY, __FILE__, __LINE__ + 1
|
41
|
+
def #{name}; (val = super) == INHERITED ? parent&.#{name} : val end
|
42
|
+
RUBY
|
43
|
+
end
|
44
|
+
|
45
|
+
# The parent Config object
|
46
|
+
attr_reader :parent
|
47
|
+
|
48
|
+
def initialize(parent = nil) # :notnew:
|
49
|
+
super()
|
50
|
+
@parent = Config[parent]
|
51
|
+
reset
|
52
|
+
end
|
53
|
+
|
54
|
+
# Creates a new config, which inherits from +self+.
|
55
|
+
def new(**attrs) self.class.new(self, **attrs) end
|
56
|
+
|
57
|
+
# Returns +true+ if +attr+ is inherited from #parent and not overridden
|
58
|
+
# by this config.
|
59
|
+
def inherited?(attr) data[attr] == INHERITED end
|
60
|
+
|
61
|
+
# :call-seq:
|
62
|
+
# reset -> self
|
63
|
+
# reset(attr) -> attribute value
|
64
|
+
#
|
65
|
+
# Resets an +attr+ to inherit from the #parent config.
|
66
|
+
#
|
67
|
+
# When +attr+ is nil or not given, all attributes are reset.
|
68
|
+
def reset(attr = nil)
|
69
|
+
if attr.nil?
|
70
|
+
data.members.each do |attr| data[attr] = INHERITED end
|
71
|
+
self
|
72
|
+
elsif inherited?(attr)
|
73
|
+
nil
|
74
|
+
else
|
75
|
+
old, data[attr] = data[attr], INHERITED
|
76
|
+
old
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def initialize_copy(other)
|
83
|
+
super
|
84
|
+
@parent ||= other # only default has nil parent
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Net
|
4
|
+
class IMAP
|
5
|
+
class Config
|
6
|
+
# >>>
|
7
|
+
# *NOTE:* This module is an internal implementation detail, with no
|
8
|
+
# guarantee of backward compatibility.
|
9
|
+
#
|
10
|
+
# Adds a +type+ keyword parameter to +attr_accessor+, to enforce that
|
11
|
+
# config attributes have valid types, for example: boolean, numeric,
|
12
|
+
# enumeration, non-nullable, etc.
|
13
|
+
module AttrTypeCoercion
|
14
|
+
# :stopdoc: internal APIs only
|
15
|
+
|
16
|
+
module Macros # :nodoc: internal API
|
17
|
+
def attr_accessor(attr, type: nil)
|
18
|
+
super(attr)
|
19
|
+
AttrTypeCoercion.attr_accessor(attr, type: type)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
private_constant :Macros
|
23
|
+
|
24
|
+
def self.included(mod)
|
25
|
+
mod.extend Macros
|
26
|
+
end
|
27
|
+
private_class_method :included
|
28
|
+
|
29
|
+
def self.attr_accessor(attr, type: nil)
|
30
|
+
return unless type
|
31
|
+
if :boolean == type then boolean attr
|
32
|
+
elsif Integer == type then integer attr
|
33
|
+
elsif Array === type then enum attr, type
|
34
|
+
else raise ArgumentError, "unknown type coercion %p" % [type]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.boolean(attr)
|
39
|
+
define_method :"#{attr}=" do |val| super !!val end
|
40
|
+
define_method :"#{attr}?" do send attr end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.integer(attr)
|
44
|
+
define_method :"#{attr}=" do |val| super Integer val end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.enum(attr, enum)
|
48
|
+
enum = enum.dup.freeze
|
49
|
+
expected = -"one of #{enum.map(&:inspect).join(", ")}"
|
50
|
+
define_method :"#{attr}=" do |val|
|
51
|
+
unless enum.include?(val)
|
52
|
+
raise ArgumentError, "expected %s, got %p" % [expected, val]
|
53
|
+
end
|
54
|
+
super val
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|