net-imap 0.4.12 → 0.4.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5147af8d1017e772136634ea2144c33a1666a00a25d03de20a6d89f9b026ecc
4
- data.tar.gz: 66a41c1fcfc932da451f65074ae6659d872b85aeeef831208cf47178f944cd08
3
+ metadata.gz: 1a7254a9f8865dfd12d8887a0ce62f58d764f43acb3eea019fadd13ff3f6983c
4
+ data.tar.gz: 8a3ae5456b5a7d78f72d862e6dcf8f8df86ec6a3d32956314c1eadc36bf5def0
5
5
  SHA512:
6
- metadata.gz: 67a5545d46acd17051097ad3e10304817980fad7621ca0225c614f8bd49d62365d9b9d3305fa1ac3fbebd63bd1ba2155cb5a94d448ca6a6763655dd31cdb22a2
7
- data.tar.gz: dbc107f94925486cbc3eb28a26c45560fce568f3836d65127628599fd7a117046d5cc0225f1999b387802316b781bce367da5b660da79200c7e576515669ca70
6
+ metadata.gz: 41ee8dd354e77a06f4875ad559efb6dbae6f60c39ad714d0de46efe8a49e125194b48e02cce4d1425c73122c57ec300dcd4e7707409bcf964318146b3b9e6168
7
+ data.tar.gz: 215057347ecca04a9816df24b5250f124b2b655615507ef84e6b2a12567b23810da9f394f74801cd046c18e7d01072a567b95eb241bb7db7896982e9d24e414f
@@ -0,0 +1,70 @@
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_dup(other)
63
+ super
64
+ @data = other.data.dup
65
+ end
66
+
67
+ end
68
+ end
69
+ end
70
+ 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
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "config/attr_accessors"
4
+ require_relative "config/attr_inheritance"
5
+ require_relative "config/attr_type_coercion"
6
+
7
+ module Net
8
+ class IMAP
9
+
10
+ # Net::IMAP::Config stores configuration options for Net::IMAP clients.
11
+ # The global configuration can be seen at either Net::IMAP.config or
12
+ # Net::IMAP::Config.global, and the client-specific configuration can be
13
+ # seen at Net::IMAP#config.
14
+ #
15
+ # When creating a new client, all unhandled keyword arguments to
16
+ # Net::IMAP.new are delegated to Config.new. Every client has its own
17
+ # config.
18
+ #
19
+ # debug_client = Net::IMAP.new(hostname, debug: true)
20
+ # quiet_client = Net::IMAP.new(hostname, debug: false)
21
+ # debug_client.config.debug? # => true
22
+ # quiet_client.config.debug? # => false
23
+ #
24
+ # == Inheritance
25
+ #
26
+ # Configs have a parent[rdoc-ref:Config::AttrInheritance#parent] config, and
27
+ # any attributes which have not been set locally will inherit the parent's
28
+ # value. Every client creates its own specific config. By default, client
29
+ # configs inherit from Config.global.
30
+ #
31
+ # plain_client = Net::IMAP.new(hostname)
32
+ # debug_client = Net::IMAP.new(hostname, debug: true)
33
+ # quiet_client = Net::IMAP.new(hostname, debug: false)
34
+ #
35
+ # plain_client.config.inherited?(:debug) # => true
36
+ # debug_client.config.inherited?(:debug) # => false
37
+ # quiet_client.config.inherited?(:debug) # => false
38
+ #
39
+ # plain_client.config.debug? # => false
40
+ # debug_client.config.debug? # => true
41
+ # quiet_client.config.debug? # => false
42
+ #
43
+ # # Net::IMAP.debug is delegated to Net::IMAP::Config.global.debug
44
+ # Net::IMAP.debug = true
45
+ # plain_client.config.debug? # => true
46
+ # debug_client.config.debug? # => true
47
+ # quiet_client.config.debug? # => false
48
+ #
49
+ # Net::IMAP.debug = false
50
+ # plain_client.config.debug = true
51
+ # plain_client.config.inherited?(:debug) # => false
52
+ # plain_client.config.debug? # => true
53
+ # plain_client.config.reset(:debug)
54
+ # plain_client.config.inherited?(:debug) # => true
55
+ # plain_client.config.debug? # => false
56
+ #
57
+ #
58
+ # == Thread Safety
59
+ #
60
+ # *NOTE:* Updates to config objects are not synchronized for thread-safety.
61
+ #
62
+ class Config
63
+ # The default config, which is hardcoded and frozen.
64
+ def self.default; @default end
65
+
66
+ # The global config object. Also available from Net::IMAP.config.
67
+ def self.global; @global end
68
+
69
+ def self.[](config) # :nodoc: unfinished API
70
+ if config.is_a?(Config) || config.nil? && global.nil?
71
+ config
72
+ else
73
+ raise TypeError, "no implicit conversion of %s to %s" % [
74
+ config.class, Config
75
+ ]
76
+ end
77
+ end
78
+
79
+ include AttrAccessors
80
+ include AttrInheritance
81
+ include AttrTypeCoercion
82
+
83
+ # The debug mode (boolean)
84
+ #
85
+ # The default value is +false+.
86
+ attr_accessor :debug, type: :boolean
87
+
88
+ # method: debug?
89
+ # :call-seq: debug? -> boolean
90
+ #
91
+ # Alias for #debug
92
+
93
+ # Seconds to wait until a connection is opened.
94
+ #
95
+ # If the IMAP object cannot open a connection within this time,
96
+ # it raises a Net::OpenTimeout exception.
97
+ #
98
+ # See Net::IMAP.new.
99
+ #
100
+ # The default value is +30+ seconds.
101
+ attr_accessor :open_timeout, type: Integer
102
+
103
+ # Seconds to wait until an IDLE response is received, after
104
+ # the client asks to leave the IDLE state.
105
+ #
106
+ # See Net::IMAP#idle and Net::IMAP#idle_done.
107
+ #
108
+ # The default value is +5+ seconds.
109
+ attr_accessor :idle_response_timeout, type: Integer
110
+
111
+ # :markup: markdown
112
+ #
113
+ # Whether to use the +SASL-IR+ extension when the server and \SASL
114
+ # mechanism both support it.
115
+ #
116
+ # See Net::IMAP#authenticate.
117
+ #
118
+ # | Starting with version | The default value is |
119
+ # |-----------------------|------------------------------------------|
120
+ # | _original_ | +false+ <em>(extension unsupported)</em> |
121
+ # | v0.4 | +true+ <em>(support added)</em> |
122
+ attr_accessor :sasl_ir, type: :boolean
123
+
124
+ # :markup: markdown
125
+ #
126
+ # Controls the behavior of Net::IMAP#responses when called without a
127
+ # block. Valid options are `:warn`, `:raise`, or
128
+ # `:silence_deprecation_warning`.
129
+ #
130
+ # | Starting with version | The default value is |
131
+ # |-------------------------|--------------------------------|
132
+ # | v0.4.13 | +:silence_deprecation_warning+ |
133
+ # | v0.5 <em>(planned)</em> | +:warn+ |
134
+ # | _eventually_ | +:raise+ |
135
+ attr_accessor :responses_without_block, type: [
136
+ :silence_deprecation_warning, :warn, :raise,
137
+ ]
138
+
139
+ # Creates a new config object and initialize its attribute with +attrs+.
140
+ #
141
+ # If +parent+ is not given, the global config is used by default.
142
+ #
143
+ # If a block is given, the new config object is yielded to it.
144
+ def initialize(parent = Config.global, **attrs)
145
+ super(parent)
146
+ attrs.each do send(:"#{_1}=", _2) end
147
+ yield self if block_given?
148
+ end
149
+
150
+ @default = new(
151
+ debug: false,
152
+ open_timeout: 30,
153
+ idle_response_timeout: 5,
154
+ sasl_ir: true,
155
+ responses_without_block: :silence_deprecation_warning,
156
+ ).freeze
157
+
158
+ @global = default.new
159
+
160
+ end
161
+ end
162
+ end
@@ -16,8 +16,8 @@ module Net
16
16
  #
