net-imap 0.5.1 → 0.5.6
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/Gemfile +1 -0
- data/README.md +10 -4
- data/docs/styles.css +75 -14
- data/lib/net/imap/command_data.rb +48 -46
- data/lib/net/imap/config.rb +73 -3
- data/lib/net/imap/data_lite.rb +226 -0
- data/lib/net/imap/esearch_result.rb +180 -0
- data/lib/net/imap/fetch_data.rb +126 -47
- data/lib/net/imap/response_data.rb +118 -144
- data/lib/net/imap/response_parser/parser_utils.rb +5 -0
- data/lib/net/imap/response_parser.rb +178 -17
- data/lib/net/imap/sasl/anonymous_authenticator.rb +3 -3
- data/lib/net/imap/sasl/cram_md5_authenticator.rb +3 -3
- data/lib/net/imap/sasl/digest_md5_authenticator.rb +8 -8
- data/lib/net/imap/sasl/external_authenticator.rb +2 -2
- data/lib/net/imap/sasl/gs2_header.rb +7 -7
- data/lib/net/imap/sasl/login_authenticator.rb +2 -2
- data/lib/net/imap/sasl/oauthbearer_authenticator.rb +6 -6
- data/lib/net/imap/sasl/plain_authenticator.rb +7 -7
- data/lib/net/imap/sasl/scram_authenticator.rb +8 -8
- data/lib/net/imap/sasl.rb +1 -1
- data/lib/net/imap/search_result.rb +2 -2
- data/lib/net/imap/sequence_set.rb +193 -58
- data/lib/net/imap/stringprep/nameprep.rb +1 -1
- data/lib/net/imap/stringprep/trace.rb +4 -4
- data/lib/net/imap/uidplus_data.rb +244 -0
- data/lib/net/imap/vanished_data.rb +56 -0
- data/lib/net/imap.rb +694 -319
- data/rakelib/rfcs.rake +2 -0
- metadata +7 -6
@@ -0,0 +1,180 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Net
|
4
|
+
class IMAP
|
5
|
+
# An "extended search" response (+ESEARCH+). ESearchResult should be
|
6
|
+
# returned (instead of SearchResult) by IMAP#search, IMAP#uid_search,
|
7
|
+
# IMAP#sort, and IMAP#uid_sort under any of the following conditions:
|
8
|
+
#
|
9
|
+
# * Return options were specified for IMAP#search or IMAP#uid_search.
|
10
|
+
# The server must support a search extension which allows
|
11
|
+
# RFC4466[https://www.rfc-editor.org/rfc/rfc4466.html] +return+ options,
|
12
|
+
# such as +ESEARCH+, +PARTIAL+, or +IMAP4rev2+.
|
13
|
+
# * Return options were specified for IMAP#sort or IMAP#uid_sort.
|
14
|
+
# The server must support the +ESORT+ extension
|
15
|
+
# {[RFC5267]}[https://www.rfc-editor.org/rfc/rfc5267.html#section-3].
|
16
|
+
#
|
17
|
+
# *NOTE:* IMAP#search and IMAP#uid_search do not support +ESORT+ yet.
|
18
|
+
# * The server supports +IMAP4rev2+ but _not_ +IMAP4rev1+, or +IMAP4rev2+
|
19
|
+
# has been enabled. +IMAP4rev2+ requires +ESEARCH+ results.
|
20
|
+
#
|
21
|
+
# Note that some servers may claim to support a search extension which
|
22
|
+
# requires an +ESEARCH+ result, such as +PARTIAL+, but still only return a
|
23
|
+
# +SEARCH+ result when +return+ options are specified.
|
24
|
+
#
|
25
|
+
# Some search extensions may result in the server sending ESearchResult
|
26
|
+
# responses after the initiating command has completed. Use
|
27
|
+
# IMAP#add_response_handler to handle these responses.
|
28
|
+
class ESearchResult < Data.define(:tag, :uid, :data)
|
29
|
+
def initialize(tag: nil, uid: nil, data: nil)
|
30
|
+
tag => String | nil; tag = -tag if tag
|
31
|
+
uid => true | false | nil; uid = !!uid
|
32
|
+
data => Array | nil; data ||= []; data.freeze
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
36
|
+
# :call-seq: to_a -> Array of integers
|
37
|
+
#
|
38
|
+
# When either #all or #partial contains a SequenceSet of message sequence
|
39
|
+
# numbers or UIDs, +to_a+ returns that set as an array of integers.
|
40
|
+
#
|
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
|
+
# the IMAP#search +RETURN+ options, #to_a returns an empty array.
|
44
|
+
#
|
45
|
+
# Note that SearchResult also implements +to_a+, so it can be used without
|
46
|
+
# checking if the server returned +SEARCH+ or +ESEARCH+ data.
|
47
|
+
def to_a; all&.numbers || partial&.to_a || [] end
|
48
|
+
|
49
|
+
##
|
50
|
+
# attr_reader: tag
|
51
|
+
#
|
52
|
+
# The tag string for the command that caused this response to be returned.
|
53
|
+
#
|
54
|
+
# When +nil+, this response was not caused by a particular command.
|
55
|
+
|
56
|
+
##
|
57
|
+
# attr_reader: uid
|
58
|
+
#
|
59
|
+
# Indicates whether #data in this response refers to UIDs (when +true+) or
|
60
|
+
# to message sequence numbers (when +false+).
|
61
|
+
|
62
|
+
##
|
63
|
+
alias uid? uid
|
64
|
+
|
65
|
+
##
|
66
|
+
# attr_reader: data
|
67
|
+
#
|
68
|
+
# Search return data, as an array of <tt>[name, value]</tt> pairs. Most
|
69
|
+
# return data corresponds to a search +return+ option with the same name.
|
70
|
+
#
|
71
|
+
# Note that some return data names may be used more than once per result.
|
72
|
+
#
|
73
|
+
# This data can be more simply retrieved by #min, #max, #all, #count,
|
74
|
+
# #modseq, and other methods.
|
75
|
+
|
76
|
+
# :call-seq: min -> integer or nil
|
77
|
+
#
|
78
|
+
# The lowest message number/UID that satisfies the SEARCH criteria.
|
79
|
+
#
|
80
|
+
# Returns +nil+ when the associated search command has no results, or when
|
81
|
+
# the +MIN+ return option wasn't specified.
|
82
|
+
#
|
83
|
+
# Requires +ESEARCH+ {[RFC4731]}[https://www.rfc-editor.org/rfc/rfc4731.html#section-3.1] or
|
84
|
+
# +IMAP4rev2+ {[RFC9051]}[https://www.rfc-editor.org/rfc/rfc9051.html#section-7.3.4].
|
85
|
+
def min; data.assoc("MIN")&.last end
|
86
|
+
|
87
|
+
# :call-seq: max -> integer or nil
|
88
|
+
#
|
89
|
+
# The highest message number/UID that satisfies the SEARCH criteria.
|
90
|
+
#
|
91
|
+
# Returns +nil+ when the associated search command has no results, or when
|
92
|
+
# the +MAX+ return option wasn't specified.
|
93
|
+
#
|
94
|
+
# Requires +ESEARCH+ {[RFC4731]}[https://www.rfc-editor.org/rfc/rfc4731.html#section-3.1] or
|
95
|
+
# +IMAP4rev2+ {[RFC9051]}[https://www.rfc-editor.org/rfc/rfc9051.html#section-7.3.4].
|
96
|
+
def max; data.assoc("MAX")&.last end
|
97
|
+
|
98
|
+
# :call-seq: all -> sequence set or nil
|
99
|
+
#
|
100
|
+
# A SequenceSet containing all message sequence numbers or UIDs that
|
101
|
+
# satisfy the SEARCH criteria.
|
102
|
+
#
|
103
|
+
# Returns +nil+ when the associated search command has no results, or when
|
104
|
+
# the +ALL+ return option was not specified but other return options were.
|
105
|
+
#
|
106
|
+
# Requires +ESEARCH+ {[RFC4731]}[https://www.rfc-editor.org/rfc/rfc4731.html#section-3.1] or
|
107
|
+
# +IMAP4rev2+ {[RFC9051]}[https://www.rfc-editor.org/rfc/rfc9051.html#section-7.3.4].
|
108
|
+
#
|
109
|
+
# See also: #to_a
|
110
|
+
def all; data.assoc("ALL")&.last end
|
111
|
+
|
112
|
+
# :call-seq: count -> integer or nil
|
113
|
+
#
|
114
|
+
# Returns the number of messages that satisfy the SEARCH criteria.
|
115
|
+
#
|
116
|
+
# Returns +nil+ when the associated search command has no results, or when
|
117
|
+
# the +COUNT+ return option wasn't specified.
|
118
|
+
#
|
119
|
+
# Requires +ESEARCH+ {[RFC4731]}[https://www.rfc-editor.org/rfc/rfc4731.html#section-3.1] or
|
120
|
+
# +IMAP4rev2+ {[RFC9051]}[https://www.rfc-editor.org/rfc/rfc9051.html#section-7.3.4].
|
121
|
+
def count; data.assoc("COUNT")&.last end
|
122
|
+
|
123
|
+
# :call-seq: modseq -> integer or nil
|
124
|
+
#
|
125
|
+
# The highest +mod-sequence+ of all messages being returned.
|
126
|
+
#
|
127
|
+
# Returns +nil+ when the associated search command has no results, or when
|
128
|
+
# the +MODSEQ+ search criterion wasn't specified.
|
129
|
+
#
|
130
|
+
# Note that there is no search +return+ option for +MODSEQ+. It will be
|
131
|
+
# returned whenever the +CONDSTORE+ extension has been enabled. Using the
|
132
|
+
# +MODSEQ+ search criteria will implicitly enable +CONDSTORE+.
|
133
|
+
#
|
134
|
+
# Requires +CONDSTORE+ {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html]
|
135
|
+
# and +ESEARCH+ {[RFC4731]}[https://www.rfc-editor.org/rfc/rfc4731.html#section-3.2].
|
136
|
+
def modseq; data.assoc("MODSEQ")&.last end
|
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
|
+
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
data/lib/net/imap/fetch_data.rb
CHANGED
@@ -3,9 +3,9 @@
|
|
3
3
|
module Net
|
4
4
|
class IMAP < Protocol
|
5
5
|
|
6
|
-
# Net::IMAP::
|
7
|
-
# Net::IMAP#fetch
|
8
|
-
#
|
6
|
+
# Net::IMAP::FetchStruct is the superclass for FetchData and UIDFetchData.
|
7
|
+
# Net::IMAP#fetch, Net::IMAP#uid_fetch, Net::IMAP#store, and
|
8
|
+
# Net::IMAP#uid_store all return arrays of FetchStruct objects.
|
9
9
|
#
|
10
10
|
# === Fetch attributes
|
11
11
|
#
|
@@ -63,8 +63,7 @@ module Net
|
|
63
63
|
# * <b><tt>"X-GM-MSGID"</tt></b> --- unique message ID. Access via #attr.
|
64
64
|
# * <b><tt>"X-GM-THRID"</tt></b> --- Thread ID. Access via #attr.
|
65
65
|
#
|
66
|
-
# [
|
67
|
-
# >>>
|
66
|
+
# [NOTE:]
|
68
67
|
# Additional static fields are defined in other \IMAP extensions, but
|
69
68
|
# Net::IMAP can't parse them yet.
|
70
69
|
#
|
@@ -87,34 +86,23 @@ module Net
|
|
87
86
|
# extension]}[https://developers.google.com/gmail/imap/imap-extensions]
|
88
87
|
# * <b><tt>"X-GM-LABELS"</tt></b> --- Gmail labels. Access via #attr.
|
89
88
|
#
|
90
|
-
# [
|
91
|
-
# >>>
|
89
|
+
# [NOTE:]
|
92
90
|
# Additional dynamic fields are defined in other \IMAP extensions, but
|
93
91
|
# Net::IMAP can't parse them yet.
|
94
92
|
#
|
95
93
|
# === Implicitly setting <tt>\Seen</tt> and using +PEEK+
|
96
94
|
#
|
97
|
-
# Unless the mailbox
|
95
|
+
# Unless the mailbox has been opened as read-only, fetching
|
98
96
|
# <tt>BODY[#{section}]</tt> or <tt>BINARY[#{section}]</tt>
|
99
97
|
# will implicitly set the <tt>\Seen</tt> flag. To avoid this, fetch using
|
100
98
|
# <tt>BODY.PEEK[#{section}]</tt> or <tt>BINARY.PEEK[#{section}]</tt>
|
101
99
|
# instead.
|
102
100
|
#
|
103
|
-
#
|
104
|
-
# <tt>
|
101
|
+
# [NOTE:]
|
102
|
+
# The data will always be _returned_ without the <tt>".PEEK"</tt> suffix,
|
103
|
+
# as <tt>BODY[#{specifier}]</tt> or <tt>BINARY[#{section}]</tt>.
|
105
104
|
#
|
106
|
-
class
|
107
|
-
##
|
108
|
-
# method: seqno
|
109
|
-
# :call-seq: seqno -> Integer
|
110
|
-
#
|
111
|
-
# The message sequence number.
|
112
|
-
#
|
113
|
-
# [Note]
|
114
|
-
# This is never the unique identifier (UID), not even for the
|
115
|
-
# Net::IMAP#uid_fetch result. The UID is available from #uid, if it was
|
116
|
-
# returned.
|
117
|
-
|
105
|
+
class FetchStruct < Struct
|
118
106
|
##
|
119
107
|
# method: attr
|
120
108
|
# :call-seq: attr -> hash
|
@@ -123,9 +111,6 @@ module Net
|
|
123
111
|
# corresponding data item. Standard data items have corresponding
|
124
112
|
# accessor methods. The definitions of each attribute type is documented
|
125
113
|
# on its accessor.
|
126
|
-
#
|
127
|
-
# >>>
|
128
|
-
# *Note:* #seqno is not a message attribute.
|
129
114
|
|
130
115
|
# :call-seq: attr_upcase -> hash
|
131
116
|
#
|
@@ -142,7 +127,7 @@ module Net
|
|
142
127
|
#
|
143
128
|
# This is the same as getting the value for <tt>"BODY"</tt> from #attr.
|
144
129
|
#
|
145
|
-
# [
|
130
|
+
# [NOTE:]
|
146
131
|
# Use #message, #part, #header, #header_fields, #header_fields_not,
|
147
132
|
# #text, or #mime to retrieve <tt>BODY[#{section_spec}]</tt> attributes.
|
148
133
|
def body; attr["BODY"] end
|
@@ -235,7 +220,7 @@ module Net
|
|
235
220
|
fields && except and
|
236
221
|
raise ArgumentError, "conflicting 'fields' and 'except' arguments"
|
237
222
|
if fields
|
238
|
-
text = "HEADER.FIELDS (%s)"
|
223
|
+
text = "HEADER.FIELDS (%s)" % [fields.join(" ").upcase]
|
239
224
|
attr_upcase[body_section_attr(part_nums, text, offset: offset)]
|
240
225
|
elsif except
|
241
226
|
text = "HEADER.FIELDS.NOT (%s)" % [except.join(" ").upcase]
|
@@ -308,6 +293,7 @@ module Net
|
|
308
293
|
# This is the same as getting the value for <tt>"BODYSTRUCTURE"</tt> from
|
309
294
|
# #attr.
|
310
295
|
def bodystructure; attr["BODYSTRUCTURE"] end
|
296
|
+
|
311
297
|
alias body_structure bodystructure
|
312
298
|
|
313
299
|
# :call-seq: envelope -> Envelope or nil
|
@@ -320,7 +306,7 @@ module Net
|
|
320
306
|
# #attr.
|
321
307
|
def envelope; attr["ENVELOPE"] end
|
322
308
|
|
323
|
-
# :call-seq: flags -> array of Symbols and Strings
|
309
|
+
# :call-seq: flags -> array of Symbols and Strings, or nil
|
324
310
|
#
|
325
311
|
# A array of flags that are set for this message. System flags are
|
326
312
|
# symbols that have been capitalized by String#capitalize. Keyword flags
|
@@ -328,7 +314,7 @@ module Net
|
|
328
314
|
#
|
329
315
|
# This is the same as getting the value for <tt>"FLAGS"</tt> from #attr.
|
330
316
|
#
|
331
|
-
# [
|
317
|
+
# [NOTE:]
|
332
318
|
# The +FLAGS+ field is dynamic, and can change for a uniquely identified
|
333
319
|
# message.
|
334
320
|
def flags; attr["FLAGS"] end
|
@@ -336,40 +322,41 @@ module Net
|
|
336
322
|
# :call-seq: internaldate -> Time or nil
|
337
323
|
#
|
338
324
|
# The internal date and time of the message on the server. This is not
|
339
|
-
# the date and time in the [RFC5322[https://
|
325
|
+
# the date and time in the [RFC5322[https://www.rfc-editor.org/rfc/rfc5322]]
|
340
326
|
# header, but rather a date and time which reflects when the message was
|
341
327
|
# received.
|
342
328
|
#
|
343
329
|
# This is similar to getting the value for <tt>"INTERNALDATE"</tt> from
|
344
330
|
# #attr.
|
345
331
|
#
|
346
|
-
# [
|
332
|
+
# [NOTE:]
|
347
333
|
# <tt>attr["INTERNALDATE"]</tt> returns a string, and this method
|
348
334
|
# returns a Time object.
|
349
335
|
def internaldate
|
350
336
|
attr["INTERNALDATE"]&.then { IMAP.decode_time _1 }
|
351
337
|
end
|
338
|
+
|
352
339
|
alias internal_date internaldate
|
353
340
|
|
354
|
-
# :call-seq: rfc822 -> String
|
341
|
+
# :call-seq: rfc822 -> String or nil
|
355
342
|
#
|
356
343
|
# Semantically equivalent to #message with no arguments.
|
357
344
|
#
|
358
345
|
# This is the same as getting the value for <tt>"RFC822"</tt> from #attr.
|
359
346
|
#
|
360
|
-
# [
|
347
|
+
# [NOTE:]
|
361
348
|
# +IMAP4rev2+ deprecates <tt>RFC822</tt>.
|
362
349
|
def rfc822; attr["RFC822"] end
|
363
350
|
|
364
|
-
# :call-seq: rfc822_size -> Integer
|
351
|
+
# :call-seq: rfc822_size -> Integer or nil
|
365
352
|
#
|
366
|
-
# A number expressing the [RFC5322[https://
|
353
|
+
# A number expressing the [RFC5322[https://www.rfc-editor.org/rfc/rfc5322]]
|
367
354
|
# size of the message.
|
368
355
|
#
|
369
356
|
# This is the same as getting the value for <tt>"RFC822.SIZE"</tt> from
|
370
357
|
# #attr.
|
371
358
|
#
|
372
|
-
# [
|
359
|
+
# [NOTE:]
|
373
360
|
# \IMAP was originally developed for the older
|
374
361
|
# RFC822[https://www.rfc-editor.org/rfc/rfc822.html] standard, and as a
|
375
362
|
# consequence several fetch items in \IMAP incorporate "RFC822" in their
|
@@ -379,34 +366,45 @@ module Net
|
|
379
366
|
# interpreted as a reference to the updated
|
380
367
|
# RFC5322[https://www.rfc-editor.org/rfc/rfc5322.html] standard.
|
381
368
|
def rfc822_size; attr["RFC822.SIZE"] end
|
382
|
-
alias size rfc822_size
|
383
369
|
|
384
|
-
# :call-seq
|
370
|
+
# NOTE: a bug in rdoc 6.7 prevents us from adding a call-seq to
|
371
|
+
# rfc822_size _and_ aliasing size => rfc822_size. Is it because this
|
372
|
+
# class inherits from Struct?
|
373
|
+
|
374
|
+
# Alias for: rfc822_size
|
375
|
+
def size; rfc822_size end
|
376
|
+
|
377
|
+
|
378
|
+
# :call-seq: rfc822_header -> String or nil
|
385
379
|
#
|
386
380
|
# Semantically equivalent to #header, with no arguments.
|
387
381
|
#
|
388
382
|
# This is the same as getting the value for <tt>"RFC822.HEADER"</tt> from #attr.
|
389
383
|
#
|
390
|
-
# [
|
384
|
+
# [NOTE:]
|
391
385
|
# +IMAP4rev2+ deprecates <tt>RFC822.HEADER</tt>.
|
392
386
|
def rfc822_header; attr["RFC822.HEADER"] end
|
393
387
|
|
394
|
-
# :call-seq: rfc822_text -> String
|
388
|
+
# :call-seq: rfc822_text -> String or nil
|
395
389
|
#
|
396
390
|
# Semantically equivalent to #text, with no arguments.
|
397
391
|
#
|
398
392
|
# This is the same as getting the value for <tt>"RFC822.TEXT"</tt> from
|
399
393
|
# #attr.
|
400
394
|
#
|
401
|
-
# [
|
395
|
+
# [NOTE:]
|
402
396
|
# +IMAP4rev2+ deprecates <tt>RFC822.TEXT</tt>.
|
403
397
|
def rfc822_text; attr["RFC822.TEXT"] end
|
404
398
|
|
405
|
-
# :call-seq: uid -> Integer
|
399
|
+
# :call-seq: uid -> Integer or nil
|
406
400
|
#
|
407
401
|
# A number expressing the unique identifier of the message.
|
408
402
|
#
|
409
403
|
# This is the same as getting the value for <tt>"UID"</tt> from #attr.
|
404
|
+
#
|
405
|
+
# [NOTE:]
|
406
|
+
# For UIDFetchData, this returns the uniqueid at the beginning of the
|
407
|
+
# +UIDFETCH+ response, _not_ the value from #attr.
|
410
408
|
def uid; attr["UID"] end
|
411
409
|
|
412
410
|
# :call-seq:
|
@@ -452,7 +450,7 @@ module Net
|
|
452
450
|
attr[section_attr("BINARY.SIZE", part_nums)]
|
453
451
|
end
|
454
452
|
|
455
|
-
# :call-seq: modseq -> Integer
|
453
|
+
# :call-seq: modseq -> Integer or nil
|
456
454
|
#
|
457
455
|
# The modification sequence number associated with this IMAP message.
|
458
456
|
#
|
@@ -461,7 +459,7 @@ module Net
|
|
461
459
|
# The server must support the +CONDSTORE+ extension
|
462
460
|
# {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html].
|
463
461
|
#
|
464
|
-
# [
|
462
|
+
# [NOTE:]
|
465
463
|
# The +MODSEQ+ field is dynamic, and can change for a uniquely
|
466
464
|
# identified message.
|
467
465
|
def modseq; attr["MODSEQ"] end
|
@@ -508,11 +506,92 @@ module Net
|
|
508
506
|
spec = Array(part).flatten.map { Integer(_1) }
|
509
507
|
spec << text if text
|
510
508
|
spec = spec.join(".")
|
511
|
-
if offset then "%s[%s]<%d>" % [attr, spec, Integer(offset)]
|
512
|
-
else "%s[%s]" % [attr, spec]
|
513
|
-
end
|
509
|
+
if offset then "%s[%s]<%d>" % [attr, spec, Integer(offset)] else "%s[%s]" % [attr, spec] end
|
514
510
|
end
|
511
|
+
end
|
515
512
|
|
513
|
+
# Net::IMAP::FetchData represents the contents of a +FETCH+ response.
|
514
|
+
# Net::IMAP#fetch, Net::IMAP#uid_fetch, Net::IMAP#store, and
|
515
|
+
# Net::IMAP#uid_store all return arrays of FetchData objects, except when
|
516
|
+
# the +UIDONLY+ extension is enabled.
|
517
|
+
#
|
518
|
+
# See FetchStruct documentation for a list of standard message attributes.
|
519
|
+
class FetchData < FetchStruct.new(:seqno, :attr)
|
520
|
+
##
|
521
|
+
# method: seqno
|
522
|
+
# :call-seq: seqno -> Integer
|
523
|
+
#
|
524
|
+
# The message sequence number.
|
525
|
+
#
|
526
|
+
# [NOTE:]
|
527
|
+
# This is not the same as the unique identifier (UID), not even for the
|
528
|
+
# Net::IMAP#uid_fetch result. The UID is available from #uid, if it was
|
529
|
+
# returned.
|
530
|
+
#
|
531
|
+
# [NOTE:]
|
532
|
+
# UIDFetchData will raise a NoMethodError.
|
533
|
+
|
534
|
+
##
|
535
|
+
# method: attr
|
536
|
+
# :call-seq: attr -> hash
|
537
|
+
#
|
538
|
+
# Each key specifies a message attribute, and the value is the
|
539
|
+
# corresponding data item. Standard data items have corresponding
|
540
|
+
# accessor methods. The definitions of each attribute type is documented
|
541
|
+
# on its accessor.
|
542
|
+
#
|
543
|
+
# See FetchStruct documentation for message attribute accessors.
|
544
|
+
#
|
545
|
+
# [NOTE:]
|
546
|
+
# #seqno is not a message attribute.
|
547
|
+
end
|
548
|
+
|
549
|
+
# Net::IMAP::UIDFetchData represents the contents of a +UIDFETCH+ response,
|
550
|
+
# When the +UIDONLY+ extension has been enabled, Net::IMAP#uid_fetch and
|
551
|
+
# Net::IMAP#uid_store will both return an array of UIDFetchData objects.
|
552
|
+
#
|
553
|
+
# UIDFetchData contains the same message attributes as FetchData. However,
|
554
|
+
# +UIDFETCH+ responses return the UID at the beginning of the response,
|
555
|
+
# replacing FetchData#seqno. UIDFetchData never contains a message sequence
|
556
|
+
# number.
|
557
|
+
#
|
558
|
+
# See FetchStruct documentation for a list of standard message attributes.
|
559
|
+
class UIDFetchData < FetchStruct.new(:uid, :attr)
|
560
|
+
##
|
561
|
+
# method: uid
|
562
|
+
# call-seq: uid -> Integer
|
563
|
+
#
|
564
|
+
# A number expressing the unique identifier of the message.
|
565
|
+
#
|
566
|
+
# [NOTE:]
|
567
|
+
# Although #attr may _also_ have a redundant +UID+ attribute, #uid
|
568
|
+
# returns the uniqueid at the beginning of the +UIDFETCH+ response.
|
569
|
+
|
570
|
+
##
|
571
|
+
# method: attr
|
572
|
+
# call-seq: attr -> hash
|
573
|
+
#
|
574
|
+
# Each key specifies a message attribute, and the value is the
|
575
|
+
# corresponding data item. Standard data items have corresponding
|
576
|
+
# accessor methods. The definitions of each attribute type is documented
|
577
|
+
# on its accessor.
|
578
|
+
#
|
579
|
+
# See FetchStruct documentation for message attribute accessors.
|
580
|
+
#
|
581
|
+
# [NOTE:]
|
582
|
+
# #uid is not a message attribute. Although the server may return a
|
583
|
+
# +UID+ message attribute, it is not required to. #uid is taken from
|
584
|
+
# its corresponding +UIDFETCH+ field.
|
585
|
+
|
586
|
+
# UIDFetchData will print a warning if <tt>#attr["UID"]</tt> is present
|
587
|
+
# but not identical to #uid.
|
588
|
+
def initialize(...)
|
589
|
+
super
|
590
|
+
attr and
|
591
|
+
attr_uid = attr["UID"] and
|
592
|
+
attr_uid != uid and
|
593
|
+
warn "#{self.class} UIDs do not match (#{attr_uid} != #{uid})"
|
594
|
+
end
|
516
595
|
end
|
517
596
|
end
|
518
597
|
end
|