net-imap 0.4.7 → 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 +39 -12
- 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
- metadata +3 -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
|
@@ -1366,7 +1370,7 @@ module Net
|
|
1366
1370
|
MailboxList.new(attr, delim, name)
|
1367
1371
|
end
|
1368
1372
|
|
1369
|
-
def
|
1373
|
+
def quota_response
|
1370
1374
|
# If quota never established, get back
|
1371
1375
|
# `NO Quota root does not exist'.
|
1372
1376
|
# If quota removed, get `()' after the
|
@@ -1399,7 +1403,7 @@ module Net
|
|
1399
1403
|
end
|
1400
1404
|
end
|
1401
1405
|
|
1402
|
-
def
|
1406
|
+
def quotaroot_response
|
1403
1407
|
# Similar to getquota, but only admin can use getquota.
|
1404
1408
|
token = match(T_ATOM)
|
1405
1409
|
name = token.value.upcase
|
@@ -1463,9 +1467,10 @@ module Net
|
|
1463
1467
|
while _ = SP? && nz_number? do data << _ end
|
1464
1468
|
if lpar?
|
1465
1469
|
label("MODSEQ"); SP!
|
1466
|
-
mod_sequence_value
|
1470
|
+
modseq = mod_sequence_value
|
1467
1471
|
rpar
|
1468
1472
|
end
|
1473
|
+
data = SearchResult.new(data, modseq: modseq)
|
1469
1474
|
UntaggedResponse.new(name, data, @str)
|
1470
1475
|
end
|
1471
1476
|
alias sort_data mailbox_data__search
|
@@ -1590,6 +1595,7 @@ module Net
|
|
1590
1595
|
when "UIDVALIDITY" then nz_number # RFC3501, RFC9051
|
1591
1596
|
when "RECENT" then number # RFC3501 (obsolete)
|
1592
1597
|
when "SIZE" then number64 # RFC8483, RFC9051
|
1598
|
+
when "HIGHESTMODSEQ" then mod_sequence_valzer # RFC7162
|
1593
1599
|
when "MAILBOXID" then parens__objectid # RFC8474
|
1594
1600
|
else
|
1595
1601
|
number? || ExtensionData.new(tagged_ext_val)
|
@@ -1796,6 +1802,8 @@ module Net
|
|
1796
1802
|
# resp-text-code =/ "HIGHESTMODSEQ" SP mod-sequence-value /
|
1797
1803
|
# "NOMODSEQ" /
|
1798
1804
|
# "MODIFIED" SP sequence-set
|
1805
|
+
# RFC7162 (QRESYNC):
|
1806
|
+
# resp-text-code =/ "CLOSED"
|
1799
1807
|
#
|
1800
1808
|
# RFC8474: OBJECTID
|
1801
1809
|
# resp-text-code =/ "MAILBOXID" SP "(" objectid ")"
|
@@ -1817,7 +1825,9 @@ module Net
|
|
1817
1825
|
"EXPUNGEISSUED", "CORRUPTION", "SERVERBUG", "CLIENTBUG", "CANNOT",
|
1818
1826
|
"LIMIT", "OVERQUOTA", "ALREADYEXISTS", "NONEXISTENT", "CLOSED",
|
1819
1827
|
"NOTSAVED", "UIDNOTSTICKY", "UNKNOWN-CTE", "HASCHILDREN"
|
1820
|
-
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
|
1821
1831
|
when "MAILBOXID" then SP!; parens__objectid # RFC8474: OBJECTID
|
1822
1832
|
else
|
1823
1833
|
SP? and text_chars_except_rbra
|
@@ -1901,22 +1911,35 @@ module Net
|
|
1901
1911
|
|
1902
1912
|
# flag-list = "(" [flag *(SP flag)] ")"
|
1903
1913
|
def flag_list
|
1904
|
-
|
1905
|
-
.split(nil)
|
1906
|
-
|
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
|
1907
1920
|
end
|
1908
1921
|
|
1909
1922
|
# "(" [flag-perm *(SP flag-perm)] ")"
|
1910
1923
|
def flag_perm__list
|
1911
|
-
|
1912
|
-
.split(nil)
|
1913
|
-
|
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 }
|
1914
1936
|
end
|
1915
1937
|
|
1916
1938
|
# See Patterns::MBX_LIST_FLAGS
|
1917
1939
|
def mbx_list_flags
|
1918
1940
|
match_re(Patterns::MBX_LIST_FLAGS, "mbx-list-flags")[1]
|
1919
|
-
.split(nil)
|
1941
|
+
.split(nil)
|
1942
|
+
.map! { _1.delete_prefix!("\\"); _1.capitalize.to_sym }
|
1920
1943
|
end
|
1921
1944
|
|
1922
1945
|
# See https://developers.google.com/gmail/imap/imap-extensions
|
@@ -1949,6 +1972,10 @@ module Net
|
|
1949
1972
|
# ;; Per-message mod-sequence.
|
1950
1973
|
alias permsg_modsequence mod_sequence_value
|
1951
1974
|
|
1975
|
+
# RFC7162:
|
1976
|
+
# mod-sequence-valzer = "0" / mod-sequence-value
|
1977
|
+
alias mod_sequence_valzer number64
|
1978
|
+
|
1952
1979
|
def parens__modseq; lpar; _ = permsg_modsequence; rpar; _ end
|
1953
1980
|
|
1954
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
|