net-imap 0.4.6 → 0.4.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|