net-imap 0.3.7 → 0.3.9
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/lib/net/imap/errors.rb +34 -0
- data/lib/net/imap/response_parser.rb +23 -3
- data/lib/net/imap/response_reader.rb +75 -0
- data/lib/net/imap.rb +118 -36
- metadata +4 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac3c48a5e014382d7b05eda0c632b7924829fba35358881aca99cd88e36efe05
|
4
|
+
data.tar.gz: 73750ad71a15a08cbab8a92ff3630ada6dbbe804af3a3981f4e65298a64e101b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1ba773bd3cc8dcd540e0c7c5ef7d63135191486660e1b5507921ed6954adb280f871a0d874838b4ef5c26d9f6d2f33d78931be7e7fd8ac8a381408a3666d1fe
|
7
|
+
data.tar.gz: 31c372f84bf66cb056a2933f85c2be65695f19b099ac119b5ee943e9d70d24c439d446af5b020cbe8cd4d961efd336d858e190f9b6e1a711571cf101603a0ff8
|
data/lib/net/imap/errors.rb
CHANGED
@@ -11,6 +11,40 @@ module Net
|
|
11
11
|
class DataFormatError < Error
|
12
12
|
end
|
13
13
|
|
14
|
+
# Error raised when the socket cannot be read, due to a configured limit.
|
15
|
+
class ResponseReadError < Error
|
16
|
+
end
|
17
|
+
|
18
|
+
# Error raised when a response is larger than IMAP#max_response_size.
|
19
|
+
class ResponseTooLargeError < ResponseReadError
|
20
|
+
attr_reader :bytes_read, :literal_size
|
21
|
+
attr_reader :max_response_size
|
22
|
+
|
23
|
+
def initialize(msg = nil, *args,
|
24
|
+
bytes_read: nil,
|
25
|
+
literal_size: nil,
|
26
|
+
max_response_size: nil,
|
27
|
+
**kwargs)
|
28
|
+
@bytes_read = bytes_read
|
29
|
+
@literal_size = literal_size
|
30
|
+
@max_response_size = max_response_size
|
31
|
+
msg ||= [
|
32
|
+
"Response size", response_size_msg, "exceeds max_response_size",
|
33
|
+
max_response_size && "(#{max_response_size}B)",
|
34
|
+
].compact.join(" ")
|
35
|
+
return super(msg, *args) if kwargs.empty? # ruby 2.6 compatibility
|
36
|
+
super(msg, *args, **kwargs)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def response_size_msg
|
42
|
+
if bytes_read && literal_size
|
43
|
+
"(#{bytes_read}B read + #{literal_size}B literal)"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
14
48
|
# Error raised when a response from the server is non-parseable.
|
15
49
|
class ResponseParseError < Error
|
16
50
|
end
|
@@ -7,6 +7,8 @@ module Net
|
|
7
7
|
|
8
8
|
# Parses an \IMAP server response.
|
9
9
|
class ResponseParser
|
10
|
+
MAX_UID_SET_SIZE = 10_000
|
11
|
+
|
10
12
|
# :call-seq: Net::IMAP::ResponseParser.new -> Net::IMAP::ResponseParser
|
11
13
|
def initialize
|
12
14
|
@str = nil
|
@@ -1379,11 +1381,29 @@ module Net
|
|
1379
1381
|
case token.symbol
|
1380
1382
|
when T_NUMBER then [Integer(token.value)]
|
1381
1383
|
when T_ATOM
|
1382
|
-
token.value
|
1383
|
-
|
1384
|
-
|
1384
|
+
entries = uid_set__ranges(token.value)
|
1385
|
+
if (count = entries.sum(&:size)) > MAX_UID_SET_SIZE
|
1386
|
+
parse_error("uid-set is too large: %d > 10k", count)
|
1387
|
+
end
|
1388
|
+
entries.flat_map(&:to_a)
|
1389
|
+
end
|
1390
|
+
end
|
1391
|
+
|
1392
|
+
# returns an array of ranges
|
1393
|
+
def uid_set__ranges(uidset)
|
1394
|
+
entries = []
|
1395
|
+
uidset.split(",") do |entry|
|
1396
|
+
uids = entry.split(":", 2).map {|uid|
|
1397
|
+
unless uid =~ /\A[1-9][0-9]*\z/
|
1398
|
+
parse_error("invalid uid-set uid: %p", uid)
|
1399
|
+
end
|
1400
|
+
uid = Integer(uid)
|
1401
|
+
NumValidator.ensure_nz_number(uid)
|
1402
|
+
uid
|
1385
1403
|
}
|
1404
|
+
entries << Range.new(*uids.minmax)
|
1386
1405
|
end
|
1406
|
+
entries
|
1387
1407
|
end
|
1388
1408
|
|
1389
1409
|
def nil_atom
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Net
|
4
|
+
class IMAP
|
5
|
+
# See https://www.rfc-editor.org/rfc/rfc9051#section-2.2.2
|
6
|
+
class ResponseReader # :nodoc:
|
7
|
+
attr_reader :client
|
8
|
+
|
9
|
+
def initialize(client, sock)
|
10
|
+
@client, @sock = client, sock
|
11
|
+
end
|
12
|
+
|
13
|
+
def read_response_buffer
|
14
|
+
@buff = String.new
|
15
|
+
catch :eof do
|
16
|
+
while true
|
17
|
+
read_line
|
18
|
+
break unless (@literal_size = get_literal_size)
|
19
|
+
read_literal
|
20
|
+
end
|
21
|
+
end
|
22
|
+
buff
|
23
|
+
ensure
|
24
|
+
@buff = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :buff, :literal_size
|
30
|
+
|
31
|
+
def bytes_read; buff.bytesize end
|
32
|
+
def empty?; buff.empty? end
|
33
|
+
def done?; line_done? && !get_literal_size end
|
34
|
+
def line_done?; buff.end_with?(CRLF) end
|
35
|
+
def get_literal_size; /\{(\d+)\}\r\n\z/n =~ buff && $1.to_i end
|
36
|
+
|
37
|
+
def read_line
|
38
|
+
buff << (@sock.gets(CRLF, read_limit) or throw :eof)
|
39
|
+
max_response_remaining! unless line_done?
|
40
|
+
end
|
41
|
+
|
42
|
+
def read_literal
|
43
|
+
# check before allocating memory for literal
|
44
|
+
max_response_remaining!
|
45
|
+
literal = String.new(capacity: literal_size)
|
46
|
+
buff << (@sock.read(read_limit(literal_size), literal) or throw :eof)
|
47
|
+
ensure
|
48
|
+
@literal_size = nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def read_limit(limit = nil)
|
52
|
+
[limit, max_response_remaining!].compact.min
|
53
|
+
end
|
54
|
+
|
55
|
+
def max_response_size; client.max_response_size end
|
56
|
+
def max_response_remaining; max_response_size &.- bytes_read end
|
57
|
+
def response_too_large?; max_response_size &.< min_response_size end
|
58
|
+
def min_response_size; bytes_read + min_response_remaining end
|
59
|
+
|
60
|
+
def min_response_remaining
|
61
|
+
empty? ? 3 : done? ? 0 : (literal_size || 0) + 2
|
62
|
+
end
|
63
|
+
|
64
|
+
def max_response_remaining!
|
65
|
+
return max_response_remaining unless response_too_large?
|
66
|
+
raise ResponseTooLargeError.new(
|
67
|
+
max_response_size: max_response_size,
|
68
|
+
bytes_read: bytes_read,
|
69
|
+
literal_size: literal_size,
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/net/imap.rb
CHANGED
@@ -45,10 +45,16 @@ module Net
|
|
45
45
|
# To work on the messages within a mailbox, the client must
|
46
46
|
# first select that mailbox, using either #select or #examine
|
47
47
|
# (for read-only access). Once the client has successfully
|
48
|
-
# selected a mailbox, they enter the
|
48
|
+
# selected a mailbox, they enter the +selected+ state, and that
|
49
49
|
# mailbox becomes the _current_ mailbox, on which mail-item
|
50
50
|
# related commands implicitly operate.
|
51
51
|
#
|
52
|
+
# === Connection state
|
53
|
+
#
|
54
|
+
# Once an IMAP connection is established, the connection is in one of four
|
55
|
+
# states: <tt>not authenticated</tt>, +authenticated+, +selected+, and
|
56
|
+
# +logout+. Most commands are valid only in certain states.
|
57
|
+
#
|
52
58
|
# === Sequence numbers and UIDs
|
53
59
|
#
|
54
60
|
# Messages have two sorts of identifiers: message sequence
|
@@ -126,6 +132,41 @@ module Net
|
|
126
132
|
#
|
127
133
|
# This script invokes the FETCH command and the SEARCH command concurrently.
|
128
134
|
#
|
135
|
+
# When running multiple commands, care must be taken to avoid ambiguity. For
|
136
|
+
# example, SEARCH responses are ambiguous about which command they are
|
137
|
+
# responding to, so search commands should not run simultaneously, unless the
|
138
|
+
# server supports +ESEARCH+ {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731] or
|
139
|
+
# IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051]. See {RFC9051
|
140
|
+
# §5.5}[https://www.rfc-editor.org/rfc/rfc9051.html#section-5.5] for
|
141
|
+
# other examples of command sequences which should not be pipelined.
|
142
|
+
#
|
143
|
+
# == Unbounded memory use
|
144
|
+
#
|
145
|
+
# Net::IMAP reads server responses in a separate receiver thread per client.
|
146
|
+
# Unhandled response data is saved to #responses, and response_handlers run
|
147
|
+
# inside the receiver thread. See the list of methods for {handling server
|
148
|
+
# responses}[rdoc-ref:Net::IMAP@Handling+server+responses], below.
|
149
|
+
#
|
150
|
+
# Because the receiver thread continuously reads and saves new responses, some
|
151
|
+
# scenarios must be careful to avoid unbounded memory use:
|
152
|
+
#
|
153
|
+
# * Commands such as #list or #fetch can have an enormous number of responses.
|
154
|
+
# * Commands such as #fetch can result in an enormous size per response.
|
155
|
+
# * Long-lived connections will gradually accumulate unsolicited server
|
156
|
+
# responses, especially +EXISTS+, +FETCH+, and +EXPUNGE+ responses.
|
157
|
+
# * A buggy or untrusted server could send inappropriate responses, which
|
158
|
+
# could be very numerous, very large, and very rapid.
|
159
|
+
#
|
160
|
+
# Use paginated or limited versions of commands whenever possible.
|
161
|
+
#
|
162
|
+
# Use #max_response_size to impose a limit on incoming server responses
|
163
|
+
# as they are being read. <em>This is especially important for untrusted
|
164
|
+
# servers.</em>
|
165
|
+
#
|
166
|
+
# Use #add_response_handler to handle responses after each one is received.
|
167
|
+
# Use the +response_handlers+ argument to ::new to assign response handlers
|
168
|
+
# before the receiver thread is started.
|
169
|
+
#
|
129
170
|
# == Errors
|
130
171
|
#
|
131
172
|
# An \IMAP server can send three different types of responses to indicate
|
@@ -187,7 +228,7 @@ module Net
|
|
187
228
|
# - Net::IMAP.new: A new client connects immediately and waits for a
|
188
229
|
# successful server greeting before returning the new client object.
|
189
230
|
# - #starttls: Asks the server to upgrade a clear-text connection to use TLS.
|
190
|
-
# - #logout: Tells the server to end the session.
|
231
|
+
# - #logout: Tells the server to end the session. Enters the +logout+ state.
|
191
232
|
# - #disconnect: Disconnects the connection (without sending #logout first).
|
192
233
|
# - #disconnected?: True if the connection has been closed.
|
193
234
|
#
|
@@ -230,40 +271,39 @@ module Net
|
|
230
271
|
# <em>Capabilities may change after</em> #starttls, #authenticate, or #login
|
231
272
|
# <em>and cached capabilities must be reloaded.</em>
|
232
273
|
# - #noop: Allows the server to send unsolicited untagged #responses.
|
233
|
-
# - #logout: Tells the server to end the session. Enters the
|
274
|
+
# - #logout: Tells the server to end the session. Enters the +logout+ state.
|
234
275
|
#
|
235
276
|
# ==== \IMAP commands for the "Not Authenticated" state
|
236
277
|
#
|
237
|
-
# In addition to the
|
238
|
-
# the
|
278
|
+
# In addition to the commands for any state, the following commands are valid
|
279
|
+
# in the +not_authenticated+ state:
|
239
280
|
#
|
240
281
|
# - #starttls: Upgrades a clear-text connection to use TLS.
|
241
282
|
#
|
242
283
|
# <em>Requires the +STARTTLS+ capability.</em>
|
243
|
-
# - #authenticate: Identifies the client to the server using
|
244
|
-
# mechanism}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml]
|
245
|
-
# Enters the
|
284
|
+
# - #authenticate: Identifies the client to the server using the given {SASL
|
285
|
+
# mechanism}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml]
|
286
|
+
# and credentials. Enters the +authenticated+ state.
|
246
287
|
#
|
247
288
|
# <em>Requires the <tt>AUTH=#{mechanism}</tt> capability for the chosen
|
248
289
|
# mechanism.</em>
|
249
290
|
# - #login: Identifies the client to the server using a plain text password.
|
250
|
-
# Using #authenticate is
|
251
|
-
# state.
|
291
|
+
# Using #authenticate is preferred. Enters the +authenticated+ state.
|
252
292
|
#
|
253
293
|
# <em>The +LOGINDISABLED+ capability</em> <b>must NOT</b> <em>be listed.</em>
|
254
294
|
#
|
255
295
|
# ==== \IMAP commands for the "Authenticated" state
|
256
296
|
#
|
257
|
-
# In addition to the
|
258
|
-
# the
|
297
|
+
# In addition to the commands for any state, the following commands are valid
|
298
|
+
# in the +authenticated+ state:
|
259
299
|
#
|
260
300
|
#--
|
261
301
|
# - #enable: <em>Not implemented by Net::IMAP, yet.</em>
|
262
302
|
#
|
263
303
|
# <em>Requires the +ENABLE+ capability.</em>
|
264
304
|
#++
|
265
|
-
# - #select: Open a mailbox and enter the
|
266
|
-
# - #examine: Open a mailbox read-only, and enter the
|
305
|
+
# - #select: Open a mailbox and enter the +selected+ state.
|
306
|
+
# - #examine: Open a mailbox read-only, and enter the +selected+ state.
|
267
307
|
# - #create: Creates a new mailbox.
|
268
308
|
# - #delete: Permanently remove a mailbox.
|
269
309
|
# - #rename: Change the name of a mailbox.
|
@@ -289,12 +329,12 @@ module Net
|
|
289
329
|
#
|
290
330
|
# ==== \IMAP commands for the "Selected" state
|
291
331
|
#
|
292
|
-
# In addition to the
|
293
|
-
# following commands are valid in the
|
332
|
+
# In addition to the commands for any state and the +authenticated+
|
333
|
+
# commands, the following commands are valid in the +selected+ state:
|
294
334
|
#
|
295
|
-
# - #close: Closes the mailbox and returns to the
|
335
|
+
# - #close: Closes the mailbox and returns to the +authenticated+ state,
|
296
336
|
# expunging deleted messages, unless the mailbox was opened as read-only.
|
297
|
-
# - #unselect: Closes the mailbox and returns to the
|
337
|
+
# - #unselect: Closes the mailbox and returns to the +authenticated+ state,
|
298
338
|
# without expunging any messages.
|
299
339
|
#
|
300
340
|
# <em>Requires the +UNSELECT+ capability.</em>
|
@@ -384,7 +424,7 @@ module Net
|
|
384
424
|
# ==== RFC3691: +UNSELECT+
|
385
425
|
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], so it is also
|
386
426
|
# listed with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
|
387
|
-
# - #unselect: Closes the mailbox and returns to the
|
427
|
+
# - #unselect: Closes the mailbox and returns to the +authenticated+ state,
|
388
428
|
# without expunging any messages.
|
389
429
|
#
|
390
430
|
# ==== RFC4314: +ACL+
|
@@ -699,7 +739,9 @@ module Net
|
|
699
739
|
# * {Character sets}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
|
700
740
|
#
|
701
741
|
class IMAP < Protocol
|
702
|
-
VERSION = "0.3.
|
742
|
+
VERSION = "0.3.9"
|
743
|
+
|
744
|
+
autoload :ResponseReader, File.expand_path("imap/response_reader", __dir__)
|
703
745
|
|
704
746
|
include MonitorMixin
|
705
747
|
if defined?(OpenSSL::SSL)
|
@@ -734,6 +776,40 @@ module Net
|
|
734
776
|
# Seconds to wait until an IDLE response is received.
|
735
777
|
attr_reader :idle_response_timeout
|
736
778
|
|
779
|
+
# The maximum allowed server response size. When +nil+, there is no limit
|
780
|
+
# on response size.
|
781
|
+
#
|
782
|
+
# The default value is _unlimited_ (after +v0.5.8+, the default is 512 MiB).
|
783
|
+
# A _much_ lower value should be used with untrusted servers (for example,
|
784
|
+
# when connecting to a user-provided hostname). When using a lower limit,
|
785
|
+
# message bodies should be fetched in chunks rather than all at once.
|
786
|
+
#
|
787
|
+
# <em>Please Note:</em> this only limits the size per response. It does
|
788
|
+
# not prevent a flood of individual responses and it does not limit how
|
789
|
+
# many unhandled responses may be stored on the responses hash. See
|
790
|
+
# Net::IMAP@Unbounded+memory+use.
|
791
|
+
#
|
792
|
+
# Socket reads are limited to the maximum remaining bytes for the current
|
793
|
+
# response: max_response_size minus the bytes that have already been read.
|
794
|
+
# When the limit is reached, or reading a +literal+ _would_ go over the
|
795
|
+
# limit, ResponseTooLargeError is raised and the connection is closed.
|
796
|
+
# See also #socket_read_limit.
|
797
|
+
#
|
798
|
+
# Note that changes will not take effect immediately, because the receiver
|
799
|
+
# thread may already be waiting for the next response using the previous
|
800
|
+
# value. Net::IMAP#noop can force a response and enforce the new setting
|
801
|
+
# immediately.
|
802
|
+
#
|
803
|
+
# ==== Versioned Defaults
|
804
|
+
#
|
805
|
+
# Net::IMAP#max_response_size <em>was added in +v0.2.5+ and +v0.3.9+ as an
|
806
|
+
# attr_accessor, and in +v0.4.20+ and +v0.5.7+ as a delegator to a config
|
807
|
+
# attribute.</em>
|
808
|
+
#
|
809
|
+
# * original: +nil+ <em>(no limit)</em>
|
810
|
+
# * +0.5+: 512 MiB
|
811
|
+
attr_accessor :max_response_size
|
812
|
+
|
737
813
|
attr_accessor :client_thread # :nodoc:
|
738
814
|
|
739
815
|
# Returns the debug mode.
|
@@ -1960,6 +2036,11 @@ module Net
|
|
1960
2036
|
# end
|
1961
2037
|
# }
|
1962
2038
|
#
|
2039
|
+
# Response handlers can also be added when the client is created before the
|
2040
|
+
# receiver thread is started, by the +response_handlers+ argument to ::new.
|
2041
|
+
# This ensures every server response is handled, including the #greeting.
|
2042
|
+
#
|
2043
|
+
# Related: #remove_response_handler, #response_handlers
|
1963
2044
|
def add_response_handler(handler = nil, &block)
|
1964
2045
|
raise ArgumentError, "two Procs are passed" if handler && block
|
1965
2046
|
@response_handlers.push(block || handler)
|
@@ -1995,6 +2076,13 @@ module Net
|
|
1995
2076
|
# OpenSSL::SSL::SSLContext#set_params as parameters.
|
1996
2077
|
# open_timeout:: Seconds to wait until a connection is opened
|
1997
2078
|
# idle_response_timeout:: Seconds to wait until an IDLE response is received
|
2079
|
+
# response_handlers:: A list of response handlers to be added before the
|
2080
|
+
# receiver thread is started. This ensures every server
|
2081
|
+
# response is handled, including the #greeting. Note
|
2082
|
+
# that the greeting is handled in the current thread,
|
2083
|
+
# but all other responses are handled in the receiver
|
2084
|
+
# thread.
|
2085
|
+
# max_response_size:: See #max_response_size.
|
1998
2086
|
#
|
1999
2087
|
# The most common errors are:
|
2000
2088
|
#
|
@@ -2025,8 +2113,10 @@ module Net
|
|
2025
2113
|
@tagno = 0
|
2026
2114
|
@open_timeout = options[:open_timeout] || 30
|
2027
2115
|
@idle_response_timeout = options[:idle_response_timeout] || 5
|
2116
|
+
@max_response_size = options[:max_response_size]
|
2028
2117
|
@parser = ResponseParser.new
|
2029
2118
|
@sock = tcp_socket(@host, @port)
|
2119
|
+
@reader = ResponseReader.new(self, @sock)
|
2030
2120
|
begin
|
2031
2121
|
if options[:ssl]
|
2032
2122
|
start_tls_session(options[:ssl])
|
@@ -2037,6 +2127,7 @@ module Net
|
|
2037
2127
|
@responses = Hash.new([].freeze)
|
2038
2128
|
@tagged_responses = {}
|
2039
2129
|
@response_handlers = []
|
2130
|
+
options[:response_handlers]&.each do |h| add_response_handler(h) end
|
2040
2131
|
@tagged_response_arrival = new_cond
|
2041
2132
|
@continued_command_tag = nil
|
2042
2133
|
@continuation_request_arrival = new_cond
|
@@ -2053,6 +2144,7 @@ module Net
|
|
2053
2144
|
if @greeting.name == "BYE"
|
2054
2145
|
raise ByeResponseError, @greeting
|
2055
2146
|
end
|
2147
|
+
@response_handlers.each do |handler| handler.call(@greeting) end
|
2056
2148
|
|
2057
2149
|
@client_thread = Thread.current
|
2058
2150
|
@receiver_thread = Thread.start {
|
@@ -2176,25 +2268,14 @@ module Net
|
|
2176
2268
|
end
|
2177
2269
|
|
2178
2270
|
def get_response
|
2179
|
-
buff =
|
2180
|
-
while true
|
2181
|
-
s = @sock.gets(CRLF)
|
2182
|
-
break unless s
|
2183
|
-
buff.concat(s)
|
2184
|
-
if /\{(\d+)\}\r\n/n =~ s
|
2185
|
-
s = @sock.read($1.to_i)
|
2186
|
-
buff.concat(s)
|
2187
|
-
else
|
2188
|
-
break
|
2189
|
-
end
|
2190
|
-
end
|
2271
|
+
buff = @reader.read_response_buffer
|
2191
2272
|
return nil if buff.length == 0
|
2192
|
-
if @@debug
|
2193
|
-
|
2194
|
-
end
|
2195
|
-
return @parser.parse(buff)
|
2273
|
+
$stderr.print(buff.gsub(/^/n, "S: ")) if @@debug
|
2274
|
+
@parser.parse(buff)
|
2196
2275
|
end
|
2197
2276
|
|
2277
|
+
#############################
|
2278
|
+
|
2198
2279
|
def record_response(name, data)
|
2199
2280
|
unless @responses.has_key?(name)
|
2200
2281
|
@responses[name] = []
|
@@ -2372,6 +2453,7 @@ module Net
|
|
2372
2453
|
context.verify_callback = VerifyCallbackProc
|
2373
2454
|
end
|
2374
2455
|
@sock = SSLSocket.new(@sock, context)
|
2456
|
+
@reader = ResponseReader.new(self, @sock)
|
2375
2457
|
@sock.sync_close = true
|
2376
2458
|
@sock.hostname = @host if @sock.respond_to? :hostname=
|
2377
2459
|
ssl_socket_connect(@sock, @open_timeout)
|
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: net-imap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shugo Maeda
|
8
8
|
- nicholas a. evans
|
9
|
-
autorequire:
|
10
9
|
bindir: exe
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: net-protocol
|
@@ -98,6 +97,7 @@ files:
|
|
98
97
|
- lib/net/imap/flags.rb
|
99
98
|
- lib/net/imap/response_data.rb
|
100
99
|
- lib/net/imap/response_parser.rb
|
100
|
+
- lib/net/imap/response_reader.rb
|
101
101
|
- lib/net/imap/sasl.rb
|
102
102
|
- lib/net/imap/sasl/saslprep.rb
|
103
103
|
- lib/net/imap/sasl/saslprep_tables.rb
|
@@ -115,7 +115,6 @@ licenses:
|
|
115
115
|
metadata:
|
116
116
|
homepage_uri: https://github.com/ruby/net-imap
|
117
117
|
source_code_uri: https://github.com/ruby/net-imap
|
118
|
-
post_install_message:
|
119
118
|
rdoc_options: []
|
120
119
|
require_paths:
|
121
120
|
- lib
|
@@ -130,8 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
129
|
- !ruby/object:Gem::Version
|
131
130
|
version: '0'
|
132
131
|
requirements: []
|
133
|
-
rubygems_version: 3.
|
134
|
-
signing_key:
|
132
|
+
rubygems_version: 3.6.8
|
135
133
|
specification_version: 4
|
136
134
|
summary: Ruby client api for Internet Message Access Protocol
|
137
135
|
test_files: []
|