17
17
  # ==== Obsolete arguments
18
18
  #
19
- # Using obsolete arguments does not a warning. Obsolete arguments will be
20
- # deprecated by a future release.
19
+ # Use of obsolete arguments does not print a warning. Obsolete arguments
20
+ # will be deprecated by a future release.
21
21
  #
22
22
  # If a second positional argument is given and it is a hash (or is
23
23
  # convertible via +#to_hash+), it is converted to keyword arguments.
@@ -154,7 +154,7 @@ module Net
154
154
  end
155
155
 
156
156
  # To be used conditionally:
157
- # assert_no_lookahead if Net::IMAP.debug
157
+ # assert_no_lookahead if config.debug?
158
158
  def assert_no_lookahead
159
159
  @token.nil? or
160
160
  parse_error("assertion failed: expected @token.nil?, actual %s: %p",
@@ -181,23 +181,23 @@ module Net
181
181
  end
182
182
 
183
183
  def peek_str?(str)
184
- assert_no_lookahead if Net::IMAP.debug
184
+ assert_no_lookahead if config.debug?
185
185
  @str[@pos, str.length] == str
186
186
  end
187
187
 
188
188
  def peek_re(re)
189
- assert_no_lookahead if Net::IMAP.debug
189
+ assert_no_lookahead if config.debug?
190
190
  re.match(@str, @pos)
191
191
  end
192
192
 
193
193
  def accept_re(re)
194
- assert_no_lookahead if Net::IMAP.debug
194
+ assert_no_lookahead if config.debug?
195
195
  re.match(@str, @pos) and @pos = $~.end(0)
196
196
  $~
197
197
  end
198
198
 
199
199
  def match_re(re, name)
200
- assert_no_lookahead if Net::IMAP.debug
200
+ assert_no_lookahead if config.debug?
201
201
  if re.match(@str, @pos)
202
202
  @pos = $~.end(0)
203
203
  $~
@@ -212,7 +212,7 @@ module Net
212
212
 
213
213
  def parse_error(fmt, *args)
214
214
  msg = format(fmt, *args)
215
- if IMAP.debug
215
+ if config.debug?
216
216
  local_path = File.dirname(__dir__)
217
217
  tok = @token ? "%s: %p" % [@token.symbol, @token.value] : "nil"
218
218
  warn "%s %s: %s" % [self.class, __method__, msg]
@@ -11,12 +11,15 @@ module Net
11
11
  include ParserUtils
12
12
  extend ParserUtils::Generator
13
13
 
14
+ attr_reader :config
15
+
14
16
  # :call-seq: Net::IMAP::ResponseParser.new -> Net::IMAP::ResponseParser
15
- def initialize
17
+ def initialize(config: Config.global)
16
18
  @str = nil
17
19
  @pos = nil
18
20
  @lex_state = nil
19
21
  @token = nil
22
+ @config = Config[config]
20
23
  end
21
24
 
22
25
  # :call-seq:
data/lib/net/imap.rb CHANGED
@@ -717,7 +717,7 @@ module Net
717
717
  # * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
718
718
  #
719
719
  class IMAP < Protocol
720
- VERSION = "0.4.12"
720
+ VERSION = "0.4.13"
721
721
 
722
722
  # Aliases for supported capabilities, to be used with the #enable command.
723
723
  ENABLE_ALIASES = {
@@ -735,14 +735,15 @@ module Net
735
735
  include SSL
736
736
  end
737
737
 
738
- # Returns the debug mode.
739
- def self.debug
740
- return @@debug
741
- end
738
+ # Returns the global Config object
739
+ def self.config; Config.global end
740
+
741
+ # Returns the global debug mode.
742
+ def self.debug; config.debug end
742
743
 
743
- # Sets the debug mode.
744
+ # Sets the global debug mode.
744
745
  def self.debug=(val)
745
- return @@debug = val
746
+ config.debug = val
746
747
  end
747
748
 
748
749
  # The default port for IMAP connections, port 143
@@ -764,13 +765,19 @@ module Net
764
765
  # Returns the initial greeting the server, an UntaggedResponse.
765
766
  attr_reader :greeting
766
767
 
768
+ # The client configuration. See Net::IMAP::Config.
769
+ #
770
+ # By default, the client's local configuration inherits from the global
771
+ # Net::IMAP.config.
772
+ attr_reader :config
773
+
767
774
  # Seconds to wait until a connection is opened.
768
775
  # If the IMAP object cannot open a connection within this time,
769
776
  # it raises a Net::OpenTimeout exception. The default value is 30 seconds.
770
- attr_reader :open_timeout
777
+ def open_timeout; config.open_timeout end
771
778
 
772
779
  # Seconds to wait until an IDLE response is received.
773
- attr_reader :idle_response_timeout
780
+ def idle_response_timeout; config.idle_response_timeout end
774
781
 
775
782
  # The hostname this client connected to
776
783
  attr_reader :host
@@ -809,14 +816,40 @@ module Net
809
816
  # If +ssl+ is a hash, it's passed to
810
817
  # {OpenSSL::SSL::SSLContext#set_params}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-set_params];
811
818
  # the keys are names of attribute assignment methods on
812
- # SSLContext[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html].
819
+ # SSLContext[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html]. For example:
820
+ #
821
+ # [{ca_file}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#attribute-i-ca_file]]
822
+ # The path to a file containing a PEM-format CA certificate.
823
+ # [{ca_path}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#attribute-i-ca_path]]
824
+ # The path to a directory containing CA certificates in PEM format.
825
+ # [{min_version}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-min_version-3D]]
826
+ # Sets the lower bound on the supported SSL/TLS protocol version. Set to
827
+ # an +OpenSSL+ constant such as +OpenSSL::SSL::TLS1_2_VERSION+,
828
+ # [{verify_mode}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#attribute-i-verify_mode]]
829
+ # SSL session verification mode. Valid modes include
830
+ # +OpenSSL::SSL::VERIFY_PEER+ and +OpenSSL::SSL::VERIFY_NONE+.
831
+ #
832
+ # See {OpenSSL::SSL::SSLContext}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html] for other valid SSL context params.
833
+ #
834
+ # See DeprecatedClientOptions.new for deprecated SSL arguments.
813
835
  #
814
- # [open_timeout]
815
- # Seconds to wait until a connection is opened
816
- # [idle_response_timeout]
817
- # Seconds to wait until an IDLE response is received
836
+ # [config]
837
+ # A Net::IMAP::Config object to use as the basis for #config. By default,
838
+ # the global Net::IMAP.config is used.
818
839
  #
819
- # See DeprecatedClientOptions.new for deprecated arguments.
840
+ # >>>
841
+ # *NOTE:* +config+ does not set #config directly---it sets the _parent_
842
+ # config for inheritance. Every client creates its own unique #config.
843
+ #
844
+ # All other keyword arguments are forwarded to Net::IMAP::Config.new, to
845
+ # initialize the client's #config. For example:
846
+ #
847
+ # [{open_timeout}[rdoc-ref:Config#open_timeout]]
848
+ # Seconds to wait until a connection is opened
849
+ # [{idle_response_timeout}[rdoc-ref:Config#idle_response_timeout]]
850
+ # Seconds to wait until an IDLE response is received
851
+ #
852
+ # See Net::IMAP::Config for other valid options.
820
853
  #
821
854
  # ==== Examples
822
855
  #
@@ -872,13 +905,12 @@ module Net
872
905
  # Connected to the host successfully, but it immediately said goodbye.
873
906
  #
874
907
  def initialize(host, port: nil, ssl: nil,
875
- open_timeout: 30, idle_response_timeout: 5)
908
+ config: Config.global, **config_options)
876
909
  super()
877
910
  # Config options
878
911
  @host = host
912
+ @config = Config.new(config, **config_options)
879
913
  @port = port || (ssl ? SSL_PORT : PORT)
880
- @open_timeout = Integer(open_timeout)
881
- @idle_response_timeout = Integer(idle_response_timeout)
882
914
  @ssl_ctx_params, @ssl_ctx = build_ssl_ctx(ssl)
883
915
 
884
916
  # Basic Client State
@@ -889,7 +921,7 @@ module Net
889
921
  @capabilities = nil
890
922
 
891
923
  # Client Protocol Receiver
892
- @parser = ResponseParser.new
924
+ @parser = ResponseParser.new(config: @config)
893
925
  @responses = Hash.new {|h, k| h[k] = [] }
894
926
  @response_handlers = []
895
927
  @receiver_thread = nil
@@ -1198,7 +1230,7 @@ module Net
1198
1230
  end
1199
1231
 
1200
1232
  # :call-seq:
1201
- # authenticate(mechanism, *, sasl_ir: true, registry: Net::IMAP::SASL.authenticators, **, &) -> ok_resp
1233
+ # authenticate(mechanism, *, sasl_ir: config.sasl_ir, registry: Net::IMAP::SASL.authenticators, **, &) -> ok_resp
1202
1234
  #
1203
1235
  # Sends an {AUTHENTICATE command [IMAP4rev1 §6.2.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.2.2]
1204
1236
  # to authenticate the client. If successful, the connection enters the
@@ -1207,7 +1239,8 @@ module Net
1207
1239
  # +mechanism+ is the name of the \SASL authentication mechanism to be used.
1208
1240
  #
1209
1241
  # +sasl_ir+ allows or disallows sending an "initial response" (see the
1210
- # +SASL-IR+ capability, below).
1242
+ # +SASL-IR+ capability, below). Defaults to the #config value for
1243
+ # {sasl_ir}[rdoc-ref:Config#sasl_ir], which defaults to +true+.
1211
1244
  #
1212
1245
  # All other arguments are forwarded to the registered SASL authenticator for
1213
1246
  # the requested mechanism. <em>The documentation for each individual
@@ -1303,7 +1336,9 @@ module Net
1303
1336
  # Previously cached #capabilities will be cleared when this method
1304
1337
  # completes. If the TaggedResponse to #authenticate includes updated
1305
1338
  # capabilities, they will be cached.
1306
- def authenticate(mechanism, *creds, sasl_ir: true, **props, &callback)
1339
+ def authenticate(mechanism, *creds,
1340
+ sasl_ir: config.sasl_ir,
1341
+ **props, &callback)
1307
1342
  mechanism = mechanism.to_s.tr("_", "-").upcase
1308
1343
  authenticator = SASL.authenticator(mechanism, *creds, **props, &callback)
1309
1344
  cmdargs = ["AUTHENTICATE", mechanism]
@@ -2397,11 +2432,17 @@ module Net
2397
2432
  # checks the connection for each 60 seconds.
2398
2433
  #
2399
2434
  # loop do
2400
- # imap.idle(60) do |res|
2401
- # ...
2435
+ # imap.idle(60) do |response|
2436
+ # do_something_with(response)
2437
+ # imap.idle_done if some_condition?(response)
2402
2438
  # end
2403
2439
  # end
2404
2440
  #
2441
+ # Returns the server's response to indicate the IDLE state has ended.
2442
+ # Returns +nil+ if the server does not respond to #idle_done within
2443
+ # {config.idle_response_timeout}[rdoc-ref:Config#idle_response_timeout]
2444
+ # seconds.
2445
+ #
2405
2446
  # Related: #idle_done, #noop, #check
2406
2447
  #
2407
2448
  # ===== Capabilities
@@ -2429,7 +2470,7 @@ module Net
2429
2470
  unless @receiver_thread_terminating
2430
2471
  remove_response_handler(response_handler)
2431
2472
  put_string("DONE#{CRLF}")
2432
- response = get_tagged_response(tag, "IDLE", @idle_response_timeout)
2473
+ response = get_tagged_response(tag, "IDLE", idle_response_timeout)
2433
2474
  end
2434
2475
  end
2435
2476
  end
@@ -2437,7 +2478,11 @@ module Net
2437
2478
  return response
2438
2479
  end
2439
2480
 
2440
- # Leaves IDLE.
2481
+ # Leaves IDLE, allowing #idle to return.
2482
+ #
2483
+ # If the server does not respond within
2484
+ # {config.idle_response_timeout}[rdoc-ref:Config#idle_response_timeout]
2485
+ # seconds, #idle will return +nil+.
2441
2486
  #
2442
2487
  # Related: #idle
2443
2488
  def idle_done
@@ -2477,6 +2522,7 @@ module Net
2477
2522
  #
2478
2523
  # Calling without a block is unsafe and deprecated. Future releases will
2479
2524
  # raise ArgumentError unless a block is given.
2525
+ # See Config#responses_without_block.
2480
2526
  #
2481
2527
  # Previously unhandled responses are automatically cleared before entering a
2482
2528
  # mailbox with #select or #examine. Long-lived connections can receive many
@@ -2501,7 +2547,12 @@ module Net
2501
2547
  elsif type
2502
2548
  raise ArgumentError, "Pass a block or use #clear_responses"
2503
2549
  else
2504
- # warn("DEPRECATED: pass a block or use #clear_responses", uplevel: 1)
2550
+ case config.responses_without_block
2551
+ when :raise
2552
+ raise ArgumentError, "Pass a block or use #clear_responses"
2553
+ when :warn
2554
+ warn("DEPRECATED: pass a block or use #clear_responses", uplevel: 1)
2555
+ end
2505
2556
  @responses
2506
2557
  end
2507
2558
  end
@@ -2582,8 +2633,6 @@ module Net
2582
2633
  PORT = 143 # :nodoc:
2583
2634
  SSL_PORT = 993 # :nodoc:
2584
2635
 
2585
- @@debug = false
2586
-
2587
2636
  def start_imap_connection
2588
2637
  @greeting = get_server_greeting
2589
2638
  @capabilities = capabilities_from_resp_code @greeting
@@ -2611,12 +2660,12 @@ module Net
2611
2660
  end
2612
2661
 
2613
2662
  def tcp_socket(host, port)
2614
- s = Socket.tcp(host, port, :connect_timeout => @open_timeout)
2663
+ s = Socket.tcp(host, port, :connect_timeout => open_timeout)
2615
2664
  s.setsockopt(:SOL_SOCKET, :SO_KEEPALIVE, true)
2616
2665
  s
2617
2666
  rescue Errno::ETIMEDOUT
2618
2667
  raise Net::OpenTimeout, "Timeout to open TCP connection to " +
2619
- "#{host}:#{port} (exceeds #{@open_timeout} seconds)"
2668
+ "#{host}:#{port} (exceeds #{open_timeout} seconds)"
2620
2669
  end
2621
2670
 
2622
2671
  def receive_responses
@@ -2728,7 +2777,7 @@ module Net
2728
2777
  end
2729
2778
  end
2730
2779
  return nil if buff.length == 0
2731
- if @@debug
2780
+ if config.debug?
2732
2781
  $stderr.print(buff.gsub(/^/n, "S: "))
2733
2782
  end
2734
2783
  return @parser.parse(buff)
@@ -2807,7 +2856,7 @@ module Net
2807
2856
 
2808
2857
  def put_string(str)
2809
2858
  @sock.print(str)
2810
- if @@debug
2859
+ if config.debug?
2811
2860
  if @debug_output_bol
2812
2861
  $stderr.print("C: ")
2813
2862
  end
@@ -2934,7 +2983,7 @@ module Net
2934
2983
  @sock = SSLSocket.new(@sock, ssl_ctx)
2935
2984
  @sock.sync_close = true
2936
2985
  @sock.hostname = @host if @sock.respond_to? :hostname=
2937
- ssl_socket_connect(@sock, @open_timeout)
2986
+ ssl_socket_connect(@sock, open_timeout)
2938
2987
  if ssl_ctx.verify_mode != VERIFY_NONE
2939
2988
  @sock.post_connection_check(@host)
2940
2989
  @tls_verified = true
@@ -2959,6 +3008,7 @@ module Net
2959
3008
  end
2960
3009
 
2961
3010
  require_relative "imap/errors"
3011
+ require_relative "imap/config"
2962
3012
  require_relative "imap/command_data"
2963
3013
  require_relative "imap/data_encoding"
2964
3014
  require_relative "imap/flags"
data/net-imap.gemspec CHANGED
@@ -25,9 +25,9 @@ Gem::Specification.new do |spec|
25
25
 
26
26
  # Specify which files should be added to the gem when it is released.
27
27
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
28
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
28
+ spec.files = Dir.chdir(__dir__) do
29
29
  `git ls-files -z 2>/dev/null`.split("\x0")
30
- .grep_v(%r{^(\.git|\.mailmap|bin|test|spec|benchmarks|features|rfcs)/})
30
+ .grep_v(%r{^(\.git(ignore)?|\.mailmap|(\.github|bin|test|spec|benchmarks|features|rfcs)/)})
31
31
  end
32
32
  spec.bindir = "exe"
33
33
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-imap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.12
4
+ version: 0.4.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shugo Maeda
8
8
  - nicholas a. evans
9
+ autorequire:
9
10
  bindir: exe
10
11
  cert_chain: []
11
- date: 2024-06-01 00:00:00.000000000 Z
12
+ date: 2024-06-16 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: net-protocol
@@ -46,12 +47,6 @@ executables: []
46
47
  extensions: []
47
48
  extra_rdoc_files: []
48
49
  files:
49
- - ".github/dependabot.yml"
50
- - ".github/workflows/pages.yml"
51
- - ".github/workflows/push_gem.yml"
52
- - ".github/workflows/test.yml"
53
- - ".gitignore"
54
- - ".mailmap"
55
50
  - BSDL
56
51
  - COPYING
57
52
  - Gemfile
@@ -62,6 +57,10 @@ files:
62
57
  - lib/net/imap.rb
63
58
  - lib/net/imap/authenticators.rb
64
59
  - lib/net/imap/command_data.rb
60
+ - lib/net/imap/config.rb
61
+ - lib/net/imap/config/attr_accessors.rb
62
+ - lib/net/imap/config/attr_inheritance.rb
63
+ - lib/net/imap/config/attr_type_coercion.rb
65
64
  - lib/net/imap/data_encoding.rb
66
65
  - lib/net/imap/deprecated_client_options.rb
67
66
  - lib/net/imap/errors.rb
@@ -111,6 +110,7 @@ metadata:
111
110
  homepage_uri: https://github.com/ruby/net-imap
112
111
  source_code_uri: https://github.com/ruby/net-imap
113
112
  changelog_uri: https://github.com/ruby/net-imap/releases
113
+ post_install_message:
114
114
  rdoc_options: []
115
115
  require_paths:
116
116
  - lib
@@ -125,7 +125,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
125
  - !ruby/object:Gem::Version
126
126
  version: '0'
127
127
  requirements: []
128
- rubygems_version: 3.6.0.dev
128
+ rubygems_version: 3.5.9
129
+ signing_key:
129
130
  specification_version: 4
130
131
  summary: Ruby client api for Internet Message Access Protocol
131
132
  test_files: []
@@ -1,6 +0,0 @@
1
- version: 2
2
- updates:
3
- - package-ecosystem: 'github-actions'
4
- directory: '/'
5
- schedule:
6
- interval: 'weekly'
@@ -1,46 +0,0 @@
1
- name: Deploy RDoc site to Pages
2
-
3
- on:
4
- push:
5
- branches: [ 'master' ]
6
- workflow_dispatch:
7
-
8
- permissions:
9
- contents: read
10
- pages: write
11
- id-token: write
12
-
13
- concurrency:
14
- group: "pages"
15
- cancel-in-progress: true
16
-
17
- jobs:
18
- build:
19
- runs-on: ubuntu-latest
20
- steps:
21
- - name: Checkout
22
- uses: actions/checkout@v4
23
- - name: Setup Ruby
24
- uses: ruby/setup-ruby@250fcd6a742febb1123a77a841497ccaa8b9e939 # v1.152.0
25
- with:
26
- ruby-version: '3.2'
27
- bundler-cache: true
28
- - name: Setup Pages
29
- id: pages
30
- uses: actions/configure-pages@v5
31
- - name: Build with RDoc
32
- run: bundle exec rake rdoc
33
- - name: Upload artifact
34
- uses: actions/upload-pages-artifact@v3
35
- with: { path: 'doc' }
36
-
37
- deploy:
38
- environment:
39
- name: github-pages
40
- url: ${{ steps.deployment.outputs.page_url }}
41
- runs-on: ubuntu-latest
42
- needs: build
43
- steps:
44
- - name: Deploy to GitHub Pages
45
- id: deployment
46
- uses: actions/deploy-pages@v4
@@ -1,48 +0,0 @@
1
- name: Publish gem to rubygems.org
2
-
3
- on:
4
- push:
5
- tags:
6
- - 'v*'
7
-
8
- permissions:
9
- contents: read
10
-
11
- jobs:
12
- push:
13
- if: github.repository == 'ruby/net-imap'
14
- runs-on: ubuntu-latest
15
-
16
- environment:
17
- name: rubygems.org
18
- url: https://rubygems.org/gems/net-imap
19
-
20
- permissions:
21
- contents: write
22
- id-token: write
23
-
24
- steps:
25
- # Set up
26
- - name: Harden Runner
27
- uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
28
- with:
29
- egress-policy: audit
30
-
31
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
32
-
33
- - name: Set up Ruby
34
- uses: ruby/setup-ruby@cacc9f1c0b3f4eb8a16a6bb0ed10897b43b9de49 # v1.176.0
35
- with:
36
- bundler-cache: true
37
- ruby-version: ruby
38
-
39
- # Release
40
- - name: Publish to RubyGems
41
- uses: rubygems/release-gem@612653d273a73bdae1df8453e090060bb4db5f31 # v1
42
-
43
- - name: Create GitHub release
44
- run: |
45
- tag_name="$(git describe --tags --abbrev=0)"
46
- gh release create "${tag_name}" --verify-tag --draft --generate-notes
47
- env:
48
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -1,31 +0,0 @@
1
- name: Run tests
2
-
3
- on: [push, pull_request]
4
-
5
- jobs:
6
- ruby-versions:
7
- uses: ruby/actions/.github/workflows/ruby_versions.yml@master
8
- with:
9
- engine: cruby
10
- min_version: 2.7
11
-
12
- build:
13
- needs: ruby-versions
14
- name: build (${{ matrix.ruby }} / ${{ matrix.os }})
15
- strategy:
16
- matrix:
17
- ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
18
- os: [ ubuntu-latest, macos-latest ]
19
- experimental: [false]
20
- runs-on: ${{ matrix.os }}
21
- continue-on-error: ${{ matrix.experimental }}
22
- steps:
23
- - uses: actions/checkout@v4
24
- - name: Set up Ruby
25
- uses: ruby/setup-ruby@v1
26
- with:
27
- ruby-version: ${{ matrix.ruby }}
28
- bundler-cache: true
29
- rubygems: 3.4.22
30
- - name: Run test
31
- run: bundle exec rake test
data/.gitignore DELETED
@@ -1,12 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /rfcs
8
- /spec/reports/
9
- /tmp/
10
- /Gemfile.lock
11
- /benchmarks/Gemfile*
12
- /benchmarks/parser.yml
data/.mailmap DELETED
@@ -1,13 +0,0 @@
1
- nicholas a. evans <nick@rubinick.dev>
2
- nicholas a. evans <nick@rubinick.dev> <nick@410labs.com>
3
- nicholas a. evans <nick@rubinick.dev> <nick@ekenosen.net>
4
- nicholas a. evans <nick@rubinick.dev> <nicholas.evans@gmail.com>
5
-
6
- Shugo Maeda <shugo@ruby-lang.org>
7
- Shugo Maeda <shugo@ruby-lang.org> <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
8
-
9
- Nobuyoshi Nakada <nobu@ruby-lang.org>
10
- Nobuyoshi Nakada <nobu@ruby-lang.org> <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
11
-
12
- Hiroshi SHIBATA <hsbt@ruby-lang.org>
13
- Hiroshi SHIBATA <hsbt@ruby-lang.org> <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>