net-imap 0.4.6 → 0.4.8
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 +4 -4
- data/.github/workflows/pages.yml +2 -2
- data/lib/net/imap/response_data.rb +65 -6
- data/lib/net/imap/response_parser.rb +53 -39
- data/lib/net/imap/search_result.rb +150 -0
- data/lib/net/imap/sequence_set.rb +1318 -36
- data/lib/net/imap.rb +165 -35
- data/net-imap.gemspec +1 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b90ea893e6f831943d2d0412ff068c7a6603ce3bf723900ea7401a9e045f724b
|
4
|
+
data.tar.gz: '087c861278ce56a7369780aa27d77e56ed6d94907a4116a3a4fd9707f327d57a'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5fa157a8887d5ca2b97b75756b5414d5973667299ae3dbdb340b432eae05cfdb2994969ea2dab68b595f2eae66bd50d19fb814196fb991af1bfc285dfa5b3d6f
|
7
|
+
data.tar.gz: 7b173943ff66f97b5b22795752a34f7338228e6ef5a4dca43b293f5e3153f90d34b7039fd24c76399b1f460e77ffe422dd3691466b0952e3631f2406bab70854
|
data/.github/workflows/pages.yml
CHANGED
@@ -27,7 +27,7 @@ jobs:
|
|
27
27
|
bundler-cache: true
|
28
28
|
- name: Setup Pages
|
29
29
|
id: pages
|
30
|
-
uses: actions/configure-pages@
|
30
|
+
uses: actions/configure-pages@v4
|
31
31
|
- name: Build with RDoc
|
32
32
|
run: bundle exec rake rdoc
|
33
33
|
- name: Upload artifact
|
@@ -43,4 +43,4 @@ jobs:
|
|
43
43
|
steps:
|
44
44
|
- name: Deploy to GitHub Pages
|
45
45
|
id: deployment
|
46
|
-
uses: actions/deploy-pages@
|
46
|
+
uses: actions/deploy-pages@v3
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module Net
|
4
4
|
class IMAP < Protocol
|
5
5
|
autoload :FetchData, "#{__dir__}/fetch_data"
|
6
|
+
autoload :SearchResult, "#{__dir__}/search_result"
|
6
7
|
autoload :SequenceSet, "#{__dir__}/sequence_set"
|
7
8
|
|
8
9
|
# Net::IMAP::ContinuationRequest represents command continuation requests.
|
@@ -205,6 +206,7 @@ module Net
|
|
205
206
|
# defines them. When unknown response code data is encountered, #data
|
206
207
|
# will return an unparsed string.
|
207
208
|
#
|
209
|
+
# ==== +IMAP4rev1+ Response Codes
|
208
210
|
# See [IMAP4rev1[https://www.rfc-editor.org/rfc/rfc3501]] {§7.1, "Server
|
209
211
|
# Responses - Status
|
210
212
|
# Responses"}[https://www.rfc-editor.org/rfc/rfc3501#section-7.1] for full
|
@@ -228,13 +230,32 @@ module Net
|
|
228
230
|
# {§2.3.1.1, "Unique Identifier (UID) Message
|
229
231
|
# Attribute}[https://www.rfc-editor.org/rfc/rfc3501#section-2.3.1.1].
|
230
232
|
# * +UIDVALIDITY+, #data is an Integer, the UID validity value of the
|
231
|
-
# mailbox See [{IMAP4rev1}[https://www.rfc-editor.org/rfc/rfc3501]],
|
233
|
+
# mailbox. See [{IMAP4rev1}[https://www.rfc-editor.org/rfc/rfc3501]],
|
232
234
|
# {§2.3.1.1, "Unique Identifier (UID) Message
|
233
235
|
# Attribute}[https://www.rfc-editor.org/rfc/rfc3501#section-2.3.1.1].
|
234
236
|
# * +UNSEEN+, #data is an Integer, the number of messages which do not have
|
235
237
|
# the <tt>\Seen</tt> flag set.
|
236
|
-
#
|
237
|
-
#
|
238
|
+
# <em>DEPRECATED by IMAP4rev2.</em>
|
239
|
+
#
|
240
|
+
# ==== +BINARY+ extension
|
241
|
+
# See {[RFC3516]}[https://www.rfc-editor.org/rfc/rfc3516].
|
242
|
+
# * +UNKNOWN-CTE+, with a tagged +NO+ response, when the server does not
|
243
|
+
# known how to decode a CTE (content-transfer-encoding). #data is +nil+.
|
244
|
+
# See IMAP#fetch.
|
245
|
+
#
|
246
|
+
# ==== +UIDPLUS+ extension
|
247
|
+
# See {[RFC4315 §3]}[https://www.rfc-editor.org/rfc/rfc4315#section-3].
|
248
|
+
# * +APPENDUID+, #data is UIDPlusData. See IMAP#append.
|
249
|
+
# * +COPYUID+, #data is UIDPlusData. See IMAP#copy.
|
250
|
+
# * +UIDNOTSTICKY+, #data is +nil+. See IMAP#select.
|
251
|
+
#
|
252
|
+
# ==== +SEARCHRES+ extension
|
253
|
+
# See {[RFC5182]}[https://www.rfc-editor.org/rfc/rfc5182].
|
254
|
+
# * +NOTSAVED+, with a tagged +NO+ response, when the search result variable
|
255
|
+
# is not saved. #data is +nil+.
|
256
|
+
#
|
257
|
+
# ==== +RFC5530+ Response Codes
|
258
|
+
# See {[RFC5530]}[https://www.rfc-editor.org/rfc/rfc5530], "IMAP Response
|
238
259
|
# Codes" for the definition of the following response codes, which are all
|
239
260
|
# machine-readable annotations for the human-readable ResponseText#text, and
|
240
261
|
# have +nil+ #data of their own:
|
@@ -256,9 +277,34 @@ module Net
|
|
256
277
|
# * +ALREADYEXISTS+
|
257
278
|
# * +NONEXISTENT+
|
258
279
|
#
|
259
|
-
#
|
260
|
-
#
|
261
|
-
#
|
280
|
+
# ==== +QRESYNC+ extension
|
281
|
+
# See {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html].
|
282
|
+
# * +CLOSED+, returned when the currently selected mailbox is closed
|
283
|
+
# implicity by selecting or examining another mailbox. #data is +nil+.
|
284
|
+
#
|
285
|
+
# ==== +IMAP4rev2+ Response Codes
|
286
|
+
# See {[RFC9051]}[https://www.rfc-editor.org/rfc/rfc9051] {§7.1, "Server
|
287
|
+
# Responses - Status
|
288
|
+
# Responses"}[https://www.rfc-editor.org/rfc/rfc9051#section-7.1] for full
|
289
|
+
# descriptions of IMAP4rev2 response codes. IMAP4rev2 includes all of the
|
290
|
+
# response codes listed above (except "UNSEEN") and adds the following:
|
291
|
+
# * +HASCHILDREN+, with a tagged +NO+ response, when a mailbox delete failed
|
292
|
+
# because the server doesn't allow deletion of mailboxes with children.
|
293
|
+
# #data is +nil+.
|
294
|
+
#
|
295
|
+
# ==== +CONDSTORE+ extension
|
296
|
+
# See {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html].
|
297
|
+
# * +NOMODSEQ+, when selecting a mailbox that does not support
|
298
|
+
# mod-sequences. #data is +nil+. See IMAP#select.
|
299
|
+
# * +HIGHESTMODSEQ+, #data is an Integer, the highest mod-sequence value of
|
300
|
+
# all messages in the mailbox. See IMAP#select.
|
301
|
+
# * +MODIFIED+, #data is a SequenceSet, the messages that have been modified
|
302
|
+
# since the +UNCHANGEDSINCE+ mod-sequence given to +STORE+ or <tt>UID
|
303
|
+
# STORE</tt>.
|
304
|
+
#
|
305
|
+
# ==== +OBJECTID+ extension
|
306
|
+
# See {[RFC8474]}[https://www.rfc-editor.org/rfc/rfc8474.html].
|
307
|
+
# * +MAILBOXID+, #data is a string
|
262
308
|
#
|
263
309
|
class ResponseCode < Struct.new(:name, :data)
|
264
310
|
##
|
@@ -728,6 +774,19 @@ module Net
|
|
728
774
|
#
|
729
775
|
# An array of Net::IMAP::ThreadMember objects for mail items that are
|
730
776
|
# children of this in the thread.
|
777
|
+
|
778
|
+
# Returns a SequenceSet containing #seqno and all #children's seqno,
|
779
|
+
# recursively.
|
780
|
+
def to_sequence_set
|
781
|
+
SequenceSet.new all_seqnos
|
782
|
+
end
|
783
|
+
|
784
|
+
protected
|
785
|
+
|
786
|
+
def all_seqnos(node = self)
|
787
|
+
[node.seqno].concat node.children.flat_map { _1.all_seqnos }
|
788
|
+
end
|
789
|
+
|
731
790
|
end
|
732
791
|
|
733
792
|
# Net::IMAP::BodyStructure is included by all of the structs that can be
|
@@ -231,6 +231,10 @@ module Net
|
|
231
231
|
FLAG_PERM_LIST = /\G\((#{FLAG_PERM}(?:#{SP}#{FLAG_PERM})*|)\)/ni
|
232
232
|
MBX_LIST_FLAGS = /\G (#{MBX_FLAG }(?:#{SP}#{MBX_FLAG })*) /nix
|
233
233
|
|
234
|
+
# Gmail allows SP and "]" in flags.......
|
235
|
+
QUIRKY_FLAG = Regexp.union(/\\?#{ASTRING_CHARS}/n, "\\*")
|
236
|
+
QUIRKY_FLAGS_LIST = /\G\(( [^)]* )\)/nx
|
237
|
+
|
234
238
|
# RFC3501:
|
235
239
|
# QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> /
|
236
240
|
# "\" quoted-specials
|
@@ -464,7 +468,7 @@ module Net
|
|
464
468
|
def sequence_set
|
465
469
|
str = combine_adjacent(*SEQUENCE_SET_TOKENS)
|
466
470
|
if Patterns::SEQUENCE_SET_STR.match?(str)
|
467
|
-
SequenceSet
|
471
|
+
SequenceSet[str]
|
468
472
|
else
|
469
473
|
parse_error("unexpected atom %p, expected sequence-set", str)
|
470
474
|
end
|
@@ -978,7 +982,7 @@ module Net
|
|
978
982
|
# env-bcc = "(" 1*address ")" / nil
|
979
983
|
def nlist__address
|
980
984
|
return if NIL?
|
981
|
-
lpar; list = [address]; list << address until rpar?
|
985
|
+
lpar; list = [address]; list << address until (quirky_SP?; rpar?)
|
982
986
|
list
|
983
987
|
end
|
984
988
|
|
@@ -989,6 +993,12 @@ module Net
|
|
989
993
|
alias env_cc nlist__address
|
990
994
|
alias env_bcc nlist__address
|
991
995
|
|
996
|
+
# Used when servers erroneously send an extra SP.
|
997
|
+
#
|
998
|
+
# As of 2023-11-28, Outlook.com (still) sends SP
|
999
|
+
# between +address+ in <tt>env-*</tt> lists.
|
1000
|
+
alias quirky_SP? SP?
|
1001
|
+
|
992
1002
|
# date-time = DQUOTE date-day-fixed "-" date-month "-" date-year
|
993
1003
|
# SP time SP zone DQUOTE
|
994
1004
|
alias date_time quoted
|
@@ -1360,7 +1370,7 @@ module Net
|
|
1360
1370
|
MailboxList.new(attr, delim, name)
|
1361
1371
|
end
|
1362
1372
|
|
1363
|
-
def
|
1373
|
+
def quota_response
|
1364
1374
|
# If quota never established, get back
|
1365
1375
|
# `NO Quota root does not exist'.
|
1366
1376
|
# If quota removed, get `()' after the
|
@@ -1393,7 +1403,7 @@ module Net
|
|
1393
1403
|
end
|
1394
1404
|
end
|
1395
1405
|
|
1396
|
-
def
|
1406
|
+
def quotaroot_response
|
1397
1407
|
# Similar to getquota, but only admin can use getquota.
|
1398
1408
|
token = match(T_ATOM)
|
1399
1409
|
name = token.value.upcase
|
@@ -1452,34 +1462,16 @@ module Net
|
|
1452
1462
|
# mailbox-data = obsolete-search-response / ...
|
1453
1463
|
# obsolete-search-response = "SEARCH" *(SP nz-number)
|
1454
1464
|
def mailbox_data__search
|
1455
|
-
|
1456
|
-
|
1457
|
-
|
1458
|
-
if
|
1459
|
-
|
1460
|
-
|
1461
|
-
|
1462
|
-
token = lookahead
|
1463
|
-
case token.symbol
|
1464
|
-
when T_CRLF
|
1465
|
-
break
|
1466
|
-
when T_SPACE
|
1467
|
-
shift_token
|
1468
|
-
when T_NUMBER
|
1469
|
-
data.push(number)
|
1470
|
-
when T_LPAR
|
1471
|
-
# TODO: include the MODSEQ value in a response
|
1472
|
-
shift_token
|
1473
|
-
match(T_ATOM)
|
1474
|
-
match(T_SPACE)
|
1475
|
-
match(T_NUMBER)
|
1476
|
-
match(T_RPAR)
|
1477
|
-
end
|
1478
|
-
end
|
1479
|
-
else
|
1480
|
-
data = []
|
1465
|
+
name = label_in("SEARCH", "SORT")
|
1466
|
+
data = []
|
1467
|
+
while _ = SP? && nz_number? do data << _ end
|
1468
|
+
if lpar?
|
1469
|
+
label("MODSEQ"); SP!
|
1470
|
+
modseq = mod_sequence_value
|
1471
|
+
rpar
|
1481
1472
|
end
|
1482
|
-
|
1473
|
+
data = SearchResult.new(data, modseq: modseq)
|
1474
|
+
UntaggedResponse.new(name, data, @str)
|
1483
1475
|
end
|
1484
1476
|
alias sort_data mailbox_data__search
|
1485
1477
|
|
@@ -1603,6 +1595,7 @@ module Net
|
|
1603
1595
|
when "UIDVALIDITY" then nz_number # RFC3501, RFC9051
|
1604
1596
|
when "RECENT" then number # RFC3501 (obsolete)
|
1605
1597
|
when "SIZE" then number64 # RFC8483, RFC9051
|
1598
|
+
when "HIGHESTMODSEQ" then mod_sequence_valzer # RFC7162
|
1606
1599
|
when "MAILBOXID" then parens__objectid # RFC8474
|
1607
1600
|
else
|
1608
1601
|
number? || ExtensionData.new(tagged_ext_val)
|
@@ -1809,6 +1802,8 @@ module Net
|
|
1809
1802
|
# resp-text-code =/ "HIGHESTMODSEQ" SP mod-sequence-value /
|
1810
1803
|
# "NOMODSEQ" /
|
1811
1804
|
# "MODIFIED" SP sequence-set
|
1805
|
+
# RFC7162 (QRESYNC):
|
1806
|
+
# resp-text-code =/ "CLOSED"
|
1812
1807
|
#
|
1813
1808
|
# RFC8474: OBJECTID
|
1814
1809
|
# resp-text-code =/ "MAILBOXID" SP "(" objectid ")"
|
@@ -1830,7 +1825,9 @@ module Net
|
|
1830
1825
|
"EXPUNGEISSUED", "CORRUPTION", "SERVERBUG", "CLIENTBUG", "CANNOT",
|
1831
1826
|
"LIMIT", "OVERQUOTA", "ALREADYEXISTS", "NONEXISTENT", "CLOSED",
|
1832
1827
|
"NOTSAVED", "UIDNOTSTICKY", "UNKNOWN-CTE", "HASCHILDREN"
|
1833
|
-
when "NOMODSEQ" # CONDSTORE
|
1828
|
+
when "NOMODSEQ" then nil # CONDSTORE
|
1829
|
+
when "HIGHESTMODSEQ" then SP!; mod_sequence_value # CONDSTORE
|
1830
|
+
when "MODIFIED" then SP!; sequence_set # CONDSTORE
|
1834
1831
|
when "MAILBOXID" then SP!; parens__objectid # RFC8474: OBJECTID
|
1835
1832
|
else
|
1836
1833
|
SP? and text_chars_except_rbra
|
@@ -1914,22 +1911,35 @@ module Net
|
|
1914
1911
|
|
1915
1912
|
# flag-list = "(" [flag *(SP flag)] ")"
|
1916
1913
|
def flag_list
|
1917
|
-
|
1918
|
-
.split(nil)
|
1919
|
-
|
1914
|
+
if (match = accept_re(Patterns::FLAG_LIST))
|
1915
|
+
match[1].split(nil)
|
1916
|
+
.map! { _1.delete_prefix!("\\") ? _1.capitalize.to_sym : _1 }
|
1917
|
+
else
|
1918
|
+
quirky__flag_list "flags-list"
|
1919
|
+
end
|
1920
1920
|
end
|
1921
1921
|
|
1922
1922
|
# "(" [flag-perm *(SP flag-perm)] ")"
|
1923
1923
|
def flag_perm__list
|
1924
|
-
|
1925
|
-
.split(nil)
|
1926
|
-
|
1924
|
+
if (match = accept_re(Patterns::FLAG_PERM_LIST))
|
1925
|
+
match[1].split(nil)
|
1926
|
+
.map! { _1.delete_prefix!("\\") ? _1.capitalize.to_sym : _1 }
|
1927
|
+
else
|
1928
|
+
quirky__flag_list "PERMANENTFLAGS flag-perm list"
|
1929
|
+
end
|
1930
|
+
end
|
1931
|
+
|
1932
|
+
def quirky__flag_list(name)
|
1933
|
+
match_re(Patterns::QUIRKY_FLAGS_LIST, "quirks mode #{name}")[1]
|
1934
|
+
.scan(Patterns::QUIRKY_FLAG)
|
1935
|
+
.map! { _1.delete_prefix!("\\") ? _1.capitalize.to_sym : _1 }
|
1927
1936
|
end
|
1928
1937
|
|
1929
1938
|
# See Patterns::MBX_LIST_FLAGS
|
1930
1939
|
def mbx_list_flags
|
1931
1940
|
match_re(Patterns::MBX_LIST_FLAGS, "mbx-list-flags")[1]
|
1932
|
-
.split(nil)
|
1941
|
+
.split(nil)
|
1942
|
+
.map! { _1.delete_prefix!("\\"); _1.capitalize.to_sym }
|
1933
1943
|
end
|
1934
1944
|
|
1935
1945
|
# See https://developers.google.com/gmail/imap/imap-extensions
|
@@ -1962,6 +1972,10 @@ module Net
|
|
1962
1972
|
# ;; Per-message mod-sequence.
|
1963
1973
|
alias permsg_modsequence mod_sequence_value
|
1964
1974
|
|
1975
|
+
# RFC7162:
|
1976
|
+
# mod-sequence-valzer = "0" / mod-sequence-value
|
1977
|
+
alias mod_sequence_valzer number64
|
1978
|
+
|
1965
1979
|
def parens__modseq; lpar; _ = permsg_modsequence; rpar; _ end
|
1966
1980
|
|
1967
1981
|
# RFC8474:
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Net
|
4
|
+
class IMAP
|
5
|
+
|
6
|
+
# An array of sequence numbers returned by Net::IMAP#search, or unique
|
7
|
+
# identifiers returned by Net::IMAP#uid_search.
|
8
|
+
#
|
9
|
+
# For backward compatibility, SearchResult inherits from Array.
|
10
|
+
class SearchResult < Array
|
11
|
+
|
12
|
+
# Returns a frozen SearchResult populated with the given +seq_nums+.
|
13
|
+
#
|
14
|
+
# Net::IMAP::SearchResult[1, 3, 5, modseq: 9]
|
15
|
+
# # => Net::IMAP::SearchResult[1, 3, 5, modseq: 9]
|
16
|
+
def self.[](*seq_nums, modseq: nil)
|
17
|
+
new(seq_nums, modseq: modseq)
|
18
|
+
end
|
19
|
+
|
20
|
+
# A modification sequence number, as described by the +CONDSTORE+
|
21
|
+
# extension in {[RFC7162
|
22
|
+
# §3.1.6]}[https://www.rfc-editor.org/rfc/rfc7162.html#section-3.1.6].
|
23
|
+
attr_reader :modseq
|
24
|
+
|
25
|
+
# Returns a frozen SearchResult populated with the given +seq_nums+.
|
26
|
+
#
|
27
|
+
# Net::IMAP::SearchResult.new([1, 3, 5], modseq: 9)
|
28
|
+
# # => Net::IMAP::SearchResult[1, 3, 5, modseq: 9]
|
29
|
+
def initialize(seq_nums, modseq: nil)
|
30
|
+
super(seq_nums.to_ary.map { Integer _1 })
|
31
|
+
@modseq = Integer modseq if modseq
|
32
|
+
freeze
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns a frozen copy of +other+.
|
36
|
+
def initialize_copy(other); super; freeze end
|
37
|
+
|
38
|
+
# Returns whether +other+ is a SearchResult with the same values and the
|
39
|
+
# same #modseq. The order of numbers is irrelevant.
|
40
|
+
#
|
41
|
+
# Net::IMAP::SearchResult[123, 456, modseq: 789] ==
|
42
|
+
# Net::IMAP::SearchResult[123, 456, modseq: 789]
|
43
|
+
# # => true
|
44
|
+
# Net::IMAP::SearchResult[123, 456, modseq: 789] ==
|
45
|
+
# Net::IMAP::SearchResult[456, 123, modseq: 789]
|
46
|
+
# # => true
|
47
|
+
#
|
48
|
+
# Net::IMAP::SearchResult[123, 456, modseq: 789] ==
|
49
|
+
# Net::IMAP::SearchResult[987, 654, modseq: 789]
|
50
|
+
# # => false
|
51
|
+
# Net::IMAP::SearchResult[123, 456, modseq: 789] ==
|
52
|
+
# Net::IMAP::SearchResult[1, 2, 3, modseq: 9999]
|
53
|
+
# # => false
|
54
|
+
#
|
55
|
+
# SearchResult can be compared directly with Array, if #modseq is nil and
|
56
|
+
# the array is sorted.
|
57
|
+
#
|
58
|
+
# Net::IMAP::SearchResult[9, 8, 6, 4, 1] == [1, 4, 6, 8, 9] # => true
|
59
|
+
# Net::IMAP::SearchResult[3, 5, 7, modseq: 99] == [3, 5, 7] # => false
|
60
|
+
#
|
61
|
+
# Note that Array#== does require matching order and ignores #modseq.
|
62
|
+
#
|
63
|
+
# [9, 8, 6, 4, 1] == Net::IMAP::SearchResult[1, 4, 6, 8, 9] # => false
|
64
|
+
# [3, 5, 7] == Net::IMAP::SearchResult[3, 5, 7, modseq: 99] # => true
|
65
|
+
#
|
66
|
+
def ==(other)
|
67
|
+
(modseq ?
|
68
|
+
other.is_a?(self.class) && modseq == other.modseq :
|
69
|
+
other.is_a?(Array)) &&
|
70
|
+
size == other.size &&
|
71
|
+
sort == other.sort
|
72
|
+
end
|
73
|
+
|
74
|
+
# Hash equality. Unlike #==, order will be taken into account.
|
75
|
+
def hash
|
76
|
+
return super if modseq.nil?
|
77
|
+
[super, self.class, modseq].hash
|
78
|
+
end
|
79
|
+
|
80
|
+
# Hash equality. Unlike #==, order will be taken into account.
|
81
|
+
def eql?(other)
|
82
|
+
return super if modseq.nil?
|
83
|
+
self.class == other.class && hash == other.hash
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns a string that represents the SearchResult.
|
87
|
+
#
|
88
|
+
# Net::IMAP::SearchResult[123, 456, 789].inspect
|
89
|
+
# # => "[123, 456, 789]"
|
90
|
+
#
|
91
|
+
# Net::IMAP::SearchResult[543, 210, 678, modseq: 2048].inspect
|
92
|
+
# # => "Net::IMAP::SearchResult[543, 210, 678, modseq: 2048]"
|
93
|
+
#
|
94
|
+
def inspect
|
95
|
+
return super if modseq.nil?
|
96
|
+
"%s[%s, modseq: %p]" % [self.class, join(", "), modseq]
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns a string that follows the formal \IMAP syntax.
|
100
|
+
#
|
101
|
+
# data = Net::IMAP::SearchResult[2, 8, 32, 128, 256, 512]
|
102
|
+
# data.to_s # => "* SEARCH 2 8 32 128 256 512"
|
103
|
+
# data.to_s("SEARCH") # => "* SEARCH 2 8 32 128 256 512"
|
104
|
+
# data.to_s("SORT") # => "* SORT 2 8 32 128 256 512"
|
105
|
+
# data.to_s(nil) # => "2 8 32 128 256 512"
|
106
|
+
#
|
107
|
+
# data = Net::IMAP::SearchResult[1, 3, 16, 1024, modseq: 2048].to_s
|
108
|
+
# data.to_s # => "* SEARCH 1 3 16 1024 (MODSEQ 2048)"
|
109
|
+
# data.to_s("SORT") # => "* SORT 1 3 16 1024 (MODSEQ 2048)"
|
110
|
+
# data.to_s # => "1 3 16 1024 (MODSEQ 2048)"
|
111
|
+
#
|
112
|
+
def to_s(type = "SEARCH")
|
113
|
+
str = +""
|
114
|
+
str << "* %s " % [type.to_str] unless type.nil?
|
115
|
+
str << join(" ")
|
116
|
+
str << " (MODSEQ %d)" % [modseq] if modseq
|
117
|
+
-str
|
118
|
+
end
|
119
|
+
|
120
|
+
# Converts the SearchResult into a SequenceSet.
|
121
|
+
#
|
122
|
+
# Net::IMAP::SearchResult[9, 1, 2, 4, 10, 12, 3, modseq: 123_456]
|
123
|
+
# .to_sequence_set
|
124
|
+
# # => Net::IMAP::SequenceSet["1:4,9:10,12"]
|
125
|
+
def to_sequence_set; SequenceSet[*self] end
|
126
|
+
|
127
|
+
def pretty_print(pp)
|
128
|
+
return super if modseq.nil?
|
129
|
+
pp.text self.class.name + "["
|
130
|
+
pp.group_sub do
|
131
|
+
pp.nest(2) do
|
132
|
+
pp.breakable ""
|
133
|
+
each do |num|
|
134
|
+
pp.pp num
|
135
|
+
pp.text ","
|
136
|
+
pp.fill_breakable
|
137
|
+
end
|
138
|
+
pp.breakable ""
|
139
|
+
pp.text "modseq: "
|
140
|
+
pp.pp modseq
|
141
|
+
end
|
142
|
+
pp.breakable ""
|
143
|
+
pp.text "]"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|