net-imap 0.3.1 → 0.3.7
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/test.yml +8 -1
- data/.gitignore +1 -0
- data/Gemfile +3 -0
- data/Rakefile +3 -0
- data/benchmarks/stringprep.yml +65 -0
- data/benchmarks/table-regexps.yml +39 -0
- data/docs/styles.css +36 -0
- data/lib/net/imap/authenticators/digest_md5.rb +2 -2
- data/lib/net/imap/authenticators/xoauth2.rb +1 -1
- data/lib/net/imap/authenticators.rb +30 -10
- data/lib/net/imap/command_data.rb +8 -11
- data/lib/net/imap/data_encoding.rb +104 -8
- data/lib/net/imap/errors.rb +1 -1
- data/lib/net/imap/flags.rb +105 -77
- data/lib/net/imap/response_data.rb +1077 -317
- data/lib/net/imap/response_parser.rb +66 -1
- data/lib/net/imap/sasl/saslprep.rb +55 -0
- data/lib/net/imap/sasl/saslprep_tables.rb +98 -0
- data/lib/net/imap/sasl/stringprep.rb +72 -0
- data/lib/net/imap/sasl/stringprep_tables.rb +153 -0
- data/lib/net/imap/sasl.rb +78 -0
- data/lib/net/imap.rb +1209 -292
- data/net-imap.gemspec +3 -1
- data/rakelib/rdoc.rake +70 -0
- data/rakelib/rfcs.rake +168 -0
- data/rakelib/saslprep.rake +30 -0
- data/rakelib/string_prep_tables_generator.rb +423 -0
- metadata +29 -3
data/lib/net/imap.rb
CHANGED
@@ -23,12 +23,14 @@ end
|
|
23
23
|
|
24
24
|
module Net
|
25
25
|
|
26
|
-
#
|
27
|
-
# Net::IMAP implements Internet Message Access Protocol (IMAP) client
|
26
|
+
# Net::IMAP implements Internet Message Access Protocol (\IMAP) client
|
28
27
|
# functionality. The protocol is described in
|
29
|
-
# [
|
28
|
+
# [IMAP4rev1[https://tools.ietf.org/html/rfc3501]].
|
29
|
+
#--
|
30
|
+
# TODO: and [IMAP4rev2[https://tools.ietf.org/html/rfc9051]].
|
31
|
+
#++
|
30
32
|
#
|
31
|
-
# == IMAP Overview
|
33
|
+
# == \IMAP Overview
|
32
34
|
#
|
33
35
|
# An \IMAP client connects to a server, and then authenticates
|
34
36
|
# itself using either #authenticate or #login. Having
|
@@ -41,12 +43,14 @@ module Net
|
|
41
43
|
# within a hierarchy of directories.
|
42
44
|
#
|
43
45
|
# To work on the messages within a mailbox, the client must
|
44
|
-
# first select that mailbox, using either #select or
|
45
|
-
# read-only access)
|
46
|
-
# selected a mailbox, they enter _selected_ state, and that
|
46
|
+
# first select that mailbox, using either #select or #examine
|
47
|
+
# (for read-only access). Once the client has successfully
|
48
|
+
# selected a mailbox, they enter the "_selected_" state, and that
|
47
49
|
# mailbox becomes the _current_ mailbox, on which mail-item
|
48
50
|
# related commands implicitly operate.
|
49
51
|
#
|
52
|
+
# === Sequence numbers and UIDs
|
53
|
+
#
|
50
54
|
# Messages have two sorts of identifiers: message sequence
|
51
55
|
# numbers and UIDs.
|
52
56
|
#
|
@@ -57,15 +61,31 @@ module Net
|
|
57
61
|
# are expunged from the mailbox, remaining messages have their
|
58
62
|
# sequence numbers "shuffled down" to fill the gaps.
|
59
63
|
#
|
64
|
+
# To avoid sequence number race conditions, servers must not expunge messages
|
65
|
+
# when no command is in progress, nor when responding to #fetch, #store, or
|
66
|
+
# #search. Expunges _may_ be sent during any other command, including
|
67
|
+
# #uid_fetch, #uid_store, and #uid_search. The #noop and #idle commands are
|
68
|
+
# both useful for this side-effect: they allow the server to send all mailbox
|
69
|
+
# updates, including expunges.
|
70
|
+
#
|
60
71
|
# UIDs, on the other hand, are permanently guaranteed not to
|
61
72
|
# identify another message within the same mailbox, even if
|
62
73
|
# the existing message is deleted. UIDs are required to
|
63
74
|
# be assigned in ascending (but not necessarily sequential)
|
64
75
|
# order within a mailbox; this means that if a non-IMAP client
|
65
|
-
# rearranges the order of
|
76
|
+
# rearranges the order of mail items within a mailbox, the
|
66
77
|
# UIDs have to be reassigned. An \IMAP client thus cannot
|
67
78
|
# rearrange message orders.
|
68
79
|
#
|
80
|
+
# === Server capabilities and protocol extensions
|
81
|
+
#
|
82
|
+
# Net::IMAP <em>does not modify its behavior</em> according to server
|
83
|
+
# #capability. Users of the class must check for required capabilities before
|
84
|
+
# issuing commands. Special care should be taken to follow all #capability
|
85
|
+
# requirements for #starttls, #login, and #authenticate.
|
86
|
+
#
|
87
|
+
# See the #capability method for more information.
|
88
|
+
#
|
69
89
|
# == Examples of Usage
|
70
90
|
#
|
71
91
|
# === List sender and subject of all recent messages in the default mailbox
|
@@ -108,7 +128,7 @@ module Net
|
|
108
128
|
#
|
109
129
|
# == Errors
|
110
130
|
#
|
111
|
-
# An IMAP server can send three different types of responses to indicate
|
131
|
+
# An \IMAP server can send three different types of responses to indicate
|
112
132
|
# failure:
|
113
133
|
#
|
114
134
|
# NO:: the attempted command could not be successfully completed. For
|
@@ -116,7 +136,7 @@ module Net
|
|
116
136
|
# the selected mailbox does not exist; etc.
|
117
137
|
#
|
118
138
|
# BAD:: the request from the client does not follow the server's
|
119
|
-
# understanding of the IMAP protocol. This includes attempting
|
139
|
+
# understanding of the \IMAP protocol. This includes attempting
|
120
140
|
# commands from the wrong client state; for instance, attempting
|
121
141
|
# to perform a SEARCH command without having SELECTed a current
|
122
142
|
# mailbox. It can also signal an internal server
|
@@ -150,77 +170,536 @@ module Net
|
|
150
170
|
# between UTF-8 and UTF-16), and Net::IMAP::ResponseParseError is
|
151
171
|
# thrown if a server response is non-parseable.
|
152
172
|
#
|
173
|
+
# == What's here?
|
174
|
+
#
|
175
|
+
# * {Connection control}[rdoc-ref:Net::IMAP@Connection+control+methods]
|
176
|
+
# * {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands]
|
177
|
+
# * {...for any state}[rdoc-ref:Net::IMAP@IMAP+commands+for+any+state]
|
178
|
+
# * {...for the "not authenticated" state}[rdoc-ref:Net::IMAP@IMAP+commands+for+the+-22Not+Authenticated-22+state]
|
179
|
+
# * {...for the "authenticated" state}[rdoc-ref:Net::IMAP@IMAP+commands+for+the+-22Authenticated-22+state]
|
180
|
+
# * {...for the "selected" state}[rdoc-ref:Net::IMAP@IMAP+commands+for+the+-22Selected-22+state]
|
181
|
+
# * {...for the "logout" state}[rdoc-ref:Net::IMAP@IMAP+commands+for+the+-22Logout-22+state]
|
182
|
+
# * {Supported IMAP extensions}[rdoc-ref:Net::IMAP@Supported+IMAP+extensions]
|
183
|
+
# * {Handling server responses}[rdoc-ref:Net::IMAP@Handling+server+responses]
|
184
|
+
#
|
185
|
+
# === Connection control methods
|
186
|
+
#
|
187
|
+
# - Net::IMAP.new: A new client connects immediately and waits for a
|
188
|
+
# successful server greeting before returning the new client object.
|
189
|
+
# - #starttls: Asks the server to upgrade a clear-text connection to use TLS.
|
190
|
+
# - #logout: Tells the server to end the session. Enters the "_logout_" state.
|
191
|
+
# - #disconnect: Disconnects the connection (without sending #logout first).
|
192
|
+
# - #disconnected?: True if the connection has been closed.
|
193
|
+
#
|
194
|
+
# === Core \IMAP commands
|
195
|
+
#
|
196
|
+
# The following commands are defined either by
|
197
|
+
# the [IMAP4rev1[https://tools.ietf.org/html/rfc3501]] base specification, or
|
198
|
+
# by one of the following extensions:
|
199
|
+
# [IDLE[https://tools.ietf.org/html/rfc2177]],
|
200
|
+
# [NAMESPACE[https://tools.ietf.org/html/rfc2342]],
|
201
|
+
# [UNSELECT[https://tools.ietf.org/html/rfc3691]],
|
202
|
+
#--
|
203
|
+
# TODO: [ENABLE[https://tools.ietf.org/html/rfc5161]],
|
204
|
+
# TODO: [LIST-EXTENDED[https://tools.ietf.org/html/rfc5258]],
|
205
|
+
# TODO: [LIST-STATUS[https://tools.ietf.org/html/rfc5819]],
|
206
|
+
#++
|
207
|
+
# [MOVE[https://tools.ietf.org/html/rfc6851]].
|
208
|
+
# These extensions are widely supported by modern IMAP4rev1 servers and have
|
209
|
+
# all been integrated into [IMAP4rev2[https://tools.ietf.org/html/rfc9051]].
|
210
|
+
# <em>Note: Net::IMAP doesn't fully support IMAP4rev2 yet.</em>
|
211
|
+
#
|
212
|
+
#--
|
213
|
+
# TODO: When IMAP4rev2 is supported, add the following to the each of the
|
214
|
+
# appropriate commands below.
|
215
|
+
# Note:: CHECK has been removed from IMAP4rev2.
|
216
|
+
# Note:: LSUB is obsoleted by +LIST-EXTENDED and has been removed from IMAP4rev2.
|
217
|
+
# <em>Some arguments require the +LIST-EXTENDED+ or +IMAP4rev2+ capability.</em>
|
218
|
+
# <em>Requires either the +ENABLE+ or +IMAP4rev2+ capability.</em>
|
219
|
+
# <em>Requires either the +NAMESPACE+ or +IMAP4rev2+ capability.</em>
|
220
|
+
# <em>Requires either the +IDLE+ or +IMAP4rev2+ capability.</em>
|
221
|
+
# <em>Requires either the +UNSELECT+ or +IMAP4rev2+ capability.</em>
|
222
|
+
# <em>Requires either the +UIDPLUS+ or +IMAP4rev2+ capability.</em>
|
223
|
+
# <em>Requires either the +MOVE+ or +IMAP4rev2+ capability.</em>
|
224
|
+
#++
|
225
|
+
#
|
226
|
+
# ==== \IMAP commands for any state
|
227
|
+
#
|
228
|
+
# - #capability: Returns the server's capabilities as an array of strings.
|
229
|
+
#
|
230
|
+
# <em>Capabilities may change after</em> #starttls, #authenticate, or #login
|
231
|
+
# <em>and cached capabilities must be reloaded.</em>
|
232
|
+
# - #noop: Allows the server to send unsolicited untagged #responses.
|
233
|
+
# - #logout: Tells the server to end the session. Enters the "_logout_" state.
|
234
|
+
#
|
235
|
+
# ==== \IMAP commands for the "Not Authenticated" state
|
236
|
+
#
|
237
|
+
# In addition to the universal commands, the following commands are valid in
|
238
|
+
# the "<em>not authenticated</em>" state:
|
239
|
+
#
|
240
|
+
# - #starttls: Upgrades a clear-text connection to use TLS.
|
241
|
+
#
|
242
|
+
# <em>Requires the +STARTTLS+ capability.</em>
|
243
|
+
# - #authenticate: Identifies the client to the server using a {SASL
|
244
|
+
# mechanism}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml].
|
245
|
+
# Enters the "_authenticated_" state.
|
246
|
+
#
|
247
|
+
# <em>Requires the <tt>AUTH=#{mechanism}</tt> capability for the chosen
|
248
|
+
# mechanism.</em>
|
249
|
+
# - #login: Identifies the client to the server using a plain text password.
|
250
|
+
# Using #authenticate is generally preferred. Enters the "_authenticated_"
|
251
|
+
# state.
|
252
|
+
#
|
253
|
+
# <em>The +LOGINDISABLED+ capability</em> <b>must NOT</b> <em>be listed.</em>
|
254
|
+
#
|
255
|
+
# ==== \IMAP commands for the "Authenticated" state
|
256
|
+
#
|
257
|
+
# In addition to the universal commands, the following commands are valid in
|
258
|
+
# the "_authenticated_" state:
|
259
|
+
#
|
260
|
+
#--
|
261
|
+
# - #enable: <em>Not implemented by Net::IMAP, yet.</em>
|
262
|
+
#
|
263
|
+
# <em>Requires the +ENABLE+ capability.</em>
|
264
|
+
#++
|
265
|
+
# - #select: Open a mailbox and enter the "_selected_" state.
|
266
|
+
# - #examine: Open a mailbox read-only, and enter the "_selected_" state.
|
267
|
+
# - #create: Creates a new mailbox.
|
268
|
+
# - #delete: Permanently remove a mailbox.
|
269
|
+
# - #rename: Change the name of a mailbox.
|
270
|
+
# - #subscribe: Adds a mailbox to the "subscribed" set.
|
271
|
+
# - #unsubscribe: Removes a mailbox from the "subscribed" set.
|
272
|
+
# - #list: Returns names and attributes of mailboxes matching a given pattern.
|
273
|
+
# - #namespace: Returns mailbox namespaces, with path prefixes and delimiters.
|
274
|
+
#
|
275
|
+
# <em>Requires the +NAMESPACE+ capability.</em>
|
276
|
+
# - #status: Returns mailbox information, e.g. message count, unseen message
|
277
|
+
# count, +UIDVALIDITY+ and +UIDNEXT+.
|
278
|
+
# - #append: Appends a message to the end of a mailbox.
|
279
|
+
# - #idle: Allows the server to send updates to the client, without the client
|
280
|
+
# needing to poll using #noop.
|
281
|
+
#
|
282
|
+
# <em>Requires the +IDLE+ capability.</em>
|
283
|
+
# - #lsub: Lists mailboxes the user has declared "active" or "subscribed".
|
284
|
+
#--
|
285
|
+
# <em>Replaced by</em> <tt>LIST-EXTENDED</tt> <em>and removed from</em>
|
286
|
+
# +IMAP4rev2+. <em>However, Net::IMAP hasn't implemented</em>
|
287
|
+
# <tt>LIST-EXTENDED</tt> _yet_.
|
288
|
+
#++
|
289
|
+
#
|
290
|
+
# ==== \IMAP commands for the "Selected" state
|
291
|
+
#
|
292
|
+
# In addition to the universal commands and the "authenticated" commands, the
|
293
|
+
# following commands are valid in the "_selected_" state:
|
294
|
+
#
|
295
|
+
# - #close: Closes the mailbox and returns to the "_authenticated_" state,
|
296
|
+
# expunging deleted messages, unless the mailbox was opened as read-only.
|
297
|
+
# - #unselect: Closes the mailbox and returns to the "_authenticated_" state,
|
298
|
+
# without expunging any messages.
|
299
|
+
#
|
300
|
+
# <em>Requires the +UNSELECT+ capability.</em>
|
301
|
+
# - #expunge: Permanently removes messages which have the Deleted flag set.
|
302
|
+
# - #uid_expunge: Restricts #expunge to only remove the specified UIDs.
|
303
|
+
#
|
304
|
+
# <em>Requires the +UIDPLUS+ capability.</em>
|
305
|
+
# - #search, #uid_search: Returns sequence numbers or UIDs of messages that
|
306
|
+
# match the given searching criteria.
|
307
|
+
# - #fetch, #uid_fetch: Returns data associated with a set of messages,
|
308
|
+
# specified by sequence number or UID.
|
309
|
+
# - #store, #uid_store: Alters a message's flags.
|
310
|
+
# - #copy, #uid_copy: Copies the specified messages to the end of the
|
311
|
+
# specified destination mailbox.
|
312
|
+
# - #move, #uid_move: Moves the specified messages to the end of the
|
313
|
+
# specified destination mailbox, expunging them from the current mailbox.
|
314
|
+
#
|
315
|
+
# <em>Requires the +MOVE+ capability.</em>
|
316
|
+
# - #check: Mostly obsolete. Can be replaced with #noop or #idle.
|
317
|
+
#--
|
318
|
+
# <em>Removed from IMAP4rev2.</em>
|
319
|
+
#++
|
320
|
+
#
|
321
|
+
# ==== \IMAP commands for the "Logout" state
|
322
|
+
#
|
323
|
+
# No \IMAP commands are valid in the +logout+ state. If the socket is still
|
324
|
+
# open, Net::IMAP will close it after receiving server confirmation.
|
325
|
+
# Exceptions will be raised by \IMAP commands that have already started and
|
326
|
+
# are waiting for a response, as well as any that are called after logout.
|
327
|
+
#
|
328
|
+
# === Supported \IMAP extensions
|
329
|
+
#
|
330
|
+
# ==== RFC9051: +IMAP4rev2+
|
331
|
+
#
|
332
|
+
# Although IMAP4rev2[https://tools.ietf.org/html/rfc9051] is <em>not supported
|
333
|
+
# yet</em>, Net::IMAP supports several extensions that have been folded into
|
334
|
+
# it: +IDLE+, +MOVE+, +NAMESPACE+, +UIDPLUS+, and +UNSELECT+.
|
335
|
+
#--
|
336
|
+
# TODO: RFC4466, ABNF extensions (automatic support for other extensions)
|
337
|
+
# TODO: +ESEARCH+, ExtendedSearchData
|
338
|
+
# TODO: +SEARCHRES+,
|
339
|
+
# TODO: +ENABLE+,
|
340
|
+
# TODO: +SASL-IR+,
|
341
|
+
# TODO: +LIST-EXTENDED+,
|
342
|
+
# TODO: +LIST-STATUS+,
|
343
|
+
# TODO: +LITERAL-+,
|
344
|
+
# TODO: +BINARY+ (only the FETCH side)
|
345
|
+
# TODO: +SPECIAL-USE+
|
346
|
+
# implicitly supported, but we can do better: Response codes: RFC5530, etc
|
347
|
+
# implicitly supported, but we can do better: <tt>STATUS=SIZE</tt>
|
348
|
+
# implicitly supported, but we can do better: <tt>STATUS DELETED</tt>
|
349
|
+
#++
|
350
|
+
# Commands for these extensions are included with the {Core IMAP
|
351
|
+
# commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands], above. Other supported
|
352
|
+
# extensons are listed below.
|
353
|
+
#
|
354
|
+
# ==== RFC2087: +QUOTA+
|
355
|
+
# - #getquota: returns the resource usage and limits for a quota root
|
356
|
+
# - #getquotaroot: returns the list of quota roots for a mailbox, as well as
|
357
|
+
# their resource usage and limits.
|
358
|
+
# - #setquota: sets the resource limits for a given quota root.
|
359
|
+
#
|
360
|
+
# ==== RFC2177: +IDLE+
|
361
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], so it is also
|
362
|
+
# listed with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
|
363
|
+
# - #idle: Allows the server to send updates to the client, without the client
|
364
|
+
# needing to poll using #noop.
|
365
|
+
#
|
366
|
+
# ==== RFC2342: +NAMESPACE+
|
367
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], so it is also
|
368
|
+
# listed with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
|
369
|
+
# - #namespace: Returns mailbox namespaces, with path prefixes and delimiters.
|
370
|
+
#
|
371
|
+
# ==== RFC2971: +ID+
|
372
|
+
# - #id: exchanges client and server implementation information.
|
373
|
+
#
|
374
|
+
#--
|
375
|
+
# ==== RFC3502: +MULTIAPPEND+
|
376
|
+
# TODO...
|
377
|
+
#++
|
378
|
+
#
|
379
|
+
#--
|
380
|
+
# ==== RFC3516: +BINARY+
|
381
|
+
# TODO...
|
382
|
+
#++
|
383
|
+
#
|
384
|
+
# ==== RFC3691: +UNSELECT+
|
385
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], so it is also
|
386
|
+
# listed with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
|
387
|
+
# - #unselect: Closes the mailbox and returns to the "_authenticated_" state,
|
388
|
+
# without expunging any messages.
|
389
|
+
#
|
390
|
+
# ==== RFC4314: +ACL+
|
391
|
+
# - #getacl: lists the authenticated user's access rights to a mailbox.
|
392
|
+
# - #setacl: sets the access rights for a user on a mailbox
|
393
|
+
#--
|
394
|
+
# TODO: #deleteacl, #listrights, #myrights
|
395
|
+
#++
|
396
|
+
# - *_Note:_* +DELETEACL+, +LISTRIGHTS+, and +MYRIGHTS+ are not supported yet.
|
397
|
+
#
|
398
|
+
# ==== RFC4315: +UIDPLUS+
|
399
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], so it is also
|
400
|
+
# listed with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
|
401
|
+
# - #uid_expunge: Restricts #expunge to only remove the specified UIDs.
|
402
|
+
# - Updates #select, #examine with the +UIDNOTSTICKY+ ResponseCode
|
403
|
+
# - Updates #append with the +APPENDUID+ ResponseCode
|
404
|
+
# - Updates #copy, #move with the +COPYUID+ ResponseCode
|
405
|
+
#
|
406
|
+
#--
|
407
|
+
# ==== RFC4466: Collected Extensions to IMAP4 ABNF
|
408
|
+
# TODO...
|
409
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], this RFC updates
|
410
|
+
# the protocol to enable new optional parameters to many commands: #select,
|
411
|
+
# #examine, #create, #rename, #fetch, #uid_fetch, #store, #uid_store, #search,
|
412
|
+
# #uid_search, and #append. However, specific parameters are not defined.
|
413
|
+
# Extensions to these commands use this syntax whenever possible. Net::IMAP
|
414
|
+
# may be partially compatible with extensions to these commands, even without
|
415
|
+
# any explicit support.
|
416
|
+
#++
|
417
|
+
#
|
418
|
+
#--
|
419
|
+
# ==== RFC4731 +ESEARCH+
|
420
|
+
# TODO...
|
421
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
|
422
|
+
# - Updates #search, #uid_search to accept result options: +MIN+, +MAX+,
|
423
|
+
# +ALL+, +COUNT+, and to return ExtendedSearchData.
|
424
|
+
#++
|
425
|
+
#
|
426
|
+
#--
|
427
|
+
# ==== RFC4959: +SASL-IR+
|
428
|
+
# TODO...
|
429
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
|
430
|
+
# - Updates #authenticate to reduce round-trips for supporting mechanisms.
|
431
|
+
#++
|
432
|
+
#
|
433
|
+
#--
|
434
|
+
# ==== RFC4978: COMPRESS=DEFLATE
|
435
|
+
# TODO...
|
436
|
+
#++
|
437
|
+
#
|
438
|
+
#--
|
439
|
+
# ==== RFC5182 +SEARCHRES+
|
440
|
+
# TODO...
|
441
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
|
442
|
+
# - Updates #search, #uid_search with the +SAVE+ result option.
|
443
|
+
# - Updates #copy, #uid_copy, #fetch, #uid_fetch, #move, #uid_move, #search,
|
444
|
+
# #uid_search, #store, #uid_store, and #uid_expunge with ability to
|
445
|
+
# reference the saved result of a previous #search or #uid_search command.
|
446
|
+
#++
|
447
|
+
#
|
448
|
+
# ==== RFC5256: +SORT+
|
449
|
+
# - #sort, #uid_sort: An alternate version of #search or #uid_search which
|
450
|
+
# sorts the results by specified keys.
|
451
|
+
# ==== RFC5256: +THREAD+
|
452
|
+
# - #thread, #uid_thread: An alternate version of #search or #uid_search,
|
453
|
+
# which arranges the results into ordered groups or threads according to a
|
454
|
+
# chosen algorithm.
|
455
|
+
#
|
456
|
+
#--
|
457
|
+
# ==== RFC5258 +LIST-EXTENDED+
|
458
|
+
# TODO...
|
459
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], this updates the
|
460
|
+
# protocol with new optional parameters to the #list command, adding a few of
|
461
|
+
# its own. Net::IMAP may be forward-compatible with future #list extensions,
|
462
|
+
# even without any explicit support.
|
463
|
+
# - Updates #list to accept selection options: +SUBSCRIBED+, +REMOTE+, and
|
464
|
+
# +RECURSIVEMATCH+, and return options: +SUBSCRIBED+ and +CHILDREN+.
|
465
|
+
#++
|
466
|
+
#
|
467
|
+
#--
|
468
|
+
# ==== RFC5819 +LIST-STATUS+
|
469
|
+
# TODO...
|
470
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
|
471
|
+
# - Updates #list with +STATUS+ return option.
|
472
|
+
#++
|
473
|
+
#
|
474
|
+
# ==== +XLIST+ (non-standard, deprecated)
|
475
|
+
# - #xlist: replaced by +SPECIAL-USE+ attributes in #list responses.
|
476
|
+
#
|
477
|
+
#--
|
478
|
+
# ==== RFC6154 +SPECIAL-USE+
|
479
|
+
# TODO...
|
480
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
|
481
|
+
# - Updates #list with the +SPECIAL-USE+ selection and return options.
|
482
|
+
#++
|
483
|
+
#
|
484
|
+
# ==== RFC6851: +MOVE+
|
485
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], so it is also
|
486
|
+
# listed with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
|
487
|
+
# - #move, #uid_move: Moves the specified messages to the end of the
|
488
|
+
# specified destination mailbox, expunging them from the current mailbox.
|
489
|
+
#
|
490
|
+
#--
|
491
|
+
# ==== RFC6855: UTF8=ACCEPT
|
492
|
+
# TODO...
|
493
|
+
# ==== RFC6855: UTF8=ONLY
|
494
|
+
# TODO...
|
495
|
+
#++
|
496
|
+
#
|
497
|
+
#--
|
498
|
+
# ==== RFC7888: <tt>LITERAL+</tt>, +LITERAL-+
|
499
|
+
# TODO...
|
500
|
+
# ==== RFC7162: +QRESYNC+
|
501
|
+
# TODO...
|
502
|
+
# ==== RFC7162: +CONDSTORE+
|
503
|
+
# TODO...
|
504
|
+
# ==== RFC8474: +OBJECTID+
|
505
|
+
# TODO...
|
506
|
+
# ==== RFC9208: +QUOTA+
|
507
|
+
# TODO...
|
508
|
+
#++
|
509
|
+
#
|
510
|
+
# === Handling server responses
|
511
|
+
#
|
512
|
+
# - #greeting: The server's initial untagged response, which can indicate a
|
513
|
+
# pre-authenticated connection.
|
514
|
+
# - #responses: A hash with arrays of unhandled <em>non-+nil+</em>
|
515
|
+
# UntaggedResponse and ResponseCode +#data+, keyed by +#name+.
|
516
|
+
# - #add_response_handler: Add a block to be called inside the receiver thread
|
517
|
+
# with every server response.
|
518
|
+
# - #remove_response_handler: Remove a previously added response handler.
|
519
|
+
#
|
153
520
|
#
|
154
521
|
# == References
|
522
|
+
#--
|
523
|
+
# TODO: Consider moving references list to REFERENCES.md or REFERENCES.rdoc.
|
524
|
+
#++
|
155
525
|
#
|
156
|
-
# [[
|
157
|
-
#
|
158
|
-
#
|
159
|
-
#
|
526
|
+
# [{IMAP4rev1}[https://www.rfc-editor.org/rfc/rfc3501.html]]::
|
527
|
+
# Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - \VERSION 4rev1",
|
528
|
+
# RFC 3501, DOI 10.17487/RFC3501, March 2003,
|
529
|
+
# <https://www.rfc-editor.org/info/rfc3501>.
|
160
530
|
#
|
161
|
-
# [
|
162
|
-
#
|
163
|
-
#
|
164
|
-
#
|
165
|
-
# RFC-3066[https://tools.ietf.org/html/rfc3066], January 2001,
|
166
|
-
# RFC-4646[https://tools.ietf.org/html/rfc4646], September 2006, and
|
167
|
-
# RFC-1766[https://tools.ietf.org/html/rfc1766], March 1995.)
|
531
|
+
# [IMAP-ABNF-EXT[https://www.rfc-editor.org/rfc/rfc4466.html]]::
|
532
|
+
# Melnikov, A. and C. Daboo, "Collected Extensions to IMAP4 ABNF",
|
533
|
+
# RFC 4466, DOI 10.17487/RFC4466, April 2006,
|
534
|
+
# <https://www.rfc-editor.org/info/rfc4466>.
|
168
535
|
#
|
169
|
-
#
|
170
|
-
#
|
171
|
-
#
|
536
|
+
# <em>Note: Net::IMAP cannot parse the entire RFC4466 grammar yet.</em>
|
537
|
+
#
|
538
|
+
# [{IMAP4rev2}[https://www.rfc-editor.org/rfc/rfc9051.html]]::
|
539
|
+
# Melnikov, A., Ed., and B. Leiba, Ed., "Internet Message Access Protocol
|
540
|
+
# (\IMAP) - Version 4rev2", RFC 9051, DOI 10.17487/RFC9051, August 2021,
|
541
|
+
# <https://www.rfc-editor.org/info/rfc9051>.
|
542
|
+
#
|
543
|
+
# <em>Note: Net::IMAP is not fully compatible with IMAP4rev2 yet.</em>
|
544
|
+
#
|
545
|
+
# [IMAP-IMPLEMENTATION[https://www.rfc-editor.org/info/rfc2683]]::
|
546
|
+
# Leiba, B., "IMAP4 Implementation Recommendations",
|
547
|
+
# RFC 2683, DOI 10.17487/RFC2683, September 1999,
|
548
|
+
# <https://www.rfc-editor.org/info/rfc2683>.
|
172
549
|
#
|
173
|
-
# [
|
174
|
-
#
|
175
|
-
#
|
176
|
-
# RFC-2045[https://tools.ietf.org/html/rfc2045], November 1996.
|
550
|
+
# [IMAP-MULTIACCESS[https://www.rfc-editor.org/info/rfc2180]]::
|
551
|
+
# Gahrns, M., "IMAP4 Multi-Accessed Mailbox Practice", RFC 2180, DOI
|
552
|
+
# 10.17487/RFC2180, July 1997, <https://www.rfc-editor.org/info/rfc2180>.
|
177
553
|
#
|
178
|
-
# [[
|
179
|
-
#
|
180
|
-
#
|
181
|
-
#
|
182
|
-
# RFC-2822[https://tools.ietf.org/html/rfc2822], April 2001, and
|
183
|
-
# RFC-822[https://tools.ietf.org/html/rfc822], August 1982.)
|
554
|
+
# [UTF7[https://tools.ietf.org/html/rfc2152]]::
|
555
|
+
# Goldsmith, D. and M. Davis, "UTF-7 A Mail-Safe Transformation Format of
|
556
|
+
# Unicode", RFC 2152, DOI 10.17487/RFC2152, May 1997,
|
557
|
+
# <https://www.rfc-editor.org/info/rfc2152>.
|
184
558
|
#
|
185
|
-
#
|
186
|
-
# Myers, J., "IMAP4 QUOTA extension",
|
187
|
-
# RFC-2087[https://tools.ietf.org/html/rfc2087], January 1997.
|
559
|
+
# === Message envelope and body structure
|
188
560
|
#
|
189
|
-
# [[
|
190
|
-
#
|
191
|
-
#
|
561
|
+
# [RFC5322[https://tools.ietf.org/html/rfc5322]]::
|
562
|
+
# Resnick, P., Ed., "Internet Message Format",
|
563
|
+
# RFC 5322, DOI 10.17487/RFC5322, October 2008,
|
564
|
+
# <https://www.rfc-editor.org/info/rfc5322>.
|
192
565
|
#
|
193
|
-
#
|
194
|
-
#
|
195
|
-
#
|
566
|
+
# <em>Note: obsoletes</em>
|
567
|
+
# RFC-2822[https://tools.ietf.org/html/rfc2822]<em> (April 2001) and</em>
|
568
|
+
# RFC-822[https://tools.ietf.org/html/rfc822]<em> (August 1982).</em>
|
196
569
|
#
|
197
|
-
# [[
|
198
|
-
#
|
199
|
-
#
|
200
|
-
#
|
570
|
+
# [CHARSET[https://tools.ietf.org/html/rfc2978]]::
|
571
|
+
# Freed, N. and J. Postel, "IANA Charset Registration Procedures", BCP 19,
|
572
|
+
# RFC 2978, DOI 10.17487/RFC2978, October 2000,
|
573
|
+
# <https://www.rfc-editor.org/info/rfc2978>.
|
201
574
|
#
|
202
|
-
# [[
|
203
|
-
#
|
204
|
-
#
|
205
|
-
#
|
575
|
+
# [DISPOSITION[https://tools.ietf.org/html/rfc2183]]::
|
576
|
+
# Troost, R., Dorner, S., and K. Moore, Ed., "Communicating Presentation
|
577
|
+
# Information in Internet Messages: The Content-Disposition Header
|
578
|
+
# Field", RFC 2183, DOI 10.17487/RFC2183, August 1997,
|
579
|
+
# <https://www.rfc-editor.org/info/rfc2183>.
|
206
580
|
#
|
207
|
-
# [
|
208
|
-
#
|
209
|
-
#
|
210
|
-
#
|
581
|
+
# [MIME-IMB[https://tools.ietf.org/html/rfc2045]]::
|
582
|
+
# Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions
|
583
|
+
# (MIME) Part One: Format of Internet Message Bodies",
|
584
|
+
# RFC 2045, DOI 10.17487/RFC2045, November 1996,
|
585
|
+
# <https://www.rfc-editor.org/info/rfc2045>.
|
211
586
|
#
|
212
|
-
# [[
|
213
|
-
#
|
587
|
+
# [MIME-IMT[https://tools.ietf.org/html/rfc2046]]::
|
588
|
+
# Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions
|
589
|
+
# (MIME) Part Two: Media Types", RFC 2046, DOI 10.17487/RFC2046,
|
590
|
+
# November 1996, <https://www.rfc-editor.org/info/rfc2046>.
|
214
591
|
#
|
215
|
-
# [[
|
216
|
-
#
|
592
|
+
# [MIME-HDRS[https://tools.ietf.org/html/rfc2047]]::
|
593
|
+
# Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part Three:
|
594
|
+
# Message Header Extensions for Non-ASCII Text",
|
595
|
+
# RFC 2047, DOI 10.17487/RFC2047, November 1996,
|
596
|
+
# <https://www.rfc-editor.org/info/rfc2047>.
|
217
597
|
#
|
218
|
-
# [[
|
219
|
-
#
|
220
|
-
#
|
598
|
+
# [RFC2231[https://tools.ietf.org/html/rfc2231]]::
|
599
|
+
# Freed, N. and K. Moore, "MIME Parameter Value and Encoded Word
|
600
|
+
# Extensions: Character Sets, Languages, and Continuations",
|
601
|
+
# RFC 2231, DOI 10.17487/RFC2231, November 1997,
|
602
|
+
# <https://www.rfc-editor.org/info/rfc2231>.
|
603
|
+
#
|
604
|
+
# [I18n-HDRS[https://tools.ietf.org/html/rfc6532]]::
|
605
|
+
# Yang, A., Steele, S., and N. Freed, "Internationalized Email Headers",
|
606
|
+
# RFC 6532, DOI 10.17487/RFC6532, February 2012,
|
607
|
+
# <https://www.rfc-editor.org/info/rfc6532>.
|
608
|
+
#
|
609
|
+
# [LANGUAGE-TAGS[https://www.rfc-editor.org/info/rfc3282]]::
|
610
|
+
# Alvestrand, H., "Content Language Headers",
|
611
|
+
# RFC 3282, DOI 10.17487/RFC3282, May 2002,
|
612
|
+
# <https://www.rfc-editor.org/info/rfc3282>.
|
613
|
+
#
|
614
|
+
# [LOCATION[https://www.rfc-editor.org/info/rfc2557]]::
|
615
|
+
# Palme, J., Hopmann, A., and N. Shelness, "MIME Encapsulation of
|
616
|
+
# Aggregate Documents, such as HTML (MHTML)",
|
617
|
+
# RFC 2557, DOI 10.17487/RFC2557, March 1999,
|
618
|
+
# <https://www.rfc-editor.org/info/rfc2557>.
|
619
|
+
#
|
620
|
+
# [MD5[https://tools.ietf.org/html/rfc1864]]::
|
621
|
+
# Myers, J. and M. Rose, "The Content-MD5 Header Field",
|
622
|
+
# RFC 1864, DOI 10.17487/RFC1864, October 1995,
|
623
|
+
# <https://www.rfc-editor.org/info/rfc1864>.
|
624
|
+
#
|
625
|
+
#--
|
626
|
+
# TODO: Document IMAP keywords.
|
627
|
+
#
|
628
|
+
# [RFC3503[https://tools.ietf.org/html/rfc3503]]
|
629
|
+
# Melnikov, A., "Message Disposition Notification (MDN)
|
630
|
+
# profile for Internet Message Access Protocol (IMAP)",
|
631
|
+
# RFC 3503, DOI 10.17487/RFC3503, March 2003,
|
632
|
+
# <https://www.rfc-editor.org/info/rfc3503>.
|
633
|
+
#++
|
634
|
+
#
|
635
|
+
# === Supported \IMAP Extensions
|
636
|
+
#
|
637
|
+
# [QUOTA[https://tools.ietf.org/html/rfc2087]]::
|
638
|
+
# Myers, J., "IMAP4 QUOTA extension", RFC 2087, DOI 10.17487/RFC2087,
|
639
|
+
# January 1997, <https://www.rfc-editor.org/info/rfc2087>.
|
640
|
+
#--
|
641
|
+
# TODO: test compatibility with updated QUOTA extension:
|
642
|
+
# [QUOTA[https://tools.ietf.org/html/rfc9208]]::
|
643
|
+
# Melnikov, A., "IMAP QUOTA Extension", RFC 9208, DOI 10.17487/RFC9208,
|
644
|
+
# March 2022, <https://www.rfc-editor.org/info/rfc9208>.
|
645
|
+
#++
|
646
|
+
# [IDLE[https://tools.ietf.org/html/rfc2177]]::
|
647
|
+
# Leiba, B., "IMAP4 IDLE command", RFC 2177, DOI 10.17487/RFC2177,
|
648
|
+
# June 1997, <https://www.rfc-editor.org/info/rfc2177>.
|
649
|
+
# [NAMESPACE[https://tools.ietf.org/html/rfc2342]]::
|
650
|
+
# Gahrns, M. and C. Newman, "IMAP4 Namespace", RFC 2342,
|
651
|
+
# DOI 10.17487/RFC2342, May 1998, <https://www.rfc-editor.org/info/rfc2342>.
|
652
|
+
# [ID[https://tools.ietf.org/html/rfc2971]]::
|
653
|
+
# Showalter, T., "IMAP4 ID extension", RFC 2971, DOI 10.17487/RFC2971,
|
654
|
+
# October 2000, <https://www.rfc-editor.org/info/rfc2971>.
|
655
|
+
# [ACL[https://tools.ietf.org/html/rfc4314]]::
|
656
|
+
# Melnikov, A., "IMAP4 Access Control List (ACL) Extension", RFC 4314,
|
657
|
+
# DOI 10.17487/RFC4314, December 2005,
|
658
|
+
# <https://www.rfc-editor.org/info/rfc4314>.
|
659
|
+
# [UIDPLUS[https://www.rfc-editor.org/rfc/rfc4315.html]]::
|
660
|
+
# Crispin, M., "Internet Message Access Protocol (\IMAP) - UIDPLUS
|
661
|
+
# extension", RFC 4315, DOI 10.17487/RFC4315, December 2005,
|
662
|
+
# <https://www.rfc-editor.org/info/rfc4315>.
|
663
|
+
# [SORT[https://tools.ietf.org/html/rfc5256]]::
|
664
|
+
# Crispin, M. and K. Murchison, "Internet Message Access Protocol - SORT and
|
665
|
+
# THREAD Extensions", RFC 5256, DOI 10.17487/RFC5256, June 2008,
|
666
|
+
# <https://www.rfc-editor.org/info/rfc5256>.
|
667
|
+
# [THREAD[https://tools.ietf.org/html/rfc5256]]::
|
668
|
+
# Crispin, M. and K. Murchison, "Internet Message Access Protocol - SORT and
|
669
|
+
# THREAD Extensions", RFC 5256, DOI 10.17487/RFC5256, June 2008,
|
670
|
+
# <https://www.rfc-editor.org/info/rfc5256>.
|
671
|
+
# [RFC5530[https://www.rfc-editor.org/rfc/rfc5530.html]]::
|
672
|
+
# Gulbrandsen, A., "IMAP Response Codes", RFC 5530, DOI 10.17487/RFC5530,
|
673
|
+
# May 2009, <https://www.rfc-editor.org/info/rfc5530>.
|
674
|
+
# [MOVE[https://tools.ietf.org/html/rfc6851]]::
|
675
|
+
# Gulbrandsen, A. and N. Freed, Ed., "Internet Message Access Protocol
|
676
|
+
# (\IMAP) - MOVE Extension", RFC 6851, DOI 10.17487/RFC6851, January 2013,
|
677
|
+
# <https://www.rfc-editor.org/info/rfc6851>.
|
678
|
+
#
|
679
|
+
# === IANA registries
|
680
|
+
#
|
681
|
+
# * {IMAP Capabilities}[http://www.iana.org/assignments/imap4-capabilities]
|
682
|
+
# * {IMAP Response Codes}[https://www.iana.org/assignments/imap-response-codes/imap-response-codes.xhtml]
|
683
|
+
# * {IMAP Mailbox Name Attributes}[https://www.iana.org/assignments/imap-mailbox-name-attributes/imap-mailbox-name-attributes.xhtml]
|
684
|
+
# * {IMAP and JMAP Keywords}[https://www.iana.org/assignments/imap-jmap-keywords/imap-jmap-keywords.xhtml]
|
685
|
+
# * {IMAP Threading Algorithms}[https://www.iana.org/assignments/imap-threading-algorithms/imap-threading-algorithms.xhtml]
|
686
|
+
#--
|
687
|
+
# * {IMAP Quota Resource Types}[http://www.iana.org/assignments/imap4-capabilities#imap-capabilities-2]
|
688
|
+
# * [{LIST-EXTENDED options and responses}[https://www.iana.org/assignments/imap-list-extended/imap-list-extended.xhtml]
|
689
|
+
# * {IMAP METADATA Server Entry and Mailbox Entry Registries}[https://www.iana.org/assignments/imap-metadata/imap-metadata.xhtml]
|
690
|
+
# * {IMAP ANNOTATE Extension Entries and Attributes}[https://www.iana.org/assignments/imap-annotate-extension/imap-annotate-extension.xhtml]
|
691
|
+
# * {IMAP URLAUTH Access Identifiers and Prefixes}[https://www.iana.org/assignments/urlauth-access-ids/urlauth-access-ids.xhtml]
|
692
|
+
# * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
|
693
|
+
#++
|
694
|
+
# * {SASL Mechanisms and SASL SCRAM Family Mechanisms}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml]
|
695
|
+
# * {Service Name and Transport Protocol Port Number Registry}[https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml]:
|
696
|
+
# +imap+: tcp/143, +imaps+: tcp/993
|
697
|
+
# * {GSSAPI/Kerberos/SASL Service Names}[https://www.iana.org/assignments/gssapi-service-names/gssapi-service-names.xhtml]:
|
698
|
+
# +imap+
|
699
|
+
# * {Character sets}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
|
221
700
|
#
|
222
701
|
class IMAP < Protocol
|
223
|
-
VERSION = "0.3.
|
702
|
+
VERSION = "0.3.7"
|
224
703
|
|
225
704
|
include MonitorMixin
|
226
705
|
if defined?(OpenSSL::SSL)
|
@@ -228,10 +707,14 @@ module Net
|
|
228
707
|
include SSL
|
229
708
|
end
|
230
709
|
|
231
|
-
#
|
710
|
+
# Returns the initial greeting the server, an UntaggedResponse.
|
232
711
|
attr_reader :greeting
|
233
712
|
|
234
|
-
# Returns
|
713
|
+
# Returns a hash with arrays of unhandled <em>non-+nil+</em>
|
714
|
+
# UntaggedResponse#data keyed by UntaggedResponse#name, and
|
715
|
+
# ResponseCode#data keyed by ResponseCode#name.
|
716
|
+
#
|
717
|
+
# For example:
|
235
718
|
#
|
236
719
|
# imap.select("inbox")
|
237
720
|
# p imap.responses["EXISTS"][-1]
|
@@ -251,8 +734,7 @@ module Net
|
|
251
734
|
# Seconds to wait until an IDLE response is received.
|
252
735
|
attr_reader :idle_response_timeout
|
253
736
|
|
254
|
-
|
255
|
-
attr_accessor :client_thread
|
737
|
+
attr_accessor :client_thread # :nodoc:
|
256
738
|
|
257
739
|
# Returns the debug mode.
|
258
740
|
def self.debug
|
@@ -281,6 +763,8 @@ module Net
|
|
281
763
|
end
|
282
764
|
|
283
765
|
# Disconnects from the server.
|
766
|
+
#
|
767
|
+
# Related: #logout
|
284
768
|
def disconnect
|
285
769
|
return if disconnected?
|
286
770
|
begin
|
@@ -304,20 +788,64 @@ module Net
|
|
304
788
|
end
|
305
789
|
|
306
790
|
# Returns true if disconnected from the server.
|
791
|
+
#
|
792
|
+
# Related: #logout, #disconnect
|
307
793
|
def disconnected?
|
308
794
|
return @sock.closed?
|
309
795
|
end
|
310
796
|
|
311
|
-
# Sends a CAPABILITY command
|
312
|
-
# capabilities that the server supports. Each
|
313
|
-
# is a string.
|
314
|
-
#
|
797
|
+
# Sends a {CAPABILITY command [IMAP4rev1 §6.1.1]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.1.1]
|
798
|
+
# and returns an array of capabilities that the server supports. Each
|
799
|
+
# capability is a string.
|
800
|
+
#
|
801
|
+
# See the {IANA IMAP4 capabilities
|
802
|
+
# registry}[http://www.iana.org/assignments/imap4-capabilities] for a list
|
803
|
+
# of all standard capabilities, and their reference RFCs.
|
804
|
+
#
|
805
|
+
# >>>
|
806
|
+
# <em>*Note* that Net::IMAP does not currently modify its
|
807
|
+
# behaviour according to the capabilities of the server;
|
808
|
+
# it is up to the user of the class to ensure that
|
809
|
+
# a certain capability is supported by a server before
|
810
|
+
# using it.</em>
|
811
|
+
#
|
812
|
+
# Capability requirements—other than +IMAP4rev1+—are listed in the
|
813
|
+
# documentation for each command method.
|
814
|
+
#
|
815
|
+
# ===== Basic IMAP4rev1 capabilities
|
816
|
+
#
|
817
|
+
# All IMAP4rev1 servers must include +IMAP4rev1+ in their capabilities list.
|
818
|
+
# All IMAP4rev1 servers must _implement_ the +STARTTLS+,
|
819
|
+
# <tt>AUTH=PLAIN</tt>, and +LOGINDISABLED+ capabilities, and clients must
|
820
|
+
# respect their presence or absence. See the capabilites requirements on
|
821
|
+
# #starttls, #login, and #authenticate.
|
822
|
+
#
|
823
|
+
# ===== Using IMAP4rev1 extensions
|
824
|
+
#
|
825
|
+
# IMAP4rev1 servers must not activate incompatible behavior until an
|
826
|
+
# explicit client action invokes a capability, e.g. sending a command or
|
827
|
+
# command argument specific to that capability. Extensions with backward
|
828
|
+
# compatible behavior, such as response codes or mailbox attributes, may
|
829
|
+
# be sent at any time.
|
830
|
+
#
|
831
|
+
# Invoking capabilities which are unknown to Net::IMAP may cause unexpected
|
832
|
+
# behavior and errors, for example ResponseParseError is raised when unknown
|
833
|
+
# response syntax is received. Invoking commands or command parameters that
|
834
|
+
# are unsupported by the server may raise NoResponseError, BadResponseError,
|
835
|
+
# or cause other unexpected behavior.
|
836
|
+
#
|
837
|
+
# ===== Caching +CAPABILITY+ responses
|
838
|
+
#
|
839
|
+
# Servers may send their capability list, unsolicited, using the
|
840
|
+
# +CAPABILITY+ response code or an untagged +CAPABILITY+ response. These
|
841
|
+
# responses can be retrieved and cached using #responses or
|
842
|
+
# #add_response_handler.
|
843
|
+
#
|
844
|
+
# But cached capabilities _must_ be discarded after #starttls, #login, or
|
845
|
+
# #authenticate. The OK TaggedResponse to #login and #authenticate may
|
846
|
+
# include +CAPABILITY+ response code data, but the TaggedResponse for
|
847
|
+
# #starttls is sent clear-text and cannot be trusted.
|
315
848
|
#
|
316
|
-
# Note that the Net::IMAP class does not modify its
|
317
|
-
# behaviour according to the capabilities of the server;
|
318
|
-
# it is up to the user of the class to ensure that
|
319
|
-
# a certain capability is supported by a server before
|
320
|
-
# using it.
|
321
849
|
def capability
|
322
850
|
synchronize do
|
323
851
|
send_command("CAPABILITY")
|
@@ -325,8 +853,9 @@ module Net
|
|
325
853
|
end
|
326
854
|
end
|
327
855
|
|
328
|
-
# Sends an ID command
|
329
|
-
# response, or nil if the server does not
|
856
|
+
# Sends an {ID command [RFC2971 §3.1]}[https://www.rfc-editor.org/rfc/rfc2971#section-3.1]
|
857
|
+
# and returns a hash of the server's response, or nil if the server does not
|
858
|
+
# identify itself.
|
330
859
|
#
|
331
860
|
# Note that the user should first check if the server supports the ID
|
332
861
|
# capability. For example:
|
@@ -341,7 +870,12 @@ module Net
|
|
341
870
|
# )
|
342
871
|
# end
|
343
872
|
#
|
344
|
-
# See [
|
873
|
+
# See [ID[https://tools.ietf.org/html/rfc2971]] for field definitions.
|
874
|
+
#
|
875
|
+
# ===== Capabilities
|
876
|
+
#
|
877
|
+
# The server's capabilities must include +ID+
|
878
|
+
# [RFC2971[https://tools.ietf.org/html/rfc2971]]
|
345
879
|
def id(client_id=nil)
|
346
880
|
synchronize do
|
347
881
|
send_command("ID", ClientID.new(client_id))
|
@@ -349,18 +883,60 @@ module Net
|
|
349
883
|
end
|
350
884
|
end
|
351
885
|
|
352
|
-
# Sends a NOOP command
|
886
|
+
# Sends a {NOOP command [IMAP4rev1 §6.1.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.1.2]
|
887
|
+
# to the server.
|
888
|
+
#
|
889
|
+
# This allows the server to send unsolicited untagged EXPUNGE #responses,
|
890
|
+
# but does not execute any client request. \IMAP servers are permitted to
|
891
|
+
# send unsolicited untagged responses at any time, except for `EXPUNGE`.
|
892
|
+
#
|
893
|
+
# * +EXPUNGE+ can only be sent while a command is in progress.
|
894
|
+
# * +EXPUNGE+ must _not_ be sent during #fetch, #store, or #search.
|
895
|
+
# * +EXPUNGE+ may be sent during #uid_fetch, #uid_store, or #uid_search.
|
896
|
+
#
|
897
|
+
# Related: #idle, #check
|
353
898
|
def noop
|
354
899
|
send_command("NOOP")
|
355
900
|
end
|
356
901
|
|
357
|
-
# Sends a LOGOUT command
|
358
|
-
#
|
902
|
+
# Sends a {LOGOUT command [IMAP4rev1 §6.1.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.1.3]
|
903
|
+
# to inform the command to inform the server that the client is done with
|
904
|
+
# the connection.
|
905
|
+
#
|
906
|
+
# Related: #disconnect
|
359
907
|
def logout
|
360
908
|
send_command("LOGOUT")
|
361
909
|
end
|
362
910
|
|
363
|
-
# Sends a STARTTLS command
|
911
|
+
# Sends a {STARTTLS command [IMAP4rev1 §6.2.1]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.2.1]
|
912
|
+
# to start a TLS session.
|
913
|
+
#
|
914
|
+
# Any +options+ are forwarded to OpenSSL::SSL::SSLContext#set_params.
|
915
|
+
#
|
916
|
+
# This method returns after TLS negotiation and hostname verification are
|
917
|
+
# both successful. Any error indicates that the connection has not been
|
918
|
+
# secured.
|
919
|
+
#
|
920
|
+
# *Note:*
|
921
|
+
# >>>
|
922
|
+
# Any #response_handlers added before STARTTLS should be aware that the
|
923
|
+
# TaggedResponse to STARTTLS is sent clear-text, _before_ TLS negotiation.
|
924
|
+
# TLS negotiation starts immediately after that response.
|
925
|
+
#
|
926
|
+
# Related: Net::IMAP.new, #login, #authenticate
|
927
|
+
#
|
928
|
+
# ===== Capability
|
929
|
+
#
|
930
|
+
# The server's capabilities must include +STARTTLS+.
|
931
|
+
#
|
932
|
+
# Server capabilities may change after #starttls, #login, and #authenticate.
|
933
|
+
# Cached capabilities _must_ be invalidated after this method completes.
|
934
|
+
#
|
935
|
+
# The TaggedResponse to #starttls is sent clear-text, so the server <em>must
|
936
|
+
# *not*</em> send capabilities in the #starttls response and clients <em>must
|
937
|
+
# not</em> use them if they are sent. Servers will generally send an
|
938
|
+
# unsolicited untagged response immeditely _after_ #starttls completes.
|
939
|
+
#
|
364
940
|
def starttls(options = {}, verify = true)
|
365
941
|
send_command("STARTTLS") do |resp|
|
366
942
|
if resp.kind_of?(TaggedResponse) && resp.name == "OK"
|
@@ -375,43 +951,95 @@ module Net
|
|
375
951
|
end
|
376
952
|
end
|
377
953
|
|
378
|
-
#
|
379
|
-
#
|
380
|
-
#
|
381
|
-
#
|
382
|
-
#
|
383
|
-
#
|
384
|
-
#
|
385
|
-
#
|
386
|
-
#
|
387
|
-
#
|
388
|
-
#
|
389
|
-
#
|
390
|
-
#
|
391
|
-
#
|
392
|
-
#
|
393
|
-
#
|
394
|
-
#
|
395
|
-
#
|
396
|
-
#
|
397
|
-
#
|
398
|
-
#
|
399
|
-
#
|
400
|
-
#
|
401
|
-
#
|
402
|
-
#
|
403
|
-
#
|
404
|
-
#
|
405
|
-
#
|
406
|
-
#
|
407
|
-
#
|
408
|
-
#
|
954
|
+
# :call-seq:
|
955
|
+
# authenticate(mechanism, ...) -> ok_resp
|
956
|
+
# authenticate(mech, *creds, **props) {|prop, auth| val } -> ok_resp
|
957
|
+
# authenticate(mechanism, authnid, credentials, authzid=nil) -> ok_resp
|
958
|
+
# authenticate(mechanism, **properties) -> ok_resp
|
959
|
+
# authenticate(mechanism) {|propname, authctx| prop_value } -> ok_resp
|
960
|
+
#
|
961
|
+
# Sends an {AUTHENTICATE command [IMAP4rev1 §6.2.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.2.2]
|
962
|
+
# to authenticate the client. If successful, the connection enters the
|
963
|
+
# "_authenticated_" state.
|
964
|
+
#
|
965
|
+
# +mechanism+ is the name of the \SASL authentication mechanism to be used.
|
966
|
+
# All other arguments are forwarded to the authenticator for the requested
|
967
|
+
# mechanism. The listed call signatures are suggestions. <em>The
|
968
|
+
# documentation for each individual mechanism must be consulted for its
|
969
|
+
# specific parameters.</em>
|
970
|
+
#
|
971
|
+
# An exception Net::IMAP::NoResponseError is raised if authentication fails.
|
972
|
+
#
|
973
|
+
# Related: #login, #starttls
|
974
|
+
#
|
975
|
+
# ==== Supported SASL Mechanisms
|
976
|
+
#
|
977
|
+
# +PLAIN+:: See PlainAuthenticator.
|
978
|
+
# Login using clear-text username and password.
|
979
|
+
#
|
980
|
+
# +XOAUTH2+:: See XOauth2Authenticator.
|
981
|
+
# Login using a username and OAuth2 access token.
|
982
|
+
# Non-standard and obsoleted by +OAUTHBEARER+, but widely
|
983
|
+
# supported.
|
984
|
+
#
|
985
|
+
# >>>
|
986
|
+
# *Deprecated:* <em>Obsolete mechanisms are available for backwards
|
987
|
+
# compatibility.</em>
|
988
|
+
#
|
989
|
+
# For +DIGEST-MD5+ see DigestMD5Authenticator.
|
990
|
+
#
|
991
|
+
# For +LOGIN+, see LoginAuthenticator.
|
992
|
+
#
|
993
|
+
# For +CRAM-MD5+, see CramMD5Authenticator.
|
994
|
+
#
|
995
|
+
# <em>Using a deprecated mechanism will print a warning.</em>
|
996
|
+
#
|
997
|
+
# See Net::IMAP::Authenticators for information on plugging in
|
998
|
+
# authenticators for other mechanisms. See the {SASL mechanism
|
999
|
+
# registry}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml]
|
1000
|
+
# for information on these and other SASL mechanisms.
|
1001
|
+
#
|
1002
|
+
# ===== Capabilities
|
1003
|
+
#
|
1004
|
+
# Clients MUST NOT attempt to authenticate with a mechanism unless
|
1005
|
+
# <tt>"AUTH=#{mechanism}"</tt> for that mechanism is a server capability.
|
1006
|
+
#
|
1007
|
+
# Server capabilities may change after #starttls, #login, and #authenticate.
|
1008
|
+
# Cached capabilities _must_ be invalidated after this method completes.
|
1009
|
+
# The TaggedResponse to #authenticate may include updated capabilities in
|
1010
|
+
# its ResponseCode.
|
1011
|
+
#
|
1012
|
+
# ===== Example
|
1013
|
+
# If the authenticators ignore unhandled keyword arguments, the same config
|
1014
|
+
# can be used for multiple mechanisms:
|
1015
|
+
#
|
1016
|
+
# password = nil # saved locally, so we don't ask more than once
|
1017
|
+
# accesstok = nil # saved locally...
|
1018
|
+
# creds = {
|
1019
|
+
# authcid: username,
|
1020
|
+
# password: proc { password ||= ui.prompt_for_password },
|
1021
|
+
# oauth2_token: proc { accesstok ||= kms.fresh_access_token },
|
1022
|
+
# }
|
1023
|
+
# capa = imap.capability
|
1024
|
+
# if capa.include? "AUTH=OAUTHBEARER"
|
1025
|
+
# imap.authenticate "OAUTHBEARER", **creds # authcid, oauth2_token
|
1026
|
+
# elsif capa.include? "AUTH=XOAUTH2"
|
1027
|
+
# imap.authenticate "XOAUTH2", **creds # authcid, oauth2_token
|
1028
|
+
# elsif capa.include? "AUTH=SCRAM-SHA-256"
|
1029
|
+
# imap.authenticate "SCRAM-SHA-256", **creds # authcid, password
|
1030
|
+
# elsif capa.include? "AUTH=PLAIN"
|
1031
|
+
# imap.authenticate "PLAIN", **creds # authcid, password
|
1032
|
+
# elsif capa.include? "AUTH=DIGEST-MD5"
|
1033
|
+
# imap.authenticate "DIGEST-MD5", **creds # authcid, password
|
1034
|
+
# elsif capa.include? "LOGINDISABLED"
|
1035
|
+
# raise "the server has disabled login"
|
1036
|
+
# else
|
1037
|
+
# imap.login username, password
|
1038
|
+
# end
|
409
1039
|
#
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
authenticator = self.class.authenticator(auth_type, *args)
|
414
|
-
send_command("AUTHENTICATE", auth_type) do |resp|
|
1040
|
+
def authenticate(mechanism, *args, **props, &cb)
|
1041
|
+
authenticator = self.class.authenticator(mechanism, *args, **props, &cb)
|
1042
|
+
send_command("AUTHENTICATE", mechanism) do |resp|
|
415
1043
|
if resp.instance_of?(ContinuationRequest)
|
416
1044
|
data = authenticator.process(resp.data.text.unpack("m")[0])
|
417
1045
|
s = [data].pack("m0")
|
@@ -421,28 +1049,53 @@ module Net
|
|
421
1049
|
end
|
422
1050
|
end
|
423
1051
|
|
424
|
-
# Sends a LOGIN command
|
425
|
-
# the plaintext +password+ authenticating
|
426
|
-
#
|
427
|
-
#
|
1052
|
+
# Sends a {LOGIN command [IMAP4rev1 §6.2.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.2.3]
|
1053
|
+
# to identify the client and carries the plaintext +password+ authenticating
|
1054
|
+
# this +user+. If successful, the connection enters the "_authenticated_"
|
1055
|
+
# state.
|
1056
|
+
#
|
1057
|
+
# Using #authenticate is generally preferred over #login. The LOGIN command
|
1058
|
+
# is not the same as #authenticate with the "LOGIN" +mechanism+.
|
428
1059
|
#
|
429
1060
|
# A Net::IMAP::NoResponseError is raised if authentication fails.
|
1061
|
+
#
|
1062
|
+
# Related: #authenticate, #starttls
|
1063
|
+
#
|
1064
|
+
# ==== Capabilities
|
1065
|
+
# Clients MUST NOT call #login if +LOGINDISABLED+ is listed with the
|
1066
|
+
# capabilities.
|
1067
|
+
#
|
1068
|
+
# Server capabilities may change after #starttls, #login, and #authenticate.
|
1069
|
+
# Cached capabilities _must_ be invalidated after this method completes.
|
1070
|
+
# The TaggedResponse to #login may include updated capabilities in its
|
1071
|
+
# ResponseCode.
|
1072
|
+
#
|
430
1073
|
def login(user, password)
|
431
1074
|
send_command("LOGIN", user, password)
|
432
1075
|
end
|
433
1076
|
|
434
|
-
# Sends a SELECT command
|
435
|
-
# in the +mailbox+ can be accessed.
|
1077
|
+
# Sends a {SELECT command [IMAP4rev1 §6.3.1]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.1]
|
1078
|
+
# to select a +mailbox+ so that messages in the +mailbox+ can be accessed.
|
436
1079
|
#
|
437
|
-
# After you have selected a mailbox, you may retrieve the
|
438
|
-
#
|
439
|
-
#
|
440
|
-
#
|
441
|
-
#
|
442
|
-
#
|
1080
|
+
# After you have selected a mailbox, you may retrieve the number of items in
|
1081
|
+
# that mailbox from <tt>imap.responses["EXISTS"][-1]</tt>, and the number of
|
1082
|
+
# recent messages from <tt>imap.responses["RECENT"][-1]</tt>. Note that
|
1083
|
+
# these values can change if new messages arrive during a session or when
|
1084
|
+
# existing messages are expunged; see #add_response_handler for a way to
|
1085
|
+
# detect these events.
|
443
1086
|
#
|
444
1087
|
# A Net::IMAP::NoResponseError is raised if the mailbox does not
|
445
1088
|
# exist or is for some reason non-selectable.
|
1089
|
+
#
|
1090
|
+
# Related: #examine
|
1091
|
+
#
|
1092
|
+
# ===== Capabilities
|
1093
|
+
#
|
1094
|
+
# If [UIDPLUS[https://www.rfc-editor.org/rfc/rfc4315.html]] is supported,
|
1095
|
+
# the server may return an untagged "NO" response with a "UIDNOTSTICKY"
|
1096
|
+
# response code indicating that the mailstore does not support persistent
|
1097
|
+
# UIDs:
|
1098
|
+
# @responses["NO"].last.code.name == "UIDNOTSTICKY"
|
446
1099
|
def select(mailbox)
|
447
1100
|
synchronize do
|
448
1101
|
@responses.clear
|
@@ -450,12 +1103,15 @@ module Net
|
|
450
1103
|
end
|
451
1104
|
end
|
452
1105
|
|
453
|
-
# Sends a EXAMINE command
|
454
|
-
# in the +mailbox+ can be accessed.
|
455
|
-
# except that the selected +mailbox+ is
|
1106
|
+
# Sends a {EXAMINE command [IMAP4rev1 §6.3.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.2]
|
1107
|
+
# to select a +mailbox+ so that messages in the +mailbox+ can be accessed.
|
1108
|
+
# Behaves the same as #select, except that the selected +mailbox+ is
|
1109
|
+
# identified as read-only.
|
456
1110
|
#
|
457
1111
|
# A Net::IMAP::NoResponseError is raised if the mailbox does not
|
458
1112
|
# exist or is for some reason non-examinable.
|
1113
|
+
#
|
1114
|
+
# Related: #select
|
459
1115
|
def examine(mailbox)
|
460
1116
|
synchronize do
|
461
1117
|
@responses.clear
|
@@ -463,69 +1119,86 @@ module Net
|
|
463
1119
|
end
|
464
1120
|
end
|
465
1121
|
|
466
|
-
# Sends a CREATE command
|
1122
|
+
# Sends a {CREATE command [IMAP4rev1 §6.3.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.3]
|
1123
|
+
# to create a new +mailbox+.
|
467
1124
|
#
|
468
1125
|
# A Net::IMAP::NoResponseError is raised if a mailbox with that name
|
469
1126
|
# cannot be created.
|
1127
|
+
#
|
1128
|
+
# Related: #rename, #delete
|
470
1129
|
def create(mailbox)
|
471
1130
|
send_command("CREATE", mailbox)
|
472
1131
|
end
|
473
1132
|
|
474
|
-
# Sends a DELETE command
|
1133
|
+
# Sends a {DELETE command [IMAP4rev1 §6.3.4]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.4]
|
1134
|
+
# to remove the +mailbox+.
|
475
1135
|
#
|
476
1136
|
# A Net::IMAP::NoResponseError is raised if a mailbox with that name
|
477
1137
|
# cannot be deleted, either because it does not exist or because the
|
478
1138
|
# client does not have permission to delete it.
|
1139
|
+
#
|
1140
|
+
# Related: #create, #rename
|
479
1141
|
def delete(mailbox)
|
480
1142
|
send_command("DELETE", mailbox)
|
481
1143
|
end
|
482
1144
|
|
483
|
-
# Sends a RENAME command
|
484
|
-
# +newname+.
|
1145
|
+
# Sends a {RENAME command [IMAP4rev1 §6.3.5]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.5]
|
1146
|
+
# to change the name of the +mailbox+ to +newname+.
|
485
1147
|
#
|
486
1148
|
# A Net::IMAP::NoResponseError is raised if a mailbox with the
|
487
1149
|
# name +mailbox+ cannot be renamed to +newname+ for whatever
|
488
1150
|
# reason; for instance, because +mailbox+ does not exist, or
|
489
1151
|
# because there is already a mailbox with the name +newname+.
|
1152
|
+
#
|
1153
|
+
# Related: #create, #delete
|
490
1154
|
def rename(mailbox, newname)
|
491
1155
|
send_command("RENAME", mailbox, newname)
|
492
1156
|
end
|
493
1157
|
|
494
|
-
# Sends a SUBSCRIBE command
|
495
|
-
# the server's set of "active" or
|
496
|
-
# by #lsub.
|
1158
|
+
# Sends a {SUBSCRIBE command [IMAP4rev1 §6.3.6]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.6]
|
1159
|
+
# to add the specified +mailbox+ name to the server's set of "active" or
|
1160
|
+
# "subscribed" mailboxes as returned by #lsub.
|
497
1161
|
#
|
498
1162
|
# A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be
|
499
1163
|
# subscribed to; for instance, because it does not exist.
|
1164
|
+
#
|
1165
|
+
# Related: #unsubscribe, #lsub, #list
|
500
1166
|
def subscribe(mailbox)
|
501
1167
|
send_command("SUBSCRIBE", mailbox)
|
502
1168
|
end
|
503
1169
|
|
504
|
-
# Sends
|
505
|
-
# from the server's set of "active"
|
1170
|
+
# Sends an {UNSUBSCRIBE command [IMAP4rev1 §6.3.7]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.7]
|
1171
|
+
# to remove the specified +mailbox+ name from the server's set of "active"
|
1172
|
+
# or "subscribed" mailboxes.
|
506
1173
|
#
|
507
1174
|
# A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be
|
508
1175
|
# unsubscribed from; for instance, because the client is not currently
|
509
1176
|
# subscribed to it.
|
1177
|
+
#
|
1178
|
+
# Related: #subscribe, #lsub, #list
|
510
1179
|
def unsubscribe(mailbox)
|
511
1180
|
send_command("UNSUBSCRIBE", mailbox)
|
512
1181
|
end
|
513
1182
|
|
514
|
-
# Sends a LIST command
|
515
|
-
# the complete set of all names available
|
516
|
-
# +refname+ provides a context (for instance, a base
|
517
|
-
# in a directory-based mailbox hierarchy). +mailbox+ specifies
|
518
|
-
#
|
519
|
-
#
|
520
|
-
#
|
521
|
-
#
|
522
|
-
#
|
1183
|
+
# Sends a {LIST command [IMAP4rev1 §6.3.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.8]
|
1184
|
+
# and returns a subset of names from the complete set of all names available
|
1185
|
+
# to the client. +refname+ provides a context (for instance, a base
|
1186
|
+
# directory in a directory-based mailbox hierarchy). +mailbox+ specifies a
|
1187
|
+
# mailbox or (via wildcards) mailboxes under that context. Two wildcards
|
1188
|
+
# may be used in +mailbox+: '*', which matches all characters *including*
|
1189
|
+
# the hierarchy delimiter (for instance, '/' on a UNIX-hosted
|
1190
|
+
# directory-based mailbox hierarchy); and '%', which matches all characters
|
1191
|
+
# *except* the hierarchy delimiter.
|
523
1192
|
#
|
524
1193
|
# If +refname+ is empty, +mailbox+ is used directly to determine
|
525
1194
|
# which mailboxes to match. If +mailbox+ is empty, the root
|
526
1195
|
# name of +refname+ and the hierarchy delimiter are returned.
|
527
1196
|
#
|
528
|
-
# The return value is an array of
|
1197
|
+
# The return value is an array of MailboxList.
|
1198
|
+
#
|
1199
|
+
# Related: #lsub, MailboxList
|
1200
|
+
#
|
1201
|
+
# ===== For example:
|
529
1202
|
#
|
530
1203
|
# imap.create("foo/bar")
|
531
1204
|
# imap.create("foo/baz")
|
@@ -533,6 +1206,10 @@ module Net
|
|
533
1206
|
# #=> [#<Net::IMAP::MailboxList attr=[:Noselect], delim="/", name="foo/">, \\
|
534
1207
|
# #<Net::IMAP::MailboxList attr=[:Noinferiors, :Marked], delim="/", name="foo/bar">, \\
|
535
1208
|
# #<Net::IMAP::MailboxList attr=[:Noinferiors], delim="/", name="foo/baz">]
|
1209
|
+
#
|
1210
|
+
#--
|
1211
|
+
# TODO: support LIST-EXTENDED extension [RFC5258]. Needed for IMAP4rev2.
|
1212
|
+
#++
|
536
1213
|
def list(refname, mailbox)
|
537
1214
|
synchronize do
|
538
1215
|
send_command("LIST", refname, mailbox)
|
@@ -540,41 +1217,39 @@ module Net
|
|
540
1217
|
end
|
541
1218
|
end
|
542
1219
|
|
543
|
-
# Sends a NAMESPACE command
|
544
|
-
#
|
545
|
-
# namespaces used by a server
|
546
|
-
# mailboxes, and shared mailboxes.
|
1220
|
+
# Sends a {NAMESPACE command [RFC2342 §5]}[https://www.rfc-editor.org/rfc/rfc2342#section-5]
|
1221
|
+
# and returns the namespaces that are available. The NAMESPACE command
|
1222
|
+
# allows a client to discover the prefixes of namespaces used by a server
|
1223
|
+
# for personal mailboxes, other users' mailboxes, and shared mailboxes.
|
547
1224
|
#
|
548
|
-
# The
|
549
|
-
#
|
550
|
-
#
|
551
|
-
# hierarchy delimiter. In that common case, the naive client may not have
|
552
|
-
# any trouble naming mailboxes.
|
1225
|
+
# The return value is a Namespaces object which has +personal+, +other+, and
|
1226
|
+
# +shared+ fields, each an array of Namespace objects. These arrays will be
|
1227
|
+
# empty when the server responds with +nil+.
|
553
1228
|
#
|
1229
|
+
# Many \IMAP servers are configured with the default personal namespaces as
|
1230
|
+
# <tt>("" "/")</tt>: no prefix and the "+/+" hierarchy delimiter. In that
|
1231
|
+
# common case, the naive client may not have any trouble naming mailboxes.
|
554
1232
|
# But many servers are configured with the default personal namespace as
|
555
|
-
# e.g.
|
556
|
-
# as the hierarchy delimiter. If the client does not check for
|
557
|
-
# naively assumes it can use the same folder names for all
|
558
|
-
# folder creation (and listing, moving, etc) can lead to
|
1233
|
+
# e.g. <tt>("INBOX." ".")</tt>, placing all personal folders under INBOX,
|
1234
|
+
# with "+.+" as the hierarchy delimiter. If the client does not check for
|
1235
|
+
# this, but naively assumes it can use the same folder names for all
|
1236
|
+
# servers, then folder creation (and listing, moving, etc) can lead to
|
1237
|
+
# errors.
|
559
1238
|
#
|
560
1239
|
# From RFC2342:
|
561
1240
|
#
|
562
1241
|
# Although typically a server will support only a single Personal
|
563
1242
|
# Namespace, and a single Other User's Namespace, circumstances exist
|
564
1243
|
# where there MAY be multiples of these, and a client MUST be prepared
|
565
|
-
# for them.
|
1244
|
+
# for them. If a client is configured such that it is required to create
|
566
1245
|
# a certain mailbox, there can be circumstances where it is unclear which
|
567
|
-
# Personal Namespaces it should create the mailbox in.
|
1246
|
+
# Personal Namespaces it should create the mailbox in. In these
|
568
1247
|
# situations a client SHOULD let the user select which namespaces to
|
569
1248
|
# create the mailbox in.
|
570
1249
|
#
|
571
|
-
#
|
572
|
-
# NAMESPACE capability. The return value is a +Net::IMAP::Namespaces+
|
573
|
-
# object which has +personal+, +other+, and +shared+ fields, each an array
|
574
|
-
# of +Net::IMAP::Namespace+ objects. These arrays will be empty when the
|
575
|
-
# server responds with nil.
|
1250
|
+
# Related: #list, Namespaces, Namespace
|
576
1251
|
#
|
577
|
-
# For example:
|
1252
|
+
# ===== For example:
|
578
1253
|
#
|
579
1254
|
# capabilities = imap.capability
|
580
1255
|
# if capabilities.include?("NAMESPACE")
|
@@ -589,7 +1264,10 @@ module Net
|
|
589
1264
|
# end
|
590
1265
|
# end
|
591
1266
|
#
|
592
|
-
#
|
1267
|
+
# ===== Capabilities
|
1268
|
+
#
|
1269
|
+
# The server's capabilities must include +NAMESPACE+
|
1270
|
+
# [RFC2342[https://tools.ietf.org/html/rfc2342]].
|
593
1271
|
def namespace
|
594
1272
|
synchronize do
|
595
1273
|
send_command("NAMESPACE")
|
@@ -614,7 +1292,7 @@ module Net
|
|
614
1292
|
# The XLIST command is like the LIST command except that the flags
|
615
1293
|
# returned refer to the function of the folder/mailbox, e.g. :Sent
|
616
1294
|
#
|
617
|
-
# The return value is an array of
|
1295
|
+
# The return value is an array of MailboxList objects. For example:
|
618
1296
|
#
|
619
1297
|
# imap.create("foo/bar")
|
620
1298
|
# imap.create("foo/baz")
|
@@ -622,6 +1300,18 @@ module Net
|
|
622
1300
|
# #=> [#<Net::IMAP::MailboxList attr=[:Noselect], delim="/", name="foo/">, \\
|
623
1301
|
# #<Net::IMAP::MailboxList attr=[:Noinferiors, :Marked], delim="/", name="foo/bar">, \\
|
624
1302
|
# #<Net::IMAP::MailboxList attr=[:Noinferiors], delim="/", name="foo/baz">]
|
1303
|
+
#
|
1304
|
+
# Related: #list, MailboxList
|
1305
|
+
#
|
1306
|
+
# ===== Capabilities
|
1307
|
+
#
|
1308
|
+
# The server's capabilities must include +XLIST+,
|
1309
|
+
# a deprecated Gmail extension (replaced by +SPECIAL-USE+).
|
1310
|
+
#--
|
1311
|
+
# TODO: Net::IMAP doesn't yet have full SPECIAL-USE support. Supporting
|
1312
|
+
# servers MAY return SPECIAL-USE attributes, but are not *required* to
|
1313
|
+
# unless the SPECIAL-USE return option is supplied.
|
1314
|
+
#++
|
625
1315
|
def xlist(refname, mailbox)
|
626
1316
|
synchronize do
|
627
1317
|
send_command("XLIST", refname, mailbox)
|
@@ -629,12 +1319,17 @@ module Net
|
|
629
1319
|
end
|
630
1320
|
end
|
631
1321
|
|
632
|
-
# Sends
|
633
|
-
# This command is generally available
|
634
|
-
# If this mailbox exists, it returns an array
|
635
|
-
#
|
1322
|
+
# Sends a {GETQUOTAROOT command [RFC2087 §4.3]}[https://www.rfc-editor.org/rfc/rfc2087#section-4.3]
|
1323
|
+
# along with the specified +mailbox+. This command is generally available
|
1324
|
+
# to both admin and user. If this mailbox exists, it returns an array
|
1325
|
+
# containing objects of type MailboxQuotaRoot and MailboxQuota.
|
1326
|
+
#
|
1327
|
+
# Related: #getquota, #setquota, MailboxQuotaRoot, MailboxQuota
|
636
1328
|
#
|
637
|
-
#
|
1329
|
+
# ===== Capabilities
|
1330
|
+
#
|
1331
|
+
# The server's capabilities must include +QUOTA+
|
1332
|
+
# [RFC2087[https://tools.ietf.org/html/rfc2087]].
|
638
1333
|
def getquotaroot(mailbox)
|
639
1334
|
synchronize do
|
640
1335
|
send_command("GETQUOTAROOT", mailbox)
|
@@ -645,12 +1340,17 @@ module Net
|
|
645
1340
|
end
|
646
1341
|
end
|
647
1342
|
|
648
|
-
# Sends
|
649
|
-
# If this mailbox exists, then an array
|
650
|
-
#
|
651
|
-
#
|
1343
|
+
# Sends a {GETQUOTA command [RFC2087 §4.2]}[https://www.rfc-editor.org/rfc/rfc2087#section-4.2]
|
1344
|
+
# along with specified +mailbox+. If this mailbox exists, then an array
|
1345
|
+
# containing a MailboxQuota object is returned. This command is generally
|
1346
|
+
# only available to server admin.
|
1347
|
+
#
|
1348
|
+
# Related: #getquotaroot, #setquota, MailboxQuota
|
652
1349
|
#
|
653
|
-
#
|
1350
|
+
# ===== Capabilities
|
1351
|
+
#
|
1352
|
+
# The server's capabilities must include +QUOTA+
|
1353
|
+
# [RFC2087[https://tools.ietf.org/html/rfc2087]].
|
654
1354
|
def getquota(mailbox)
|
655
1355
|
synchronize do
|
656
1356
|
send_command("GETQUOTA", mailbox)
|
@@ -658,12 +1358,17 @@ module Net
|
|
658
1358
|
end
|
659
1359
|
end
|
660
1360
|
|
661
|
-
# Sends a SETQUOTA command
|
662
|
-
# +quota+. If +quota+ is nil, then
|
663
|
-
# mailbox. Typically one needs to be logged
|
664
|
-
# for this to work.
|
1361
|
+
# Sends a {SETQUOTA command [RFC2087 §4.1]}[https://www.rfc-editor.org/rfc/rfc2087#section-4.1]
|
1362
|
+
# along with the specified +mailbox+ and +quota+. If +quota+ is nil, then
|
1363
|
+
# +quota+ will be unset for that mailbox. Typically one needs to be logged
|
1364
|
+
# in as a server admin for this to work.
|
1365
|
+
#
|
1366
|
+
# Related: #getquota, #getquotaroot
|
1367
|
+
#
|
1368
|
+
# ===== Capabilities
|
665
1369
|
#
|
666
|
-
# The
|
1370
|
+
# The server's capabilities must include +QUOTA+
|
1371
|
+
# [RFC2087[https://tools.ietf.org/html/rfc2087]].
|
667
1372
|
def setquota(mailbox, quota)
|
668
1373
|
if quota.nil?
|
669
1374
|
data = '()'
|
@@ -673,11 +1378,17 @@ module Net
|
|
673
1378
|
send_command("SETQUOTA", mailbox, RawData.new(data))
|
674
1379
|
end
|
675
1380
|
|
676
|
-
# Sends
|
677
|
-
# +rights+ that user is to have on that
|
678
|
-
# then that user will be stripped of any
|
1381
|
+
# Sends a {SETACL command [RFC4314 §3.1]}[https://www.rfc-editor.org/rfc/rfc4314#section-3.1]
|
1382
|
+
# along with +mailbox+, +user+ and the +rights+ that user is to have on that
|
1383
|
+
# mailbox. If +rights+ is nil, then that user will be stripped of any
|
1384
|
+
# rights to that mailbox.
|
1385
|
+
#
|
1386
|
+
# Related: #getacl
|
1387
|
+
#
|
1388
|
+
# ===== Capabilities
|
679
1389
|
#
|
680
|
-
# The
|
1390
|
+
# The server's capabilities must include +ACL+
|
1391
|
+
# [RFC4314[https://tools.ietf.org/html/rfc4314]].
|
681
1392
|
def setacl(mailbox, user, rights)
|
682
1393
|
if rights.nil?
|
683
1394
|
send_command("SETACL", mailbox, user, "")
|
@@ -686,11 +1397,16 @@ module Net
|
|
686
1397
|
end
|
687
1398
|
end
|
688
1399
|
|
689
|
-
#
|
690
|
-
# If this mailbox exists, an array
|
691
|
-
#
|
1400
|
+
# Sends a {GETACL command [RFC4314 §3.3]}[https://www.rfc-editor.org/rfc/rfc4314#section-3.3]
|
1401
|
+
# along with a specified +mailbox+. If this mailbox exists, an array
|
1402
|
+
# containing objects of MailboxACLItem will be returned.
|
692
1403
|
#
|
693
|
-
#
|
1404
|
+
# Related: #setacl, MailboxACLItem
|
1405
|
+
#
|
1406
|
+
# ===== Capabilities
|
1407
|
+
#
|
1408
|
+
# The server's capabilities must include +ACL+
|
1409
|
+
# [RFC4314[https://tools.ietf.org/html/rfc4314]].
|
694
1410
|
def getacl(mailbox)
|
695
1411
|
synchronize do
|
696
1412
|
send_command("GETACL", mailbox)
|
@@ -698,12 +1414,14 @@ module Net
|
|
698
1414
|
end
|
699
1415
|
end
|
700
1416
|
|
701
|
-
# Sends a LSUB command
|
702
|
-
# of names
|
703
|
-
# "subscribed." +refname+ and +mailbox+ are
|
704
|
-
# for #list.
|
1417
|
+
# Sends a {LSUB command [IMAP4rev1 §6.3.9]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.9]
|
1418
|
+
# and returns a subset of names from the set of names that the user has
|
1419
|
+
# declared as being "active" or "subscribed." +refname+ and +mailbox+ are
|
1420
|
+
# interpreted as for #list.
|
705
1421
|
#
|
706
|
-
# The return value is an array of
|
1422
|
+
# The return value is an array of MailboxList objects.
|
1423
|
+
#
|
1424
|
+
# Related: #subscribe, #unsubscribe, #list, MailboxList
|
707
1425
|
def lsub(refname, mailbox)
|
708
1426
|
synchronize do
|
709
1427
|
send_command("LSUB", refname, mailbox)
|
@@ -711,9 +1429,10 @@ module Net
|
|
711
1429
|
end
|
712
1430
|
end
|
713
1431
|
|
714
|
-
# Sends a STATUS
|
715
|
-
# +mailbox+. +attr+ is a list of one
|
716
|
-
# statuses are to be requested. Supported
|
1432
|
+
# Sends a {STATUS commands [IMAP4rev1 §6.3.10]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.10]
|
1433
|
+
# and returns the status of the indicated +mailbox+. +attr+ is a list of one
|
1434
|
+
# or more attributes whose statuses are to be requested. Supported
|
1435
|
+
# attributes include:
|
717
1436
|
#
|
718
1437
|
# MESSAGES:: the number of messages in the mailbox.
|
719
1438
|
# RECENT:: the number of recent messages in the mailbox.
|
@@ -734,11 +1453,12 @@ module Net
|
|
734
1453
|
end
|
735
1454
|
end
|
736
1455
|
|
737
|
-
# Sends
|
738
|
-
# the +mailbox+. The optional +flags+
|
739
|
-
# flags initially passed to the new message. The
|
740
|
-
# +date_time+ argument specifies the creation time to assign to the
|
1456
|
+
# Sends an {APPEND command [IMAP4rev1 §6.3.11]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.11]
|
1457
|
+
# to append the +message+ to the end of the +mailbox+. The optional +flags+
|
1458
|
+
# argument is an array of flags initially passed to the new message. The
|
1459
|
+
# optional +date_time+ argument specifies the creation time to assign to the
|
741
1460
|
# new message; it defaults to the current time.
|
1461
|
+
#
|
742
1462
|
# For example:
|
743
1463
|
#
|
744
1464
|
# imap.append("inbox", <<EOF.gsub(/\n/, "\r\n"), [:Seen], Time.now)
|
@@ -752,6 +1472,18 @@ module Net
|
|
752
1472
|
# A Net::IMAP::NoResponseError is raised if the mailbox does
|
753
1473
|
# not exist (it is not created automatically), or if the flags,
|
754
1474
|
# date_time, or message arguments contain errors.
|
1475
|
+
#
|
1476
|
+
# ===== Capabilities
|
1477
|
+
#
|
1478
|
+
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
|
1479
|
+
# supported and the destination supports persistent UIDs, the server's
|
1480
|
+
# response should include an +APPENDUID+ response code with UIDPlusData.
|
1481
|
+
# This will report the UIDVALIDITY of the destination mailbox and the
|
1482
|
+
# assigned UID of the appended message.
|
1483
|
+
#
|
1484
|
+
#--
|
1485
|
+
# TODO: add MULTIAPPEND support
|
1486
|
+
#++
|
755
1487
|
def append(mailbox, message, flags = nil, date_time = nil)
|
756
1488
|
args = []
|
757
1489
|
if flags
|
@@ -762,23 +1494,47 @@ module Net
|
|
762
1494
|
send_command("APPEND", mailbox, *args)
|
763
1495
|
end
|
764
1496
|
|
765
|
-
# Sends a CHECK command
|
766
|
-
# selected mailbox. This performs
|
767
|
-
# housekeeping; for instance, reconciling the
|
768
|
-
# in-memory and on-disk state.
|
1497
|
+
# Sends a {CHECK command [IMAP4rev1 §6.4.1]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.1]
|
1498
|
+
# to request a checkpoint of the currently selected mailbox. This performs
|
1499
|
+
# implementation-specific housekeeping; for instance, reconciling the
|
1500
|
+
# mailbox's in-memory and on-disk state.
|
1501
|
+
#
|
1502
|
+
# Related: #idle, #noop
|
769
1503
|
def check
|
770
1504
|
send_command("CHECK")
|
771
1505
|
end
|
772
1506
|
|
773
|
-
# Sends a CLOSE command
|
774
|
-
#
|
775
|
-
# messages that have the
|
1507
|
+
# Sends a {CLOSE command [IMAP4rev1 §6.4.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.2]
|
1508
|
+
# to close the currently selected mailbox. The CLOSE command permanently
|
1509
|
+
# removes from the mailbox all messages that have the <tt>\\Deleted</tt>
|
1510
|
+
# flag set.
|
1511
|
+
#
|
1512
|
+
# Related: #unselect
|
776
1513
|
def close
|
777
1514
|
send_command("CLOSE")
|
778
1515
|
end
|
779
1516
|
|
1517
|
+
# Sends an {UNSELECT command [RFC3691 §2]}[https://www.rfc-editor.org/rfc/rfc3691#section-3]
|
1518
|
+
# {[IMAP4rev2 §6.4.2]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.2]
|
1519
|
+
# to free the session resources for a mailbox and return to the
|
1520
|
+
# "_authenticated_" state. This is the same as #close, except that
|
1521
|
+
# <tt>\\Deleted</tt> messages are not removed from the mailbox.
|
1522
|
+
#
|
1523
|
+
# Related: #close
|
1524
|
+
#
|
1525
|
+
# ===== Capabilities
|
1526
|
+
#
|
1527
|
+
# The server's capabilities must include +UNSELECT+
|
1528
|
+
# [RFC3691[https://tools.ietf.org/html/rfc3691]].
|
1529
|
+
def unselect
|
1530
|
+
send_command("UNSELECT")
|
1531
|
+
end
|
1532
|
+
|
1533
|
+
# Sends an {EXPUNGE command [IMAP4rev1 §6.4.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.3]
|
780
1534
|
# Sends a EXPUNGE command to permanently remove from the currently
|
781
1535
|
# selected mailbox all messages that have the \Deleted flag set.
|
1536
|
+
#
|
1537
|
+
# Related: #uid_expunge
|
782
1538
|
def expunge
|
783
1539
|
synchronize do
|
784
1540
|
send_command("EXPUNGE")
|
@@ -786,20 +1542,65 @@ module Net
|
|
786
1542
|
end
|
787
1543
|
end
|
788
1544
|
|
789
|
-
# Sends a
|
790
|
-
#
|
791
|
-
#
|
792
|
-
#
|
793
|
-
#
|
794
|
-
#
|
1545
|
+
# Sends a {UID EXPUNGE command [RFC4315 §2.1]}[https://www.rfc-editor.org/rfc/rfc4315#section-2.1]
|
1546
|
+
# {[IMAP4rev2 §6.4.9]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.9]
|
1547
|
+
# to permanently remove all messages that have both the <tt>\\Deleted</tt>
|
1548
|
+
# flag set and a UID that is included in +uid_set+.
|
1549
|
+
#
|
1550
|
+
# By using #uid_expunge instead of #expunge when resynchronizing with
|
1551
|
+
# the server, the client can ensure that it does not inadvertantly
|
1552
|
+
# remove any messages that have been marked as <tt>\\Deleted</tt> by other
|
1553
|
+
# clients between the time that the client was last connected and
|
1554
|
+
# the time the client resynchronizes.
|
1555
|
+
#
|
1556
|
+
# *Note:*
|
1557
|
+
# >>>
|
1558
|
+
# Although the command takes a set of UIDs for its argument, the
|
1559
|
+
# server still returns regular EXPUNGE responses, which contain
|
1560
|
+
# a <em>sequence number</em>. These will be deleted from
|
1561
|
+
# #responses and this method returns them as an array of
|
1562
|
+
# <em>sequence number</em> integers.
|
795
1563
|
#
|
796
|
-
#
|
797
|
-
#
|
798
|
-
#
|
1564
|
+
# Related: #expunge
|
1565
|
+
#
|
1566
|
+
# ===== Capabilities
|
1567
|
+
#
|
1568
|
+
# The server's capabilities must include +UIDPLUS+
|
1569
|
+
# [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]].
|
1570
|
+
def uid_expunge(uid_set)
|
1571
|
+
synchronize do
|
1572
|
+
send_command("UID EXPUNGE", MessageSet.new(uid_set))
|
1573
|
+
return @responses.delete("EXPUNGE")
|
1574
|
+
end
|
1575
|
+
end
|
1576
|
+
|
1577
|
+
# Sends a {SEARCH command [IMAP4rev1 §6.4.4]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.4]
|
1578
|
+
# to search the mailbox for messages that match the given searching
|
1579
|
+
# criteria, and returns message sequence numbers. +keys+ can either be a
|
1580
|
+
# string holding the entire search string, or a single-dimension array of
|
1581
|
+
# search keywords and arguments.
|
1582
|
+
#
|
1583
|
+
# Related: #uid_search
|
1584
|
+
#
|
1585
|
+
# ===== Search criteria
|
1586
|
+
#
|
1587
|
+
# For a full list of search criteria,
|
1588
|
+
# see [{IMAP4rev1 §6.4.4}[https://www.rfc-editor.org/rfc/rfc3501.html#section-6.4.4]],
|
1589
|
+
# or [{IMAP4rev2 §6.4.4}[https://www.rfc-editor.org/rfc/rfc9051.html#section-6.4.4]],
|
1590
|
+
# in addition to documentation for
|
1591
|
+
# any [CAPABILITIES[https://www.iana.org/assignments/imap-capabilities/imap-capabilities.xhtml]]
|
1592
|
+
# reported by #capability which may define additional search filters, e.g:
|
1593
|
+
# +CONDSTORE+, +WITHIN+, +FILTERS+, <tt>SEARCH=FUZZY</tt>, +OBJECTID+, or
|
1594
|
+
# +SAVEDATE+. The following are some common search criteria:
|
1595
|
+
#
|
1596
|
+
# <message set>:: a set of message sequence numbers. "<tt>,</tt>" indicates
|
1597
|
+
# an interval, "+:+" indicates a range. For instance,
|
1598
|
+
# "<tt>2,10:12,15</tt>" means "<tt>2,10,11,12,15</tt>".
|
799
1599
|
#
|
800
1600
|
# BEFORE <date>:: messages with an internal date strictly before
|
801
|
-
# <date>. The date argument has a format similar
|
802
|
-
# to 8-Aug-2002
|
1601
|
+
# <b><date></b>. The date argument has a format similar
|
1602
|
+
# to <tt>8-Aug-2002</tt>, and can be formatted using
|
1603
|
+
# Net::IMAP.format_date.
|
803
1604
|
#
|
804
1605
|
# BODY <string>:: messages that contain <string> within their body.
|
805
1606
|
#
|
@@ -822,21 +1623,26 @@ module Net
|
|
822
1623
|
#
|
823
1624
|
# TO <string>:: messages with <string> in their TO field.
|
824
1625
|
#
|
825
|
-
# For example:
|
1626
|
+
# ===== For example:
|
826
1627
|
#
|
827
1628
|
# p imap.search(["SUBJECT", "hello", "NOT", "NEW"])
|
828
1629
|
# #=> [1, 6, 7, 8]
|
1630
|
+
#
|
829
1631
|
def search(keys, charset = nil)
|
830
1632
|
return search_internal("SEARCH", keys, charset)
|
831
1633
|
end
|
832
1634
|
|
833
|
-
#
|
1635
|
+
# Sends a {UID SEARCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
|
1636
|
+
# to search the mailbox for messages that match the given searching
|
1637
|
+
# criteria, and returns unique identifiers (<tt>UID</tt>s).
|
1638
|
+
#
|
1639
|
+
# See #search for documentation of search criteria.
|
834
1640
|
def uid_search(keys, charset = nil)
|
835
1641
|
return search_internal("UID SEARCH", keys, charset)
|
836
1642
|
end
|
837
1643
|
|
838
|
-
# Sends a FETCH command
|
839
|
-
# in the mailbox.
|
1644
|
+
# Sends a {FETCH command [IMAP4rev1 §6.4.5]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.5]
|
1645
|
+
# to retrieve data associated with a message in the mailbox.
|
840
1646
|
#
|
841
1647
|
# The +set+ parameter is a number or a range between two numbers,
|
842
1648
|
# or an array of those. The number is a message sequence number,
|
@@ -848,12 +1654,14 @@ module Net
|
|
848
1654
|
# equivalent to 1..5.
|
849
1655
|
#
|
850
1656
|
# +attr+ is a list of attributes to fetch; see the documentation
|
851
|
-
# for
|
1657
|
+
# for FetchData for a list of valid attributes.
|
852
1658
|
#
|
853
|
-
# The return value is an array of
|
1659
|
+
# The return value is an array of FetchData or nil
|
854
1660
|
# (instead of an empty array) if there is no matching message.
|
855
1661
|
#
|
856
|
-
#
|
1662
|
+
# Related: #uid_search, FetchData
|
1663
|
+
#
|
1664
|
+
# ===== For example:
|
857
1665
|
#
|
858
1666
|
# p imap.fetch(6..8, "UID")
|
859
1667
|
# #=> [#<Net::IMAP::FetchData seqno=6, attr={"UID"=>98}>, \\
|
@@ -874,20 +1682,35 @@ module Net
|
|
874
1682
|
return fetch_internal("FETCH", set, attr, mod)
|
875
1683
|
end
|
876
1684
|
|
877
|
-
#
|
1685
|
+
# Sends a {UID FETCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
|
1686
|
+
# to retrieve data associated with a message in the mailbox.
|
1687
|
+
#
|
1688
|
+
# Similar to #fetch, but the +set+ parameter contains unique identifiers
|
1689
|
+
# instead of message sequence numbers.
|
1690
|
+
#
|
1691
|
+
# >>>
|
1692
|
+
# *Note:* Servers _MUST_ implicitly include the +UID+ message data item as
|
1693
|
+
# part of any +FETCH+ response caused by a +UID+ command, regardless of
|
1694
|
+
# whether a +UID+ was specified as a message data item to the +FETCH+.
|
1695
|
+
#
|
1696
|
+
# Related: #fetch, FetchData
|
878
1697
|
def uid_fetch(set, attr, mod = nil)
|
879
1698
|
return fetch_internal("UID FETCH", set, attr, mod)
|
880
1699
|
end
|
881
1700
|
|
882
|
-
# Sends a STORE command
|
883
|
-
# in the mailbox, in particular their
|
884
|
-
# is a number, an array of numbers, or a Range
|
885
|
-
# is a message sequence number. +attr+ is the name of a
|
886
|
-
# to store: 'FLAGS' will replace the message's flag list
|
887
|
-
#
|
888
|
-
#
|
1701
|
+
# Sends a {STORE command [IMAP4rev1 §6.4.6]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.6]
|
1702
|
+
# to alter data associated with messages in the mailbox, in particular their
|
1703
|
+
# flags. The +set+ parameter is a number, an array of numbers, or a Range
|
1704
|
+
# object. Each number is a message sequence number. +attr+ is the name of a
|
1705
|
+
# data item to store: 'FLAGS' will replace the message's flag list with the
|
1706
|
+
# provided one, '+FLAGS' will add the provided flags, and '-FLAGS' will
|
1707
|
+
# remove them. +flags+ is a list of flags.
|
1708
|
+
#
|
1709
|
+
# The return value is an array of FetchData
|
889
1710
|
#
|
890
|
-
#
|
1711
|
+
# Related: #uid_store
|
1712
|
+
#
|
1713
|
+
# ===== For example:
|
891
1714
|
#
|
892
1715
|
# p imap.store(6..8, "+FLAGS", [:Deleted])
|
893
1716
|
# #=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\
|
@@ -897,86 +1720,137 @@ module Net
|
|
897
1720
|
return store_internal("STORE", set, attr, flags)
|
898
1721
|
end
|
899
1722
|
|
900
|
-
#
|
1723
|
+
# Sends a {UID STORE command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
|
1724
|
+
# to alter data associated with messages in the mailbox, in particular their
|
1725
|
+
# flags.
|
1726
|
+
#
|
1727
|
+
# Similar to #store, but +set+ contains unique identifiers instead of
|
1728
|
+
# message sequence numbers.
|
1729
|
+
#
|
1730
|
+
# Related: #store
|
901
1731
|
def uid_store(set, attr, flags)
|
902
1732
|
return store_internal("UID STORE", set, attr, flags)
|
903
1733
|
end
|
904
1734
|
|
905
|
-
# Sends a COPY command
|
906
|
-
#
|
907
|
-
# a number, an array of numbers, or a
|
908
|
-
# a message sequence number.
|
1735
|
+
# Sends a {COPY command [IMAP4rev1 §6.4.7]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.7]
|
1736
|
+
# to copy the specified message(s) to the end of the specified destination
|
1737
|
+
# +mailbox+. The +set+ parameter is a number, an array of numbers, or a
|
1738
|
+
# Range object. The number is a message sequence number.
|
1739
|
+
#
|
1740
|
+
# Related: #uid_copy
|
1741
|
+
#
|
1742
|
+
# ===== Capabilities
|
1743
|
+
#
|
1744
|
+
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
|
1745
|
+
# supported, the server's response should include a +COPYUID+ response code
|
1746
|
+
# with UIDPlusData. This will report the UIDVALIDITY of the destination
|
1747
|
+
# mailbox, the UID set of the source messages, and the assigned UID set of
|
1748
|
+
# the moved messages.
|
909
1749
|
def copy(set, mailbox)
|
910
1750
|
copy_internal("COPY", set, mailbox)
|
911
1751
|
end
|
912
1752
|
|
1753
|
+
# Sends a {UID COPY command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
|
1754
|
+
# to copy the specified message(s) to the end of the specified destination
|
1755
|
+
# +mailbox+.
|
1756
|
+
#
|
913
1757
|
# Similar to #copy, but +set+ contains unique identifiers.
|
1758
|
+
#
|
1759
|
+
# ===== Capabilities
|
1760
|
+
#
|
1761
|
+
# +UIDPLUS+ affects #uid_copy the same way it affects #copy.
|
914
1762
|
def uid_copy(set, mailbox)
|
915
1763
|
copy_internal("UID COPY", set, mailbox)
|
916
1764
|
end
|
917
1765
|
|
918
|
-
# Sends a MOVE command
|
919
|
-
#
|
920
|
-
#
|
921
|
-
# a
|
1766
|
+
# Sends a {MOVE command [RFC6851 §3.1]}[https://www.rfc-editor.org/rfc/rfc6851#section-3.1]
|
1767
|
+
# {[IMAP4rev2 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.8]
|
1768
|
+
# to move the specified message(s) to the end of the specified destination
|
1769
|
+
# +mailbox+. The +set+ parameter is a number, an array of numbers, or a
|
1770
|
+
# Range object. The number is a message sequence number.
|
1771
|
+
#
|
1772
|
+
# Related: #uid_move
|
1773
|
+
#
|
1774
|
+
# ===== Capabilities
|
1775
|
+
#
|
1776
|
+
# The server's capabilities must include +MOVE+
|
1777
|
+
# [RFC6851[https://tools.ietf.org/html/rfc6851]].
|
1778
|
+
#
|
1779
|
+
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
|
1780
|
+
# supported, the server's response should include a +COPYUID+ response code
|
1781
|
+
# with UIDPlusData. This will report the UIDVALIDITY of the destination
|
1782
|
+
# mailbox, the UID set of the source messages, and the assigned UID set of
|
1783
|
+
# the moved messages.
|
922
1784
|
#
|
923
|
-
# The MOVE extension is described in [EXT-MOVE[https://tools.ietf.org/html/rfc6851]].
|
924
1785
|
def move(set, mailbox)
|
925
1786
|
copy_internal("MOVE", set, mailbox)
|
926
1787
|
end
|
927
1788
|
|
1789
|
+
# Sends a {UID MOVE command [RFC6851 §3.2]}[https://www.rfc-editor.org/rfc/rfc6851#section-3.2]
|
1790
|
+
# {[IMAP4rev2 §6.4.9]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.9]
|
1791
|
+
# to move the specified message(s) to the end of the specified destination
|
1792
|
+
# +mailbox+.
|
1793
|
+
#
|
928
1794
|
# Similar to #move, but +set+ contains unique identifiers.
|
929
1795
|
#
|
930
|
-
#
|
1796
|
+
# Related: #move
|
1797
|
+
#
|
1798
|
+
# ===== Capabilities
|
1799
|
+
#
|
1800
|
+
# Same as #move: The server's capabilities must include +MOVE+
|
1801
|
+
# [RFC6851[https://tools.ietf.org/html/rfc6851]]. +UIDPLUS+ also affects
|
1802
|
+
# #uid_move the same way it affects #move.
|
931
1803
|
def uid_move(set, mailbox)
|
932
1804
|
copy_internal("UID MOVE", set, mailbox)
|
933
1805
|
end
|
934
1806
|
|
935
|
-
# Sends a SORT command
|
936
|
-
#
|
1807
|
+
# Sends a {SORT command [RFC5256 §3]}[https://www.rfc-editor.org/rfc/rfc5256#section-3]
|
1808
|
+
# to search a mailbox for messages that match +search_keys+ and return an
|
1809
|
+
# array of message sequence numbers, sorted by +sort_keys+. +search_keys+
|
1810
|
+
# are interpreted the same as for #search.
|
1811
|
+
#
|
1812
|
+
#--
|
1813
|
+
# TODO: describe +sort_keys+
|
1814
|
+
#++
|
1815
|
+
#
|
1816
|
+
# Related: #uid_sort, #search, #uid_search, #thread, #uid_thread
|
1817
|
+
#
|
1818
|
+
# ===== For example:
|
937
1819
|
#
|
938
1820
|
# p imap.sort(["FROM"], ["ALL"], "US-ASCII")
|
939
1821
|
# #=> [1, 2, 3, 5, 6, 7, 8, 4, 9]
|
940
1822
|
# p imap.sort(["DATE"], ["SUBJECT", "hello"], "US-ASCII")
|
941
1823
|
# #=> [6, 7, 8, 1]
|
942
1824
|
#
|
943
|
-
#
|
1825
|
+
# ===== Capabilities
|
1826
|
+
#
|
1827
|
+
# The server's capabilities must include +SORT+
|
1828
|
+
# [RFC5256[https://tools.ietf.org/html/rfc5256]].
|
944
1829
|
def sort(sort_keys, search_keys, charset)
|
945
1830
|
return sort_internal("SORT", sort_keys, search_keys, charset)
|
946
1831
|
end
|
947
1832
|
|
948
|
-
#
|
1833
|
+
# Sends a {UID SORT command [RFC5256 §3]}[https://www.rfc-editor.org/rfc/rfc5256#section-3]
|
1834
|
+
# to search a mailbox for messages that match +search_keys+ and return an
|
1835
|
+
# array of unique identifiers, sorted by +sort_keys+. +search_keys+ are
|
1836
|
+
# interpreted the same as for #search.
|
949
1837
|
#
|
950
|
-
#
|
1838
|
+
# Related: #sort, #search, #uid_search, #thread, #uid_thread
|
1839
|
+
#
|
1840
|
+
# ===== Capabilities
|
1841
|
+
#
|
1842
|
+
# The server's capabilities must include +SORT+
|
1843
|
+
# [RFC5256[https://tools.ietf.org/html/rfc5256]].
|
951
1844
|
def uid_sort(sort_keys, search_keys, charset)
|
952
1845
|
return sort_internal("UID SORT", sort_keys, search_keys, charset)
|
953
1846
|
end
|
954
1847
|
|
955
|
-
#
|
956
|
-
#
|
957
|
-
#
|
958
|
-
#
|
959
|
-
# mailbox:
|
960
|
-
#
|
961
|
-
# imap.add_response_handler { |resp|
|
962
|
-
# if resp.kind_of?(Net::IMAP::UntaggedResponse) and resp.name == "EXISTS"
|
963
|
-
# puts "Mailbox now has #{resp.data} messages"
|
964
|
-
# end
|
965
|
-
# }
|
1848
|
+
# Sends a {THREAD command [RFC5256 §3]}[https://www.rfc-editor.org/rfc/rfc5256#section-3]
|
1849
|
+
# to search a mailbox and return message sequence numbers in threaded
|
1850
|
+
# format, as a ThreadMember tree. +search_keys+ are interpreted the same as
|
1851
|
+
# for #search.
|
966
1852
|
#
|
967
|
-
|
968
|
-
raise ArgumentError, "two Procs are passed" if handler && block
|
969
|
-
@response_handlers.push(block || handler)
|
970
|
-
end
|
971
|
-
|
972
|
-
# Removes the response handler.
|
973
|
-
def remove_response_handler(handler)
|
974
|
-
@response_handlers.delete(handler)
|
975
|
-
end
|
976
|
-
|
977
|
-
# Similar to #search, but returns message sequence numbers in threaded
|
978
|
-
# format, as a Net::IMAP::ThreadMember tree. The supported algorithms
|
979
|
-
# are:
|
1853
|
+
# The supported algorithms are:
|
980
1854
|
#
|
981
1855
|
# ORDEREDSUBJECT:: split into single-level threads according to subject,
|
982
1856
|
# ordered by date.
|
@@ -986,21 +1860,34 @@ module Net
|
|
986
1860
|
# Unlike #search, +charset+ is a required argument. US-ASCII
|
987
1861
|
# and UTF-8 are sample values.
|
988
1862
|
#
|
989
|
-
#
|
1863
|
+
# Related: #uid_thread, #search, #uid_search, #sort, #uid_sort
|
1864
|
+
#
|
1865
|
+
# ===== Capabilities
|
1866
|
+
#
|
1867
|
+
# The server's capabilities must include +THREAD+
|
1868
|
+
# [RFC5256[https://tools.ietf.org/html/rfc5256]].
|
990
1869
|
def thread(algorithm, search_keys, charset)
|
991
1870
|
return thread_internal("THREAD", algorithm, search_keys, charset)
|
992
1871
|
end
|
993
1872
|
|
1873
|
+
# Sends a {UID THREAD command [RFC5256 §3]}[https://www.rfc-editor.org/rfc/rfc5256#section-3]
|
994
1874
|
# Similar to #thread, but returns unique identifiers instead of
|
995
1875
|
# message sequence numbers.
|
996
1876
|
#
|
997
|
-
#
|
1877
|
+
# Related: #thread, #search, #uid_search, #sort, #uid_sort
|
1878
|
+
#
|
1879
|
+
# ===== Capabilities
|
1880
|
+
#
|
1881
|
+
# The server's capabilities must include +THREAD+
|
1882
|
+
# [RFC5256[https://tools.ietf.org/html/rfc5256]].
|
998
1883
|
def uid_thread(algorithm, search_keys, charset)
|
999
1884
|
return thread_internal("UID THREAD", algorithm, search_keys, charset)
|
1000
1885
|
end
|
1001
1886
|
|
1002
|
-
# Sends an IDLE command
|
1003
|
-
#
|
1887
|
+
# Sends an {IDLE command [RFC2177 §3]}[https://www.rfc-editor.org/rfc/rfc6851#section-3]
|
1888
|
+
# {[IMAP4rev2 §6.3.13]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.3.13]
|
1889
|
+
# that waits for notifications of new or expunged messages. Yields
|
1890
|
+
# responses from the server during the IDLE.
|
1004
1891
|
#
|
1005
1892
|
# Use #idle_done to leave IDLE.
|
1006
1893
|
#
|
@@ -1013,6 +1900,13 @@ module Net
|
|
1013
1900
|
# ...
|
1014
1901
|
# end
|
1015
1902
|
# end
|
1903
|
+
#
|
1904
|
+
# Related: #idle_done, #noop, #check
|
1905
|
+
#
|
1906
|
+
# ===== Capabilities
|
1907
|
+
#
|
1908
|
+
# The server's capabilities must include +IDLE+
|
1909
|
+
# [RFC2177[https://tools.ietf.org/html/rfc2177]].
|
1016
1910
|
def idle(timeout = nil, &response_handler)
|
1017
1911
|
raise LocalJumpError, "no block given" unless response_handler
|
1018
1912
|
|
@@ -1043,6 +1937,8 @@ module Net
|
|
1043
1937
|
end
|
1044
1938
|
|
1045
1939
|
# Leaves IDLE.
|
1940
|
+
#
|
1941
|
+
# Related: #idle
|
1046
1942
|
def idle_done
|
1047
1943
|
synchronize do
|
1048
1944
|
if @idle_done_cond.nil?
|
@@ -1052,6 +1948,28 @@ module Net
|
|
1052
1948
|
end
|
1053
1949
|
end
|
1054
1950
|
|
1951
|
+
# Adds a response handler. For example, to detect when
|
1952
|
+
# the server sends a new EXISTS response (which normally
|
1953
|
+
# indicates new messages being added to the mailbox),
|
1954
|
+
# add the following handler after selecting the
|
1955
|
+
# mailbox:
|
1956
|
+
#
|
1957
|
+
# imap.add_response_handler { |resp|
|
1958
|
+
# if resp.kind_of?(Net::IMAP::UntaggedResponse) and resp.name == "EXISTS"
|
1959
|
+
# puts "Mailbox now has #{resp.data} messages"
|
1960
|
+
# end
|
1961
|
+
# }
|
1962
|
+
#
|
1963
|
+
def add_response_handler(handler = nil, &block)
|
1964
|
+
raise ArgumentError, "two Procs are passed" if handler && block
|
1965
|
+
@response_handlers.push(block || handler)
|
1966
|
+
end
|
1967
|
+
|
1968
|
+
# Removes the response handler.
|
1969
|
+
def remove_response_handler(handler)
|
1970
|
+
@response_handlers.delete(handler)
|
1971
|
+
end
|
1972
|
+
|
1055
1973
|
private
|
1056
1974
|
|
1057
1975
|
CRLF = "\r\n" # :nodoc:
|
@@ -1072,9 +1990,7 @@ module Net
|
|
1072
1990
|
#
|
1073
1991
|
# port:: Port number (default value is 143 for imap, or 993 for imaps)
|
1074
1992
|
# ssl:: If +options[:ssl]+ is true, then an attempt will be made
|
1075
|
-
# to use SSL (now TLS) to connect to the server.
|
1076
|
-
# OpenSSL [OSSL] and the Ruby OpenSSL [RSSL] extensions need to
|
1077
|
-
# be installed.
|
1993
|
+
# to use SSL (now TLS) to connect to the server.
|
1078
1994
|
# If +options[:ssl]+ is a hash, it's passed to
|
1079
1995
|
# OpenSSL::SSL::SSLContext#set_params as parameters.
|
1080
1996
|
# open_timeout:: Seconds to wait until a connection is opened
|
@@ -1474,3 +2390,4 @@ require_relative "imap/flags"
|
|
1474
2390
|
require_relative "imap/response_data"
|
1475
2391
|
require_relative "imap/response_parser"
|
1476
2392
|
require_relative "imap/authenticators"
|
2393
|
+
require_relative "imap/sasl"
|