net-imap 0.5.3 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/net/imap/command_data.rb +32 -0
- data/lib/net/imap/esearch_result.rb +44 -4
- data/lib/net/imap/response_parser.rb +51 -0
- data/lib/net/imap.rb +109 -47
- data/rakelib/rfcs.rake +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a871e99f51067e3a509aa5a74fe2c49f4d79496bcec2f21ac50c3c5793d2cdbf
|
4
|
+
data.tar.gz: 302c03e65954f9a118d877f97ea2296f34a7f50c8b1299e3e4f8b589cb620880
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85d97c9729220265da03588f175fea22bcdd27d40cd06910ad35bc01ed64bd0c27b2769790464712572166761f3e82fc4eb6330fef64f45cceb0b3e1007f7126
|
7
|
+
data.tar.gz: aa18d53b81e57ddfbdde2b8295ca7324f965fa744846fdd756ec4ca1c30e6e72092b106ff454d100f70d1078ee239f2b3e643bd4650606a2fc3b4ab5a2d0cc1f
|
@@ -153,6 +153,38 @@ module Net
|
|
153
153
|
end
|
154
154
|
end
|
155
155
|
|
156
|
+
class PartialRange < CommandData # :nodoc:
|
157
|
+
uint32_max = 2**32 - 1
|
158
|
+
POS_RANGE = 1..uint32_max
|
159
|
+
NEG_RANGE = -uint32_max..-1
|
160
|
+
Positive = ->{ (_1 in Range) and POS_RANGE.cover?(_1) }
|
161
|
+
Negative = ->{ (_1 in Range) and NEG_RANGE.cover?(_1) }
|
162
|
+
|
163
|
+
def initialize(data:)
|
164
|
+
min, max = case data
|
165
|
+
in Range
|
166
|
+
data.minmax.map { Integer _1 }
|
167
|
+
in ResponseParser::Patterns::PARTIAL_RANGE
|
168
|
+
data.split(":").map { Integer _1 }.minmax
|
169
|
+
else
|
170
|
+
raise ArgumentError, "invalid partial range input: %p" % [data]
|
171
|
+
end
|
172
|
+
data = min..max
|
173
|
+
unless data in Positive | Negative
|
174
|
+
raise ArgumentError, "invalid partial-range: %p" % [data]
|
175
|
+
end
|
176
|
+
super
|
177
|
+
rescue TypeError, RangeError
|
178
|
+
raise ArgumentError, "expected range min/max to be Integers"
|
179
|
+
end
|
180
|
+
|
181
|
+
def formatted = "%d:%d" % data.minmax
|
182
|
+
|
183
|
+
def send_data(imap, tag)
|
184
|
+
imap.__send__(:put_string, formatted)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
156
188
|
# *DEPRECATED*. Replaced by SequenceSet.
|
157
189
|
class MessageSet < CommandData # :nodoc:
|
158
190
|
def send_data(imap, tag)
|
@@ -35,16 +35,16 @@ module Net
|
|
35
35
|
|
36
36
|
# :call-seq: to_a -> Array of integers
|
37
37
|
#
|
38
|
-
# When #all contains a SequenceSet of message sequence
|
38
|
+
# When either #all or #partial contains a SequenceSet of message sequence
|
39
39
|
# numbers or UIDs, +to_a+ returns that set as an array of integers.
|
40
40
|
#
|
41
|
-
# When #all
|
42
|
-
# returned no results or because +ALL+
|
41
|
+
# When both #all and #partial are +nil+, either because the server
|
42
|
+
# returned no results or because +ALL+ and +PARTIAL+ were not included in
|
43
43
|
# the IMAP#search +RETURN+ options, #to_a returns an empty array.
|
44
44
|
#
|
45
45
|
# Note that SearchResult also implements +to_a+, so it can be used without
|
46
46
|
# checking if the server returned +SEARCH+ or +ESEARCH+ data.
|
47
|
-
def to_a; all&.numbers || [] end
|
47
|
+
def to_a; all&.numbers || partial&.to_a || [] end
|
48
48
|
|
49
49
|
##
|
50
50
|
# attr_reader: tag
|
@@ -135,6 +135,46 @@ module Net
|
|
135
135
|
# and +ESEARCH+ {[RFC4731]}[https://www.rfc-editor.org/rfc/rfc4731.html#section-3.2].
|
136
136
|
def modseq; data.assoc("MODSEQ")&.last end
|
137
137
|
|
138
|
+
# Returned by ESearchResult#partial.
|
139
|
+
#
|
140
|
+
# Requires +PARTIAL+ {[RFC9394]}[https://www.rfc-editor.org/rfc/rfc9394.html]
|
141
|
+
# or <tt>CONTEXT=SEARCH</tt>/<tt>CONTEXT=SORT</tt>
|
142
|
+
# {[RFC5267]}[https://www.rfc-editor.org/rfc/rfc5267.html]
|
143
|
+
#
|
144
|
+
# See also: #to_a
|
145
|
+
class PartialResult < Data.define(:range, :results)
|
146
|
+
def initialize(range:, results:)
|
147
|
+
range => Range
|
148
|
+
results = SequenceSet[results] unless results.nil?
|
149
|
+
super
|
150
|
+
end
|
151
|
+
|
152
|
+
##
|
153
|
+
# method: range
|
154
|
+
# :call-seq: range -> range
|
155
|
+
|
156
|
+
##
|
157
|
+
# method: results
|
158
|
+
# :call-seq: results -> sequence set or nil
|
159
|
+
|
160
|
+
# Converts #results to an array of integers.
|
161
|
+
#
|
162
|
+
# See also: ESearchResult#to_a.
|
163
|
+
def to_a; results&.numbers || [] end
|
164
|
+
end
|
165
|
+
|
166
|
+
# :call-seq: partial -> PartialResult or nil
|
167
|
+
#
|
168
|
+
# A PartialResult containing a subset of the message sequence numbers or
|
169
|
+
# UIDs that satisfy the SEARCH criteria.
|
170
|
+
#
|
171
|
+
# Requires +PARTIAL+ {[RFC9394]}[https://www.rfc-editor.org/rfc/rfc9394.html]
|
172
|
+
# or <tt>CONTEXT=SEARCH</tt>/<tt>CONTEXT=SORT</tt>
|
173
|
+
# {[RFC5267]}[https://www.rfc-editor.org/rfc/rfc5267.html]
|
174
|
+
#
|
175
|
+
# See also: #to_a
|
176
|
+
def partial; data.assoc("PARTIAL")&.last end
|
177
|
+
|
138
178
|
end
|
139
179
|
end
|
140
180
|
end
|
@@ -321,6 +321,24 @@ module Net
|
|
321
321
|
SEQUENCE_SET = /#{SEQUENCE_SET_ITEM}(?:,#{SEQUENCE_SET_ITEM})*/n
|
322
322
|
SEQUENCE_SET_STR = /\A#{SEQUENCE_SET}\z/n
|
323
323
|
|
324
|
+
# partial-range-first = nz-number ":" nz-number
|
325
|
+
# ;; Request to search from oldest (lowest UIDs) to
|
326
|
+
# ;; more recent messages.
|
327
|
+
# ;; A range 500:400 is the same as 400:500.
|
328
|
+
# ;; This is similar to <seq-range> from [RFC3501]
|
329
|
+
# ;; but cannot contain "*".
|
330
|
+
PARTIAL_RANGE_FIRST = /\A(#{NZ_NUMBER}):(#{NZ_NUMBER})\z/n
|
331
|
+
|
332
|
+
# partial-range-last = MINUS nz-number ":" MINUS nz-number
|
333
|
+
# ;; Request to search from newest (highest UIDs) to
|
334
|
+
# ;; oldest messages.
|
335
|
+
# ;; A range -500:-400 is the same as -400:-500.
|
336
|
+
PARTIAL_RANGE_LAST = /\A(-#{NZ_NUMBER}):(-#{NZ_NUMBER})\z/n
|
337
|
+
|
338
|
+
# partial-range = partial-range-first / partial-range-last
|
339
|
+
PARTIAL_RANGE = Regexp.union(PARTIAL_RANGE_FIRST,
|
340
|
+
PARTIAL_RANGE_LAST)
|
341
|
+
|
324
342
|
# RFC3501:
|
325
343
|
# literal = "{" number "}" CRLF *CHAR8
|
326
344
|
# ; Number represents the number of CHAR8s
|
@@ -1517,6 +1535,9 @@ module Net
|
|
1517
1535
|
# From RFC4731 (ESEARCH):
|
1518
1536
|
# search-return-data =/ "MODSEQ" SP mod-sequence-value
|
1519
1537
|
#
|
1538
|
+
# From RFC9394 (PARTIAL):
|
1539
|
+
# search-return-data =/ ret-data-partial
|
1540
|
+
#
|
1520
1541
|
def search_return_data
|
1521
1542
|
label = search_modifier_name; SP!
|
1522
1543
|
value =
|
@@ -1526,11 +1547,41 @@ module Net
|
|
1526
1547
|
when "ALL" then sequence_set
|
1527
1548
|
when "COUNT" then number
|
1528
1549
|
when "MODSEQ" then mod_sequence_value # RFC7162: CONDSTORE
|
1550
|
+
when "PARTIAL" then ret_data_partial__value # RFC9394: PARTIAL
|
1529
1551
|
else search_return_value
|
1530
1552
|
end
|
1531
1553
|
[label, value]
|
1532
1554
|
end
|
1533
1555
|
|
1556
|
+
# From RFC5267 (CONTEXT=SEARCH, CONTEXT=SORT) and RFC9394 (PARTIAL):
|
1557
|
+
# ret-data-partial = "PARTIAL"
|
1558
|
+
# SP "(" partial-range SP partial-results ")"
|
1559
|
+
def ret_data_partial__value
|
1560
|
+
lpar
|
1561
|
+
range = partial_range; SP!
|
1562
|
+
results = partial_results
|
1563
|
+
rpar
|
1564
|
+
ESearchResult::PartialResult.new(range, results)
|
1565
|
+
end
|
1566
|
+
|
1567
|
+
# partial-range = partial-range-first / partial-range-last
|
1568
|
+
# tagged-ext-simple =/ partial-range-last
|
1569
|
+
def partial_range
|
1570
|
+
case (str = atom)
|
1571
|
+
when Patterns::PARTIAL_RANGE_FIRST, Patterns::PARTIAL_RANGE_LAST
|
1572
|
+
min, max = [Integer($1), Integer($2)].minmax
|
1573
|
+
min..max
|
1574
|
+
else
|
1575
|
+
parse_error("unexpected atom %p, expected partial-range", str)
|
1576
|
+
end
|
1577
|
+
end
|
1578
|
+
|
1579
|
+
# partial-results = sequence-set / "NIL"
|
1580
|
+
# ;; <sequence-set> from [RFC3501].
|
1581
|
+
# ;; NIL indicates that no results correspond to
|
1582
|
+
# ;; the requested range.
|
1583
|
+
def partial_results; NIL? ? nil : sequence_set end
|
1584
|
+
|
1534
1585
|
# search-modifier-name = tagged-ext-label
|
1535
1586
|
alias search_modifier_name tagged_ext_label
|
1536
1587
|
|
data/lib/net/imap.rb
CHANGED
@@ -534,6 +534,11 @@ module Net
|
|
534
534
|
# See FetchData#emailid and FetchData#emailid.
|
535
535
|
# - Updates #status with support for the +MAILBOXID+ status attribute.
|
536
536
|
#
|
537
|
+
# ==== RFC9394: +PARTIAL+
|
538
|
+
# - Updates #search, #uid_search with the +PARTIAL+ return option which adds
|
539
|
+
# ESearchResult#partial return data.
|
540
|
+
# - Updates #uid_fetch with the +partial+ modifier.
|
541
|
+
#
|
537
542
|
# == References
|
538
543
|
#
|
539
544
|
# [{IMAP4rev1}[https://www.rfc-editor.org/rfc/rfc3501.html]]::
|
@@ -701,6 +706,11 @@ module Net
|
|
701
706
|
# Gondwana, B., Ed., "IMAP Extension for Object Identifiers",
|
702
707
|
# RFC 8474, DOI 10.17487/RFC8474, September 2018,
|
703
708
|
# <https://www.rfc-editor.org/info/rfc8474>.
|
709
|
+
# [PARTIAL[https://www.rfc-editor.org/info/rfc9394]]::
|
710
|
+
# Melnikov, A., Achuthan, A., Nagulakonda, V., and L. Alves,
|
711
|
+
# "IMAP PARTIAL Extension for Paged SEARCH and FETCH", RFC 9394,
|
712
|
+
# DOI 10.17487/RFC9394, June 2023,
|
713
|
+
# <https://www.rfc-editor.org/info/rfc9394>.
|
704
714
|
#
|
705
715
|
# === IANA registries
|
706
716
|
# * {IMAP Capabilities}[http://www.iana.org/assignments/imap4-capabilities]
|
@@ -723,7 +733,7 @@ module Net
|
|
723
733
|
# * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
|
724
734
|
#
|
725
735
|
class IMAP < Protocol
|
726
|
-
VERSION = "0.5.
|
736
|
+
VERSION = "0.5.4"
|
727
737
|
|
728
738
|
# Aliases for supported capabilities, to be used with the #enable command.
|
729
739
|
ENABLE_ALIASES = {
|
@@ -1971,8 +1981,9 @@ module Net
|
|
1971
1981
|
# the server to return an ESearchResult instead of a SearchResult, but some
|
1972
1982
|
# servers disobey this requirement. <em>Requires an extended search
|
1973
1983
|
# capability, such as +ESEARCH+ or +IMAP4rev2+.</em>
|
1974
|
-
# See {"Argument translation"}[rdoc-ref:#search@Argument+translation]
|
1975
|
-
#
|
1984
|
+
# See {"Argument translation"}[rdoc-ref:#search@Argument+translation] and
|
1985
|
+
# {"Supported return options"}[rdoc-ref:#search@Supported+return+options],
|
1986
|
+
# below.
|
1976
1987
|
#
|
1977
1988
|
# +charset+ is the name of the {registered character
|
1978
1989
|
# set}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
|
@@ -2082,33 +2093,58 @@ module Net
|
|
2082
2093
|
# <em>*WARNING:* This is vulnerable to injection attacks when external
|
2083
2094
|
# inputs are used.</em>
|
2084
2095
|
#
|
2085
|
-
# ====
|
2096
|
+
# ==== Supported return options
|
2086
2097
|
#
|
2087
2098
|
# For full definitions of the standard return options and return data, see
|
2088
2099
|
# the relevant RFCs.
|
2089
2100
|
#
|
2090
|
-
# ===== +ESEARCH+ or +IMAP4rev2+
|
2091
|
-
#
|
2092
|
-
# The following return options require either +ESEARCH+ or +IMAP4rev2+.
|
2093
|
-
# See [{RFC4731 §3.1}[https://rfc-editor.org/rfc/rfc4731#section-3.1]] or
|
2094
|
-
# [{IMAP4rev2 §6.4.4}[https://www.rfc-editor.org/rfc/rfc9051.html#section-6.4.4]].
|
2095
|
-
#
|
2096
2101
|
# [+ALL+]
|
2097
2102
|
# Returns ESearchResult#all with a SequenceSet of all matching sequence
|
2098
2103
|
# numbers or UIDs. This is the default, when return options are empty.
|
2099
2104
|
#
|
2100
2105
|
# For compatibility with SearchResult, ESearchResult#to_a returns an
|
2101
2106
|
# Array of message sequence numbers or UIDs.
|
2107
|
+
#
|
2108
|
+
# <em>Requires either the +ESEARCH+ or +IMAP4rev2+ capabability.</em>
|
2109
|
+
# {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731]
|
2110
|
+
# {[RFC9051]}[https://rfc-editor.org/rfc/rfc9051]
|
2111
|
+
#
|
2102
2112
|
# [+COUNT+]
|
2103
2113
|
# Returns ESearchResult#count with the number of matching messages.
|
2114
|
+
#
|
2115
|
+
# <em>Requires either the +ESEARCH+ or +IMAP4rev2+ capabability.</em>
|
2116
|
+
# {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731]
|
2117
|
+
# {[RFC9051]}[https://rfc-editor.org/rfc/rfc9051]
|
2118
|
+
#
|
2104
2119
|
# [+MAX+]
|
2105
2120
|
# Returns ESearchResult#max with the highest matching sequence number or
|
2106
2121
|
# UID.
|
2122
|
+
#
|
2123
|
+
# <em>Requires either the +ESEARCH+ or +IMAP4rev2+ capabability.</em>
|
2124
|
+
# {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731]
|
2125
|
+
# {[RFC9051]}[https://rfc-editor.org/rfc/rfc9051]
|
2126
|
+
#
|
2107
2127
|
# [+MIN+]
|
2108
2128
|
# Returns ESearchResult#min with the lowest matching sequence number or
|
2109
2129
|
# UID.
|
2110
2130
|
#
|
2111
|
-
#
|
2131
|
+
# <em>Requires either the +ESEARCH+ or +IMAP4rev2+ capabability.</em>
|
2132
|
+
# {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731]
|
2133
|
+
# {[RFC9051]}[https://rfc-editor.org/rfc/rfc9051]
|
2134
|
+
#
|
2135
|
+
# [+PARTIAL+ _range_]
|
2136
|
+
# Returns ESearchResult#partial with a SequenceSet of a subset of
|
2137
|
+
# matching sequence numbers or UIDs, as selected by _range_. As with
|
2138
|
+
# sequence numbers, the first result is +1+: <tt>1..500</tt> selects the
|
2139
|
+
# first 500 search results (in mailbox order), <tt>501..1000</tt> the
|
2140
|
+
# second 500, and so on. _range_ may also be negative: <tt>-500..-1</tt>
|
2141
|
+
# selects the last 500 search results.
|
2142
|
+
#
|
2143
|
+
# <em>Requires either the <tt>CONTEXT=SEARCH</tt> or +PARTIAL+ capabability.</em>
|
2144
|
+
# {[RFC5267]}[https://rfc-editor.org/rfc/rfc5267]
|
2145
|
+
# {[RFC9394]}[https://rfc-editor.org/rfc/rfc9394]
|
2146
|
+
#
|
2147
|
+
# ===== +MODSEQ+ return data
|
2112
2148
|
#
|
2113
2149
|
# ESearchResult#modseq return data does not have a corresponding return
|
2114
2150
|
# option. Instead, it is returned if the +MODSEQ+ search key is used or
|
@@ -2120,8 +2156,8 @@ module Net
|
|
2120
2156
|
#
|
2121
2157
|
# {RFC4466 §2.6}[https://www.rfc-editor.org/rfc/rfc4466.html#section-2.6]
|
2122
2158
|
# defines standard syntax for search extensions. Net::IMAP allows sending
|
2123
|
-
#
|
2124
|
-
# return values into ExtensionData. Please note that this is an
|
2159
|
+
# unsupported search return options and will parse unsupported search
|
2160
|
+
# extensions' return values into ExtensionData. Please note that this is an
|
2125
2161
|
# intentionally _unstable_ API. Future releases may return different
|
2126
2162
|
# (incompatible) objects, <em>without deprecation or warning</em>.
|
2127
2163
|
#
|
@@ -2357,14 +2393,9 @@ module Net
|
|
2357
2393
|
# Sends a {FETCH command [IMAP4rev1 §6.4.5]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.5]
|
2358
2394
|
# to retrieve data associated with a message in the mailbox.
|
2359
2395
|
#
|
2360
|
-
#
|
2361
|
-
#
|
2362
|
-
#
|
2363
|
-
# being interpreted as '100:*'. Beware that the +exclude_end?+
|
2364
|
-
# property of a Range object is ignored, and the contents of a
|
2365
|
-
# range are independent of the order of the range endpoints as per
|
2366
|
-
# the protocol specification, so 1...5, 5..1 and 5...1 are all
|
2367
|
-
# equivalent to 1..5.
|
2396
|
+
# +set+ is the message sequence numbers to fetch, and may be any valid input
|
2397
|
+
# to {SequenceSet[...]}[rdoc-ref:SequenceSet@Creating+sequence+sets].
|
2398
|
+
# (For UIDs, use #uid_fetch instead.)
|
2368
2399
|
#
|
2369
2400
|
# +attr+ is a list of attributes to fetch; see the documentation
|
2370
2401
|
# for FetchData for a list of valid attributes.
|
@@ -2374,7 +2405,7 @@ module Net
|
|
2374
2405
|
#
|
2375
2406
|
# The return value is an array of FetchData.
|
2376
2407
|
#
|
2377
|
-
# Related: #
|
2408
|
+
# Related: #uid_fetch, FetchData
|
2378
2409
|
#
|
2379
2410
|
# ==== For example:
|
2380
2411
|
#
|
@@ -2403,30 +2434,66 @@ module Net
|
|
2403
2434
|
# {[RFC7162]}[https://tools.ietf.org/html/rfc7162] in order to use the
|
2404
2435
|
# +changedsince+ argument. Using +changedsince+ implicitly enables the
|
2405
2436
|
# +CONDSTORE+ extension.
|
2406
|
-
def fetch(
|
2407
|
-
fetch_internal("FETCH",
|
2437
|
+
def fetch(...)
|
2438
|
+
fetch_internal("FETCH", ...)
|
2408
2439
|
end
|
2409
2440
|
|
2410
2441
|
# :call-seq:
|
2411
|
-
# uid_fetch(set, attr, changedsince: nil) -> array of FetchData
|
2442
|
+
# uid_fetch(set, attr, changedsince: nil, partial: nil) -> array of FetchData
|
2412
2443
|
#
|
2413
2444
|
# Sends a {UID FETCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
|
2414
2445
|
# to retrieve data associated with a message in the mailbox.
|
2415
2446
|
#
|
2416
|
-
#
|
2417
|
-
#
|
2447
|
+
# +set+ is the message UIDs to fetch, and may be any valid input to
|
2448
|
+
# {SequenceSet[...]}[rdoc-ref:SequenceSet@Creating+sequence+sets].
|
2449
|
+
# (For message sequence numbers, use #fetch instead.)
|
2418
2450
|
#
|
2451
|
+
# +attr+ behaves the same as with #fetch.
|
2419
2452
|
# >>>
|
2420
2453
|
# *Note:* Servers _MUST_ implicitly include the +UID+ message data item as
|
2421
2454
|
# part of any +FETCH+ response caused by a +UID+ command, regardless of
|
2422
2455
|
# whether a +UID+ was specified as a message data item to the +FETCH+.
|
2423
2456
|
#
|
2457
|
+
# +changedsince+ (optional) behaves the same as with #fetch.
|
2458
|
+
#
|
2459
|
+
# +partial+ is an optional range to limit the number of results returned.
|
2460
|
+
# It's useful when +set+ contains an unknown number of messages.
|
2461
|
+
# <tt>1..500</tt> returns the first 500 messages in +set+ (in mailbox
|
2462
|
+
# order), <tt>501..1000</tt> the second 500, and so on. +partial+ may also
|
2463
|
+
# be negative: <tt>-500..-1</tt> selects the last 500 messages in +set+.
|
2464
|
+
# <em>Requires the +PARTIAL+ capabability.</em>
|
2465
|
+
# {[RFC9394]}[https://rfc-editor.org/rfc/rfc9394]
|
2466
|
+
#
|
2467
|
+
# For example:
|
2468
|
+
#
|
2469
|
+
# # Without partial, the size of the results may be unknown beforehand:
|
2470
|
+
# results = imap.uid_fetch(next_uid_to_fetch.., %w(UID FLAGS))
|
2471
|
+
# # ... maybe wait for a long time ... and allocate a lot of memory ...
|
2472
|
+
# results.size # => 0..2**32-1
|
2473
|
+
# process results # may also take a long time and use a lot of memory...
|
2474
|
+
#
|
2475
|
+
# # Using partial, the results may be paginated:
|
2476
|
+
# loop do
|
2477
|
+
# results = imap.uid_fetch(next_uid_to_fetch.., %w(UID FLAGS),
|
2478
|
+
# partial: 1..500)
|
2479
|
+
# # fetch should return quickly and allocate little memory
|
2480
|
+
# results.size # => 0..500
|
2481
|
+
# break if results.empty?
|
2482
|
+
# next_uid_to_fetch = results.last.uid + 1
|
2483
|
+
# process results
|
2484
|
+
# end
|
2485
|
+
#
|
2424
2486
|
# Related: #fetch, FetchData
|
2425
2487
|
#
|
2426
2488
|
# ==== Capabilities
|
2427
|
-
#
|
2428
|
-
|
2429
|
-
|
2489
|
+
#
|
2490
|
+
# The server's capabilities must include +PARTIAL+
|
2491
|
+
# {[RFC9394]}[https://rfc-editor.org/rfc/rfc9394] in order to use the
|
2492
|
+
# +partial+ argument.
|
2493
|
+
#
|
2494
|
+
# Otherwise, the same as #fetch.
|
2495
|
+
def uid_fetch(...)
|
2496
|
+
fetch_internal("UID FETCH", ...)
|
2430
2497
|
end
|
2431
2498
|
|
2432
2499
|
# :call-seq:
|
@@ -3338,24 +3405,14 @@ module Net
|
|
3338
3405
|
]
|
3339
3406
|
return_opts.map {|opt|
|
3340
3407
|
case opt
|
3341
|
-
when Symbol
|
3342
|
-
when
|
3343
|
-
|
3408
|
+
when Symbol then opt.to_s
|
3409
|
+
when PartialRange::Negative then PartialRange[opt]
|
3410
|
+
when Range then SequenceSet[opt]
|
3411
|
+
else opt
|
3344
3412
|
end
|
3345
3413
|
}
|
3346
3414
|
end
|
3347
3415
|
|
3348
|
-
def partial_range_last_or_seqset(range)
|
3349
|
-
case [range.begin, range.end]
|
3350
|
-
in [Integer => first, Integer => last] if first.negative? && last.negative?
|
3351
|
-
# partial-range-last [RFC9394]
|
3352
|
-
first <= last or raise DataFormatError, "empty range: %p" % [range]
|
3353
|
-
"#{first}:#{last}"
|
3354
|
-
else
|
3355
|
-
SequenceSet[range]
|
3356
|
-
end
|
3357
|
-
end
|
3358
|
-
|
3359
3416
|
def search_internal(cmd, ...)
|
3360
3417
|
args, esearch = search_args(...)
|
3361
3418
|
synchronize do
|
@@ -3382,7 +3439,12 @@ module Net
|
|
3382
3439
|
end
|
3383
3440
|
end
|
3384
3441
|
|
3385
|
-
def fetch_internal(cmd, set, attr, mod = nil, changedsince: nil)
|
3442
|
+
def fetch_internal(cmd, set, attr, mod = nil, partial: nil, changedsince: nil)
|
3443
|
+
set = SequenceSet[set]
|
3444
|
+
if partial
|
3445
|
+
mod ||= []
|
3446
|
+
mod << "PARTIAL" << PartialRange[partial]
|
3447
|
+
end
|
3386
3448
|
if changedsince
|
3387
3449
|
mod ||= []
|
3388
3450
|
mod << "CHANGEDSINCE" << Integer(changedsince)
|
@@ -3399,9 +3461,9 @@ module Net
|
|
3399
3461
|
synchronize do
|
3400
3462
|
clear_responses("FETCH")
|
3401
3463
|
if mod
|
3402
|
-
send_command(cmd,
|
3464
|
+
send_command(cmd, set, attr, mod)
|
3403
3465
|
else
|
3404
|
-
send_command(cmd,
|
3466
|
+
send_command(cmd, set, attr)
|
3405
3467
|
end
|
3406
3468
|
clear_responses("FETCH")
|
3407
3469
|
end
|
data/rakelib/rfcs.rake
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: net-imap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shugo Maeda
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-12-
|
12
|
+
date: 2024-12-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: net-protocol
|