net-imap 0.4.12 → 0.4.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.

Potentially problematic release.


This version of net-imap might be problematic. Click here for more details.

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>