net-imap 0.2.3 → 0.3.4

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.

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
- # [IMAP[https://tools.ietf.org/html/rfc3501]].
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 (for
45
- # read-only access) #examine. Once the client has successfully
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 mailitems within a mailbox, the
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,538 @@ 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: The untagged responses, as a hash. Keys are the untagged
515
+ # response type (e.g. "OK", "FETCH", "FLAGS") and response code (e.g.
516
+ # "ALERT", "UIDVALIDITY", "UIDNEXT", "TRYCREATE", etc). Values are arrays
517
+ # of UntaggedResponse or ResponseCode.
518
+ # - #add_response_handler: Add a block to be called inside the receiver thread
519
+ # with every server response.
520
+ # - #remove_response_handler: Remove a previously added response handler.
521
+ #
153
522
  #
154
523
  # == References
524
+ #--
525
+ # TODO: Consider moving references list to REFERENCES.md or REFERENCES.rdoc.
526
+ #++
155
527
  #
156
- # [[IMAP[https://tools.ietf.org/html/rfc3501]]]
157
- # Crispin, M. "INTERNET MESSAGE ACCESS PROTOCOL - \VERSION 4rev1",
158
- # RFC-3501[https://tools.ietf.org/html/rfc3501], March 2003. (Note:
159
- # obsoletes RFC-2060[https://tools.ietf.org/html/rfc2060], December 1996.)
528
+ # [{IMAP4rev1}[https://www.rfc-editor.org/rfc/rfc3501.html]]::
529
+ # Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - \VERSION 4rev1",
530
+ # RFC 3501, DOI 10.17487/RFC3501, March 2003,
531
+ # <https://www.rfc-editor.org/info/rfc3501>.
160
532
  #
161
- # [[LANGUAGE-TAGS[https://tools.ietf.org/html/rfc1766]]]
162
- # Phillips, A. and Davis, M. "Tags for Identifying Languages",
163
- # RFC-5646[https://tools.ietf.org/html/rfc5646], September 2009.
164
- # (Note: obsoletes
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.)
533
+ # [IMAP-ABNF-EXT[https://www.rfc-editor.org/rfc/rfc4466.html]]::
534
+ # Melnikov, A. and C. Daboo, "Collected Extensions to IMAP4 ABNF",
535
+ # RFC 4466, DOI 10.17487/RFC4466, April 2006,
536
+ # <https://www.rfc-editor.org/info/rfc4466>.
168
537
  #
169
- # [[MD5[https://tools.ietf.org/html/rfc1864]]]
170
- # Myers, J. and M. Rose, "The Content-MD5 Header Field",
171
- # RFC-1864[https://tools.ietf.org/html/rfc1864], October 1995.
538
+ # <em>Note: Net::IMAP cannot parse the entire RFC4466 grammar yet.</em>
539
+ #
540
+ # [{IMAP4rev2}[https://www.rfc-editor.org/rfc/rfc9051.html]]::
541
+ # Melnikov, A., Ed., and B. Leiba, Ed., "Internet Message Access Protocol
542
+ # (\IMAP) - Version 4rev2", RFC 9051, DOI 10.17487/RFC9051, August 2021,
543
+ # <https://www.rfc-editor.org/info/rfc9051>.
544
+ #
545
+ # <em>Note: Net::IMAP is not fully compatible with IMAP4rev2 yet.</em>
546
+ #
547
+ # [IMAP-IMPLEMENTATION[https://www.rfc-editor.org/info/rfc2683]]::
548
+ # Leiba, B., "IMAP4 Implementation Recommendations",
549
+ # RFC 2683, DOI 10.17487/RFC2683, September 1999,
550
+ # <https://www.rfc-editor.org/info/rfc2683>.
172
551
  #
173
- # [[MIME-IMB[https://tools.ietf.org/html/rfc2045]]]
174
- # Freed, N. and N. Borenstein, "MIME (Multipurpose Internet
175
- # Mail Extensions) Part One: Format of Internet Message Bodies",
176
- # RFC-2045[https://tools.ietf.org/html/rfc2045], November 1996.
552
+ # [IMAP-MULTIACCESS[https://www.rfc-editor.org/info/rfc2180]]::
553
+ # Gahrns, M., "IMAP4 Multi-Accessed Mailbox Practice", RFC 2180, DOI
554
+ # 10.17487/RFC2180, July 1997, <https://www.rfc-editor.org/info/rfc2180>.
177
555
  #
178
- # [[RFC-5322[https://tools.ietf.org/html/rfc5322]]]
179
- # Resnick, P., "Internet Message Format",
180
- # RFC-5322[https://tools.ietf.org/html/rfc5322], October 2008.
181
- # (Note: obsoletes
182
- # RFC-2822[https://tools.ietf.org/html/rfc2822], April 2001, and
183
- # RFC-822[https://tools.ietf.org/html/rfc822], August 1982.)
556
+ # [UTF7[https://tools.ietf.org/html/rfc2152]]::
557
+ # Goldsmith, D. and M. Davis, "UTF-7 A Mail-Safe Transformation Format of
558
+ # Unicode", RFC 2152, DOI 10.17487/RFC2152, May 1997,
559
+ # <https://www.rfc-editor.org/info/rfc2152>.
184
560
  #
185
- # [[EXT-QUOTA[https://tools.ietf.org/html/rfc2087]]]
186
- # Myers, J., "IMAP4 QUOTA extension",
187
- # RFC-2087[https://tools.ietf.org/html/rfc2087], January 1997.
561
+ # === Message envelope and body structure
188
562
  #
189
- # [[EXT-NAMESPACE[https://tools.ietf.org/html/rfc2342]]]
190
- # Gahrns, M. and Newman, C., "IMAP4 Namespace",
191
- # RFC-2342[https://tools.ietf.org/html/rfc2342], May 1998.
563
+ # [RFC5322[https://tools.ietf.org/html/rfc5322]]::
564
+ # Resnick, P., Ed., "Internet Message Format",
565
+ # RFC 5322, DOI 10.17487/RFC5322, October 2008,
566
+ # <https://www.rfc-editor.org/info/rfc5322>.
192
567
  #
193
- # [[EXT-ID[https://tools.ietf.org/html/rfc2971]]]
194
- # Showalter, T., "IMAP4 ID extension",
195
- # RFC-2971[https://tools.ietf.org/html/rfc2971], October 2000.
568
+ # <em>Note: obsoletes</em>
569
+ # RFC-2822[https://tools.ietf.org/html/rfc2822]<em> (April 2001) and</em>
570
+ # RFC-822[https://tools.ietf.org/html/rfc822]<em> (August 1982).</em>
196
571
  #
197
- # [[EXT-ACL[https://tools.ietf.org/html/rfc4314]]]
198
- # Melnikov, A., "IMAP4 ACL extension",
199
- # RFC-4314[https://tools.ietf.org/html/rfc4314], December 2005. (Note:
200
- # obsoletes RFC-2086[https://tools.ietf.org/html/rfc2086], January 1997.)
572
+ # [CHARSET[https://tools.ietf.org/html/rfc2978]]::
573
+ # Freed, N. and J. Postel, "IANA Charset Registration Procedures", BCP 19,
574
+ # RFC 2978, DOI 10.17487/RFC2978, October 2000,
575
+ # <https://www.rfc-editor.org/info/rfc2978>.
201
576
  #
202
- # [[EXT-SORT-THREAD[https://tools.ietf.org/html/rfc5256]]]
203
- # Crispin, M. and Muchison, K., "INTERNET MESSAGE ACCESS PROTOCOL - SORT
204
- # and THREAD Extensions", RFC-5256[https://tools.ietf.org/html/rfc5256],
205
- # June 2008.
577
+ # [DISPOSITION[https://tools.ietf.org/html/rfc2183]]::
578
+ # Troost, R., Dorner, S., and K. Moore, Ed., "Communicating Presentation
579
+ # Information in Internet Messages: The Content-Disposition Header
580
+ # Field", RFC 2183, DOI 10.17487/RFC2183, August 1997,
581
+ # <https://www.rfc-editor.org/info/rfc2183>.
206
582
  #
207
- # [[EXT-MOVE[https://tools.ietf.org/html/rfc6851]]]
208
- # Gulbrandsen, A. and Freed, N., "Internet Message Access Protocol (\IMAP) -
209
- # MOVE Extension", RFC-6851[https://tools.ietf.org/html/rfc6851], January
210
- # 2013.
583
+ # [MIME-IMB[https://tools.ietf.org/html/rfc2045]]::
584
+ # Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions
585
+ # (MIME) Part One: Format of Internet Message Bodies",
586
+ # RFC 2045, DOI 10.17487/RFC2045, November 1996,
587
+ # <https://www.rfc-editor.org/info/rfc2045>.
211
588
  #
212
- # [[OSSL]]
213
- # http://www.openssl.org
589
+ # [MIME-IMT[https://tools.ietf.org/html/rfc2046]]::
590
+ # Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions
591
+ # (MIME) Part Two: Media Types", RFC 2046, DOI 10.17487/RFC2046,
592
+ # November 1996, <https://www.rfc-editor.org/info/rfc2046>.
214
593
  #
215
- # [[RSSL]]
216
- # http://savannah.gnu.org/projects/rubypki
594
+ # [MIME-HDRS[https://tools.ietf.org/html/rfc2047]]::
595
+ # Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part Three:
596
+ # Message Header Extensions for Non-ASCII Text",
597
+ # RFC 2047, DOI 10.17487/RFC2047, November 1996,
598
+ # <https://www.rfc-editor.org/info/rfc2047>.
217
599
  #
218
- # [[UTF7[https://tools.ietf.org/html/rfc2152]]]
219
- # Goldsmith, D. and Davis, M., "UTF-7: A Mail-Safe Transformation Format of
220
- # Unicode", RFC-2152[https://tools.ietf.org/html/rfc2152], May 1997.
600
+ # [RFC2231[https://tools.ietf.org/html/rfc2231]]::
601
+ # Freed, N. and K. Moore, "MIME Parameter Value and Encoded Word
602
+ # Extensions: Character Sets, Languages, and Continuations",
603
+ # RFC 2231, DOI 10.17487/RFC2231, November 1997,
604
+ # <https://www.rfc-editor.org/info/rfc2231>.
605
+ #
606
+ # [I18n-HDRS[https://tools.ietf.org/html/rfc6532]]::
607
+ # Yang, A., Steele, S., and N. Freed, "Internationalized Email Headers",
608
+ # RFC 6532, DOI 10.17487/RFC6532, February 2012,
609
+ # <https://www.rfc-editor.org/info/rfc6532>.
610
+ #
611
+ # [LANGUAGE-TAGS[https://www.rfc-editor.org/info/rfc3282]]::
612
+ # Alvestrand, H., "Content Language Headers",
613
+ # RFC 3282, DOI 10.17487/RFC3282, May 2002,
614
+ # <https://www.rfc-editor.org/info/rfc3282>.
615
+ #
616
+ # [LOCATION[https://www.rfc-editor.org/info/rfc2557]]::
617
+ # Palme, J., Hopmann, A., and N. Shelness, "MIME Encapsulation of
618
+ # Aggregate Documents, such as HTML (MHTML)",
619
+ # RFC 2557, DOI 10.17487/RFC2557, March 1999,
620
+ # <https://www.rfc-editor.org/info/rfc2557>.
621
+ #
622
+ # [MD5[https://tools.ietf.org/html/rfc1864]]::
623
+ # Myers, J. and M. Rose, "The Content-MD5 Header Field",
624
+ # RFC 1864, DOI 10.17487/RFC1864, October 1995,
625
+ # <https://www.rfc-editor.org/info/rfc1864>.
626
+ #
627
+ #--
628
+ # TODO: Document IMAP keywords.
629
+ #
630
+ # [RFC3503[https://tools.ietf.org/html/rfc3503]]
631
+ # Melnikov, A., "Message Disposition Notification (MDN)
632
+ # profile for Internet Message Access Protocol (IMAP)",
633
+ # RFC 3503, DOI 10.17487/RFC3503, March 2003,
634
+ # <https://www.rfc-editor.org/info/rfc3503>.
635
+ #++
636
+ #
637
+ # === Supported \IMAP Extensions
638
+ #
639
+ # [QUOTA[https://tools.ietf.org/html/rfc2087]]::
640
+ # Myers, J., "IMAP4 QUOTA extension", RFC 2087, DOI 10.17487/RFC2087,
641
+ # January 1997, <https://www.rfc-editor.org/info/rfc2087>.
642
+ #--
643
+ # TODO: test compatibility with updated QUOTA extension:
644
+ # [QUOTA[https://tools.ietf.org/html/rfc9208]]::
645
+ # Melnikov, A., "IMAP QUOTA Extension", RFC 9208, DOI 10.17487/RFC9208,
646
+ # March 2022, <https://www.rfc-editor.org/info/rfc9208>.
647
+ #++
648
+ # [IDLE[https://tools.ietf.org/html/rfc2177]]::
649
+ # Leiba, B., "IMAP4 IDLE command", RFC 2177, DOI 10.17487/RFC2177,
650
+ # June 1997, <https://www.rfc-editor.org/info/rfc2177>.
651
+ # [NAMESPACE[https://tools.ietf.org/html/rfc2342]]::
652
+ # Gahrns, M. and C. Newman, "IMAP4 Namespace", RFC 2342,
653
+ # DOI 10.17487/RFC2342, May 1998, <https://www.rfc-editor.org/info/rfc2342>.
654
+ # [ID[https://tools.ietf.org/html/rfc2971]]::
655
+ # Showalter, T., "IMAP4 ID extension", RFC 2971, DOI 10.17487/RFC2971,
656
+ # October 2000, <https://www.rfc-editor.org/info/rfc2971>.
657
+ # [ACL[https://tools.ietf.org/html/rfc4314]]::
658
+ # Melnikov, A., "IMAP4 Access Control List (ACL) Extension", RFC 4314,
659
+ # DOI 10.17487/RFC4314, December 2005,
660
+ # <https://www.rfc-editor.org/info/rfc4314>.
661
+ # [UIDPLUS[https://www.rfc-editor.org/rfc/rfc4315.html]]::
662
+ # Crispin, M., "Internet Message Access Protocol (\IMAP) - UIDPLUS
663
+ # extension", RFC 4315, DOI 10.17487/RFC4315, December 2005,
664
+ # <https://www.rfc-editor.org/info/rfc4315>.
665
+ # [SORT[https://tools.ietf.org/html/rfc5256]]::
666
+ # Crispin, M. and K. Murchison, "Internet Message Access Protocol - SORT and
667
+ # THREAD Extensions", RFC 5256, DOI 10.17487/RFC5256, June 2008,
668
+ # <https://www.rfc-editor.org/info/rfc5256>.
669
+ # [THREAD[https://tools.ietf.org/html/rfc5256]]::
670
+ # Crispin, M. and K. Murchison, "Internet Message Access Protocol - SORT and
671
+ # THREAD Extensions", RFC 5256, DOI 10.17487/RFC5256, June 2008,
672
+ # <https://www.rfc-editor.org/info/rfc5256>.
673
+ # [RFC5530[https://www.rfc-editor.org/rfc/rfc5530.html]]::
674
+ # Gulbrandsen, A., "IMAP Response Codes", RFC 5530, DOI 10.17487/RFC5530,
675
+ # May 2009, <https://www.rfc-editor.org/info/rfc5530>.
676
+ # [MOVE[https://tools.ietf.org/html/rfc6851]]::
677
+ # Gulbrandsen, A. and N. Freed, Ed., "Internet Message Access Protocol
678
+ # (\IMAP) - MOVE Extension", RFC 6851, DOI 10.17487/RFC6851, January 2013,
679
+ # <https://www.rfc-editor.org/info/rfc6851>.
680
+ #
681
+ # === IANA registries
682
+ #
683
+ # * {IMAP Capabilities}[http://www.iana.org/assignments/imap4-capabilities]
684
+ # * {IMAP Response Codes}[https://www.iana.org/assignments/imap-response-codes/imap-response-codes.xhtml]
685
+ # * {IMAP Mailbox Name Attributes}[https://www.iana.org/assignments/imap-mailbox-name-attributes/imap-mailbox-name-attributes.xhtml]
686
+ # * {IMAP and JMAP Keywords}[https://www.iana.org/assignments/imap-jmap-keywords/imap-jmap-keywords.xhtml]
687
+ # * {IMAP Threading Algorithms}[https://www.iana.org/assignments/imap-threading-algorithms/imap-threading-algorithms.xhtml]
688
+ #--
689
+ # * {IMAP Quota Resource Types}[http://www.iana.org/assignments/imap4-capabilities#imap-capabilities-2]
690
+ # * [{LIST-EXTENDED options and responses}[https://www.iana.org/assignments/imap-list-extended/imap-list-extended.xhtml]
691
+ # * {IMAP METADATA Server Entry and Mailbox Entry Registries}[https://www.iana.org/assignments/imap-metadata/imap-metadata.xhtml]
692
+ # * {IMAP ANNOTATE Extension Entries and Attributes}[https://www.iana.org/assignments/imap-annotate-extension/imap-annotate-extension.xhtml]
693
+ # * {IMAP URLAUTH Access Identifiers and Prefixes}[https://www.iana.org/assignments/urlauth-access-ids/urlauth-access-ids.xhtml]
694
+ # * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
695
+ #++
696
+ # * {SASL Mechanisms and SASL SCRAM Family Mechanisms}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml]
697
+ # * {Service Name and Transport Protocol Port Number Registry}[https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml]:
698
+ # +imap+: tcp/143, +imaps+: tcp/993
699
+ # * {GSSAPI/Kerberos/SASL Service Names}[https://www.iana.org/assignments/gssapi-service-names/gssapi-service-names.xhtml]:
700
+ # +imap+
701
+ # * {Character sets}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
221
702
  #
222
703
  class IMAP < Protocol
223
- VERSION = "0.2.3"
704
+ VERSION = "0.3.4"
224
705
 
225
706
  include MonitorMixin
226
707
  if defined?(OpenSSL::SSL)
@@ -228,10 +709,12 @@ module Net
228
709
  include SSL
229
710
  end
230
711
 
231
- # Returns an initial greeting response from the server.
712
+ # Returns the initial greeting the server, an UntaggedResponse.
232
713
  attr_reader :greeting
233
714
 
234
- # Returns recorded untagged responses. For example:
715
+ # Returns recorded untagged responses.
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
- # The thread to receive exceptions.
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, and returns an array of
312
- # capabilities that the server supports. Each capability
313
- # is a string. See [IMAP] for a list of possible
314
- # capabilities.
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, and returns a hash of the server's
329
- # response, or nil if the server does not identify itself.
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 [EXT-ID[https://tools.ietf.org/html/rfc2971]] for field definitions.
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 to the server. It does nothing.
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 to inform the server that the client is
358
- # done with the connection.
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 to start TLS session.
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,34 +951,95 @@ module Net
375
951
  end
376
952
  end
377
953
 
378
- # Sends an AUTHENTICATE command to authenticate the client.
379
- # The +auth_type+ parameter is a string that represents
380
- # the authentication mechanism to be used. Currently Net::IMAP
381
- # supports the authentication mechanisms:
382
- #
383
- # LOGIN:: login using cleartext user and password.
384
- # CRAM-MD5:: login with cleartext user and encrypted password
385
- # (see [RFC-2195] for a full description). This
386
- # mechanism requires that the server have the user's
387
- # password stored in clear-text password.
388
- #
389
- # For both of these mechanisms, there should be two +args+: username
390
- # and (cleartext) password. A server may not support one or the other
391
- # of these mechanisms; check #capability for a capability of
392
- # the form "AUTH=LOGIN" or "AUTH=CRAM-MD5".
393
- #
394
- # Authentication is done using the appropriate authenticator object:
395
- # see +add_authenticator+ for more information on plugging in your own
396
- # authenticator.
397
- #
398
- # For example:
399
- #
400
- # imap.authenticate('LOGIN', user, password)
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
401
1039
  #
402
- # A Net::IMAP::NoResponseError is raised if authentication fails.
403
- def authenticate(auth_type, *args)
404
- authenticator = self.class.authenticator(auth_type, *args)
405
- 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|
406
1043
  if resp.instance_of?(ContinuationRequest)
407
1044
  data = authenticator.process(resp.data.text.unpack("m")[0])
408
1045
  s = [data].pack("m0")
@@ -412,28 +1049,53 @@ module Net
412
1049
  end
413
1050
  end
414
1051
 
415
- # Sends a LOGIN command to identify the client and carries
416
- # the plaintext +password+ authenticating this +user+. Note
417
- # that, unlike calling #authenticate with an +auth_type+
418
- # of "LOGIN", #login does *not* use the login authenticator.
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+.
419
1059
  #
420
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
+ #
421
1073
  def login(user, password)
422
1074
  send_command("LOGIN", user, password)
423
1075
  end
424
1076
 
425
- # Sends a SELECT command to select a +mailbox+ so that messages
426
- # 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.
427
1079
  #
428
- # After you have selected a mailbox, you may retrieve the
429
- # number of items in that mailbox from +@responses["EXISTS"][-1]+,
430
- # and the number of recent messages from +@responses["RECENT"][-1]+.
431
- # Note that these values can change if new messages arrive
432
- # during a session; see #add_response_handler for a way of
433
- # detecting this event.
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.
434
1086
  #
435
1087
  # A Net::IMAP::NoResponseError is raised if the mailbox does not
436
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"
437
1099
  def select(mailbox)
438
1100
  synchronize do
439
1101
  @responses.clear
@@ -441,12 +1103,15 @@ module Net
441
1103
  end
442
1104
  end
443
1105
 
444
- # Sends a EXAMINE command to select a +mailbox+ so that messages
445
- # in the +mailbox+ can be accessed. Behaves the same as #select,
446
- # except that the selected +mailbox+ is identified as read-only.
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.
447
1110
  #
448
1111
  # A Net::IMAP::NoResponseError is raised if the mailbox does not
449
1112
  # exist or is for some reason non-examinable.
1113
+ #
1114
+ # Related: #select
450
1115
  def examine(mailbox)
451
1116
  synchronize do
452
1117
  @responses.clear
@@ -454,69 +1119,86 @@ module Net
454
1119
  end
455
1120
  end
456
1121
 
457
- # Sends a CREATE command to create a new +mailbox+.
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+.
458
1124
  #
459
1125
  # A Net::IMAP::NoResponseError is raised if a mailbox with that name
460
1126
  # cannot be created.
1127
+ #
1128
+ # Related: #rename, #delete
461
1129
  def create(mailbox)
462
1130
  send_command("CREATE", mailbox)
463
1131
  end
464
1132
 
465
- # Sends a DELETE command to remove the +mailbox+.
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+.
466
1135
  #
467
1136
  # A Net::IMAP::NoResponseError is raised if a mailbox with that name
468
1137
  # cannot be deleted, either because it does not exist or because the
469
1138
  # client does not have permission to delete it.
1139
+ #
1140
+ # Related: #create, #rename
470
1141
  def delete(mailbox)
471
1142
  send_command("DELETE", mailbox)
472
1143
  end
473
1144
 
474
- # Sends a RENAME command to change the name of the +mailbox+ to
475
- # +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+.
476
1147
  #
477
1148
  # A Net::IMAP::NoResponseError is raised if a mailbox with the
478
1149
  # name +mailbox+ cannot be renamed to +newname+ for whatever
479
1150
  # reason; for instance, because +mailbox+ does not exist, or
480
1151
  # because there is already a mailbox with the name +newname+.
1152
+ #
1153
+ # Related: #create, #delete
481
1154
  def rename(mailbox, newname)
482
1155
  send_command("RENAME", mailbox, newname)
483
1156
  end
484
1157
 
485
- # Sends a SUBSCRIBE command to add the specified +mailbox+ name to
486
- # the server's set of "active" or "subscribed" mailboxes as returned
487
- # 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.
488
1161
  #
489
1162
  # A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be
490
1163
  # subscribed to; for instance, because it does not exist.
1164
+ #
1165
+ # Related: #unsubscribe, #lsub, #list
491
1166
  def subscribe(mailbox)
492
1167
  send_command("SUBSCRIBE", mailbox)
493
1168
  end
494
1169
 
495
- # Sends a UNSUBSCRIBE command to remove the specified +mailbox+ name
496
- # from the server's set of "active" or "subscribed" mailboxes.
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.
497
1173
  #
498
1174
  # A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be
499
1175
  # unsubscribed from; for instance, because the client is not currently
500
1176
  # subscribed to it.
1177
+ #
1178
+ # Related: #subscribe, #lsub, #list
501
1179
  def unsubscribe(mailbox)
502
1180
  send_command("UNSUBSCRIBE", mailbox)
503
1181
  end
504
1182
 
505
- # Sends a LIST command, and returns a subset of names from
506
- # the complete set of all names available to the client.
507
- # +refname+ provides a context (for instance, a base directory
508
- # in a directory-based mailbox hierarchy). +mailbox+ specifies
509
- # a mailbox or (via wildcards) mailboxes under that context.
510
- # Two wildcards may be used in +mailbox+: '*', which matches
511
- # all characters *including* the hierarchy delimiter (for instance,
512
- # '/' on a UNIX-hosted directory-based mailbox hierarchy); and '%',
513
- # which matches all characters *except* the hierarchy delimiter.
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.
514
1192
  #
515
1193
  # If +refname+ is empty, +mailbox+ is used directly to determine
516
1194
  # which mailboxes to match. If +mailbox+ is empty, the root
517
1195
  # name of +refname+ and the hierarchy delimiter are returned.
518
1196
  #
519
- # The return value is an array of +Net::IMAP::MailboxList+. For example:
1197
+ # The return value is an array of MailboxList.
1198
+ #
1199
+ # Related: #lsub, MailboxList
1200
+ #
1201
+ # ===== For example:
520
1202
  #
521
1203
  # imap.create("foo/bar")
522
1204
  # imap.create("foo/baz")
@@ -524,6 +1206,10 @@ module Net
524
1206
  # #=> [#<Net::IMAP::MailboxList attr=[:Noselect], delim="/", name="foo/">, \\
525
1207
  # #<Net::IMAP::MailboxList attr=[:Noinferiors, :Marked], delim="/", name="foo/bar">, \\
526
1208
  # #<Net::IMAP::MailboxList attr=[:Noinferiors], delim="/", name="foo/baz">]
1209
+ #
1210
+ #--
1211
+ # TODO: support LIST-EXTENDED extension [RFC5258]. Needed for IMAP4rev2.
1212
+ #++
527
1213
  def list(refname, mailbox)
528
1214
  synchronize do
529
1215
  send_command("LIST", refname, mailbox)
@@ -531,41 +1217,39 @@ module Net
531
1217
  end
532
1218
  end
533
1219
 
534
- # Sends a NAMESPACE command and returns the namespaces that are available.
535
- # The NAMESPACE command allows a client to discover the prefixes of
536
- # namespaces used by a server for personal mailboxes, other users'
537
- # 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.
538
1224
  #
539
- # The NAMESPACE extension predates [IMAP4rev1[https://tools.ietf.org/html/rfc2501]],
540
- # so most IMAP servers support it. Many popular IMAP servers are configured
541
- # with the default personal namespaces as `("" "/")`: no prefix and "/"
542
- # hierarchy delimiter. In that common case, the naive client may not have
543
- # 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+.
544
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.
545
1232
  # But many servers are configured with the default personal namespace as
546
- # e.g. `("INBOX." ".")`, placing all personal folders under INBOX, with "."
547
- # as the hierarchy delimiter. If the client does not check for this, but
548
- # naively assumes it can use the same folder names for all servers, then
549
- # folder creation (and listing, moving, etc) can lead to errors.
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.
550
1238
  #
551
1239
  # From RFC2342:
552
1240
  #
553
1241
  # Although typically a server will support only a single Personal
554
1242
  # Namespace, and a single Other User's Namespace, circumstances exist
555
1243
  # where there MAY be multiples of these, and a client MUST be prepared
556
- # for them. If a client is configured such that it is required to create
1244
+ # for them. If a client is configured such that it is required to create
557
1245
  # a certain mailbox, there can be circumstances where it is unclear which
558
- # Personal Namespaces it should create the mailbox in. In these
1246
+ # Personal Namespaces it should create the mailbox in. In these
559
1247
  # situations a client SHOULD let the user select which namespaces to
560
1248
  # create the mailbox in.
561
1249
  #
562
- # The user of this method should first check if the server supports the
563
- # NAMESPACE capability. The return value is a +Net::IMAP::Namespaces+
564
- # object which has +personal+, +other+, and +shared+ fields, each an array
565
- # of +Net::IMAP::Namespace+ objects. These arrays will be empty when the
566
- # server responds with nil.
1250
+ # Related: #list, Namespaces, Namespace
567
1251
  #
568
- # For example:
1252
+ # ===== For example:
569
1253
  #
570
1254
  # capabilities = imap.capability
571
1255
  # if capabilities.include?("NAMESPACE")
@@ -580,7 +1264,10 @@ module Net
580
1264
  # end
581
1265
  # end
582
1266
  #
583
- # The NAMESPACE extension is described in [EXT-NAMESPACE[https://tools.ietf.org/html/rfc2342]]
1267
+ # ===== Capabilities
1268
+ #
1269
+ # The server's capabilities must include +NAMESPACE+
1270
+ # [RFC2342[https://tools.ietf.org/html/rfc2342]].
584
1271
  def namespace
585
1272
  synchronize do
586
1273
  send_command("NAMESPACE")
@@ -605,7 +1292,7 @@ module Net
605
1292
  # The XLIST command is like the LIST command except that the flags
606
1293
  # returned refer to the function of the folder/mailbox, e.g. :Sent
607
1294
  #
608
- # The return value is an array of +Net::IMAP::MailboxList+. For example:
1295
+ # The return value is an array of MailboxList objects. For example:
609
1296
  #
610
1297
  # imap.create("foo/bar")
611
1298
  # imap.create("foo/baz")
@@ -613,6 +1300,18 @@ module Net
613
1300
  # #=> [#<Net::IMAP::MailboxList attr=[:Noselect], delim="/", name="foo/">, \\
614
1301
  # #<Net::IMAP::MailboxList attr=[:Noinferiors, :Marked], delim="/", name="foo/bar">, \\
615
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
+ #++
616
1315
  def xlist(refname, mailbox)
617
1316
  synchronize do
618
1317
  send_command("XLIST", refname, mailbox)
@@ -620,12 +1319,17 @@ module Net
620
1319
  end
621
1320
  end
622
1321
 
623
- # Sends the GETQUOTAROOT command along with the specified +mailbox+.
624
- # This command is generally available to both admin and user.
625
- # If this mailbox exists, it returns an array containing objects of type
626
- # Net::IMAP::MailboxQuotaRoot and Net::IMAP::MailboxQuota.
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
1328
+ #
1329
+ # ===== Capabilities
627
1330
  #
628
- # The QUOTA extension is described in [EXT-QUOTA[https://tools.ietf.org/html/rfc2087]]
1331
+ # The server's capabilities must include +QUOTA+
1332
+ # [RFC2087[https://tools.ietf.org/html/rfc2087]].
629
1333
  def getquotaroot(mailbox)
630
1334
  synchronize do
631
1335
  send_command("GETQUOTAROOT", mailbox)
@@ -636,12 +1340,17 @@ module Net
636
1340
  end
637
1341
  end
638
1342
 
639
- # Sends the GETQUOTA command along with specified +mailbox+.
640
- # If this mailbox exists, then an array containing a
641
- # Net::IMAP::MailboxQuota object is returned. This
642
- # command is generally only available to server admin.
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.
643
1347
  #
644
- # The QUOTA extension is described in [EXT-QUOTA[https://tools.ietf.org/html/rfc2087]]
1348
+ # Related: #getquotaroot, #setquota, MailboxQuota
1349
+ #
1350
+ # ===== Capabilities
1351
+ #
1352
+ # The server's capabilities must include +QUOTA+
1353
+ # [RFC2087[https://tools.ietf.org/html/rfc2087]].
645
1354
  def getquota(mailbox)
646
1355
  synchronize do
647
1356
  send_command("GETQUOTA", mailbox)
@@ -649,12 +1358,17 @@ module Net
649
1358
  end
650
1359
  end
651
1360
 
652
- # Sends a SETQUOTA command along with the specified +mailbox+ and
653
- # +quota+. If +quota+ is nil, then +quota+ will be unset for that
654
- # mailbox. Typically one needs to be logged in as a server admin
655
- # 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
656
1367
  #
657
- # The QUOTA extension is described in [EXT-QUOTA[https://tools.ietf.org/html/rfc2087]]
1368
+ # ===== Capabilities
1369
+ #
1370
+ # The server's capabilities must include +QUOTA+
1371
+ # [RFC2087[https://tools.ietf.org/html/rfc2087]].
658
1372
  def setquota(mailbox, quota)
659
1373
  if quota.nil?
660
1374
  data = '()'
@@ -664,11 +1378,17 @@ module Net
664
1378
  send_command("SETQUOTA", mailbox, RawData.new(data))
665
1379
  end
666
1380
 
667
- # Sends the SETACL command along with +mailbox+, +user+ and the
668
- # +rights+ that user is to have on that mailbox. If +rights+ is nil,
669
- # then that user will be stripped of any rights to that mailbox.
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
670
1387
  #
671
- # The ACL extension is described in [EXT-ACL[https://tools.ietf.org/html/rfc4314]]
1388
+ # ===== Capabilities
1389
+ #
1390
+ # The server's capabilities must include +ACL+
1391
+ # [RFC4314[https://tools.ietf.org/html/rfc4314]].
672
1392
  def setacl(mailbox, user, rights)
673
1393
  if rights.nil?
674
1394
  send_command("SETACL", mailbox, user, "")
@@ -677,11 +1397,16 @@ module Net
677
1397
  end
678
1398
  end
679
1399
 
680
- # Send the GETACL command along with a specified +mailbox+.
681
- # If this mailbox exists, an array containing objects of
682
- # Net::IMAP::MailboxACLItem will be returned.
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.
1403
+ #
1404
+ # Related: #setacl, MailboxACLItem
683
1405
  #
684
- # The ACL extension is described in [EXT-ACL[https://tools.ietf.org/html/rfc4314]]
1406
+ # ===== Capabilities
1407
+ #
1408
+ # The server's capabilities must include +ACL+
1409
+ # [RFC4314[https://tools.ietf.org/html/rfc4314]].
685
1410
  def getacl(mailbox)
686
1411
  synchronize do
687
1412
  send_command("GETACL", mailbox)
@@ -689,12 +1414,14 @@ module Net
689
1414
  end
690
1415
  end
691
1416
 
692
- # Sends a LSUB command, and returns a subset of names from the set
693
- # of names that the user has declared as being "active" or
694
- # "subscribed." +refname+ and +mailbox+ are interpreted as
695
- # 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.
1421
+ #
1422
+ # The return value is an array of MailboxList objects.
696
1423
  #
697
- # The return value is an array of +Net::IMAP::MailboxList+.
1424
+ # Related: #subscribe, #unsubscribe, #list, MailboxList
698
1425
  def lsub(refname, mailbox)
699
1426
  synchronize do
700
1427
  send_command("LSUB", refname, mailbox)
@@ -702,9 +1429,10 @@ module Net
702
1429
  end
703
1430
  end
704
1431
 
705
- # Sends a STATUS command, and returns the status of the indicated
706
- # +mailbox+. +attr+ is a list of one or more attributes whose
707
- # statuses are to be requested. Supported attributes include:
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:
708
1436
  #
709
1437
  # MESSAGES:: the number of messages in the mailbox.
710
1438
  # RECENT:: the number of recent messages in the mailbox.
@@ -725,11 +1453,12 @@ module Net
725
1453
  end
726
1454
  end
727
1455
 
728
- # Sends a APPEND command to append the +message+ to the end of
729
- # the +mailbox+. The optional +flags+ argument is an array of
730
- # flags initially passed to the new message. The optional
731
- # +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
732
1460
  # new message; it defaults to the current time.
1461
+ #
733
1462
  # For example:
734
1463
  #
735
1464
  # imap.append("inbox", <<EOF.gsub(/\n/, "\r\n"), [:Seen], Time.now)
@@ -743,6 +1472,18 @@ module Net
743
1472
  # A Net::IMAP::NoResponseError is raised if the mailbox does
744
1473
  # not exist (it is not created automatically), or if the flags,
745
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
+ #++
746
1487
  def append(mailbox, message, flags = nil, date_time = nil)
747
1488
  args = []
748
1489
  if flags
@@ -753,23 +1494,47 @@ module Net
753
1494
  send_command("APPEND", mailbox, *args)
754
1495
  end
755
1496
 
756
- # Sends a CHECK command to request a checkpoint of the currently
757
- # selected mailbox. This performs implementation-specific
758
- # housekeeping; for instance, reconciling the mailbox's
759
- # 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
760
1503
  def check
761
1504
  send_command("CHECK")
762
1505
  end
763
1506
 
764
- # Sends a CLOSE command to close the currently selected mailbox.
765
- # The CLOSE command permanently removes from the mailbox all
766
- # messages that have the \Deleted flag set.
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
767
1513
  def close
768
1514
  send_command("CLOSE")
769
1515
  end
770
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]
771
1534
  # Sends a EXPUNGE command to permanently remove from the currently
772
1535
  # selected mailbox all messages that have the \Deleted flag set.
1536
+ #
1537
+ # Related: #uid_expunge
773
1538
  def expunge
774
1539
  synchronize do
775
1540
  send_command("EXPUNGE")
@@ -777,20 +1542,65 @@ module Net
777
1542
  end
778
1543
  end
779
1544
 
780
- # Sends a SEARCH command to search the mailbox for messages that
781
- # match the given searching criteria, and returns message sequence
782
- # numbers. +keys+ can either be a string holding the entire
783
- # search string, or a single-dimension array of search keywords and
784
- # arguments. The following are some common search criteria;
785
- # see [IMAP] section 6.4.4 for a full list.
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.
1563
+ #
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:
786
1595
  #
787
- # <message set>:: a set of message sequence numbers. ',' indicates
788
- # an interval, ':' indicates a range. For instance,
789
- # '2,10:12,15' means "2,10,11,12,15".
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>".
790
1599
  #
791
1600
  # BEFORE <date>:: messages with an internal date strictly before
792
- # <date>. The date argument has a format similar
793
- # 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.
794
1604
  #
795
1605
  # BODY <string>:: messages that contain <string> within their body.
796
1606
  #
@@ -813,21 +1623,26 @@ module Net
813
1623
  #
814
1624
  # TO <string>:: messages with <string> in their TO field.
815
1625
  #
816
- # For example:
1626
+ # ===== For example:
817
1627
  #
818
1628
  # p imap.search(["SUBJECT", "hello", "NOT", "NEW"])
819
1629
  # #=> [1, 6, 7, 8]
1630
+ #
820
1631
  def search(keys, charset = nil)
821
1632
  return search_internal("SEARCH", keys, charset)
822
1633
  end
823
1634
 
824
- # Similar to #search, but returns unique identifiers.
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.
825
1640
  def uid_search(keys, charset = nil)
826
1641
  return search_internal("UID SEARCH", keys, charset)
827
1642
  end
828
1643
 
829
- # Sends a FETCH command to retrieve data associated with a message
830
- # 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.
831
1646
  #
832
1647
  # The +set+ parameter is a number or a range between two numbers,
833
1648
  # or an array of those. The number is a message sequence number,
@@ -839,12 +1654,14 @@ module Net
839
1654
  # equivalent to 1..5.
840
1655
  #
841
1656
  # +attr+ is a list of attributes to fetch; see the documentation
842
- # for Net::IMAP::FetchData for a list of valid attributes.
1657
+ # for FetchData for a list of valid attributes.
843
1658
  #
844
- # The return value is an array of Net::IMAP::FetchData or nil
1659
+ # The return value is an array of FetchData or nil
845
1660
  # (instead of an empty array) if there is no matching message.
846
1661
  #
847
- # For example:
1662
+ # Related: #uid_search, FetchData
1663
+ #
1664
+ # ===== For example:
848
1665
  #
849
1666
  # p imap.fetch(6..8, "UID")
850
1667
  # #=> [#<Net::IMAP::FetchData seqno=6, attr={"UID"=>98}>, \\
@@ -865,20 +1682,35 @@ module Net
865
1682
  return fetch_internal("FETCH", set, attr, mod)
866
1683
  end
867
1684
 
868
- # Similar to #fetch, but +set+ contains unique identifiers.
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
869
1697
  def uid_fetch(set, attr, mod = nil)
870
1698
  return fetch_internal("UID FETCH", set, attr, mod)
871
1699
  end
872
1700
 
873
- # Sends a STORE command to alter data associated with messages
874
- # in the mailbox, in particular their flags. The +set+ parameter
875
- # is a number, an array of numbers, or a Range object. Each number
876
- # is a message sequence number. +attr+ is the name of a data item
877
- # to store: 'FLAGS' will replace the message's flag list
878
- # with the provided one, '+FLAGS' will add the provided flags,
879
- # and '-FLAGS' will remove them. +flags+ is a list of flags.
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.
880
1708
  #
881
- # The return value is an array of Net::IMAP::FetchData. For example:
1709
+ # The return value is an array of FetchData
1710
+ #
1711
+ # Related: #uid_store
1712
+ #
1713
+ # ===== For example:
882
1714
  #
883
1715
  # p imap.store(6..8, "+FLAGS", [:Deleted])
884
1716
  # #=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\
@@ -888,86 +1720,137 @@ module Net
888
1720
  return store_internal("STORE", set, attr, flags)
889
1721
  end
890
1722
 
891
- # Similar to #store, but +set+ contains unique identifiers.
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
892
1731
  def uid_store(set, attr, flags)
893
1732
  return store_internal("UID STORE", set, attr, flags)
894
1733
  end
895
1734
 
896
- # Sends a COPY command to copy the specified message(s) to the end
897
- # of the specified destination +mailbox+. The +set+ parameter is
898
- # a number, an array of numbers, or a Range object. The number is
899
- # 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.
900
1749
  def copy(set, mailbox)
901
1750
  copy_internal("COPY", set, mailbox)
902
1751
  end
903
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
+ #
904
1757
  # Similar to #copy, but +set+ contains unique identifiers.
1758
+ #
1759
+ # ===== Capabilities
1760
+ #
1761
+ # +UIDPLUS+ affects #uid_copy the same way it affects #copy.
905
1762
  def uid_copy(set, mailbox)
906
1763
  copy_internal("UID COPY", set, mailbox)
907
1764
  end
908
1765
 
909
- # Sends a MOVE command to move the specified message(s) to the end
910
- # of the specified destination +mailbox+. The +set+ parameter is
911
- # a number, an array of numbers, or a Range object. The number is
912
- # a message sequence number.
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.
913
1784
  #
914
- # The MOVE extension is described in [EXT-MOVE[https://tools.ietf.org/html/rfc6851]].
915
1785
  def move(set, mailbox)
916
1786
  copy_internal("MOVE", set, mailbox)
917
1787
  end
918
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
+ #
919
1794
  # Similar to #move, but +set+ contains unique identifiers.
920
1795
  #
921
- # The MOVE extension is described in [EXT-MOVE[https://tools.ietf.org/html/rfc6851]].
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.
922
1803
  def uid_move(set, mailbox)
923
1804
  copy_internal("UID MOVE", set, mailbox)
924
1805
  end
925
1806
 
926
- # Sends a SORT command to sort messages in the mailbox.
927
- # Returns an array of message sequence numbers. For example:
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:
928
1819
  #
929
1820
  # p imap.sort(["FROM"], ["ALL"], "US-ASCII")
930
1821
  # #=> [1, 2, 3, 5, 6, 7, 8, 4, 9]
931
1822
  # p imap.sort(["DATE"], ["SUBJECT", "hello"], "US-ASCII")
932
1823
  # #=> [6, 7, 8, 1]
933
1824
  #
934
- # The SORT extension is described in [EXT-SORT-THREAD[https://tools.ietf.org/html/rfc5256]].
1825
+ # ===== Capabilities
1826
+ #
1827
+ # The server's capabilities must include +SORT+
1828
+ # [RFC5256[https://tools.ietf.org/html/rfc5256]].
935
1829
  def sort(sort_keys, search_keys, charset)
936
1830
  return sort_internal("SORT", sort_keys, search_keys, charset)
937
1831
  end
938
1832
 
939
- # Similar to #sort, but returns an array of unique identifiers.
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.
1837
+ #
1838
+ # Related: #sort, #search, #uid_search, #thread, #uid_thread
940
1839
  #
941
- # The SORT extension is described in [EXT-SORT-THREAD[https://tools.ietf.org/html/rfc5256]].
1840
+ # ===== Capabilities
1841
+ #
1842
+ # The server's capabilities must include +SORT+
1843
+ # [RFC5256[https://tools.ietf.org/html/rfc5256]].
942
1844
  def uid_sort(sort_keys, search_keys, charset)
943
1845
  return sort_internal("UID SORT", sort_keys, search_keys, charset)
944
1846
  end
945
1847
 
946
- # Adds a response handler. For example, to detect when
947
- # the server sends a new EXISTS response (which normally
948
- # indicates new messages being added to the mailbox),
949
- # add the following handler after selecting the
950
- # mailbox:
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.
951
1852
  #
952
- # imap.add_response_handler { |resp|
953
- # if resp.kind_of?(Net::IMAP::UntaggedResponse) and resp.name == "EXISTS"
954
- # puts "Mailbox now has #{resp.data} messages"
955
- # end
956
- # }
957
- #
958
- def add_response_handler(handler = nil, &block)
959
- raise ArgumentError, "two Procs are passed" if handler && block
960
- @response_handlers.push(block || handler)
961
- end
962
-
963
- # Removes the response handler.
964
- def remove_response_handler(handler)
965
- @response_handlers.delete(handler)
966
- end
967
-
968
- # Similar to #search, but returns message sequence numbers in threaded
969
- # format, as a Net::IMAP::ThreadMember tree. The supported algorithms
970
- # are:
1853
+ # The supported algorithms are:
971
1854
  #
972
1855
  # ORDEREDSUBJECT:: split into single-level threads according to subject,
973
1856
  # ordered by date.
@@ -977,21 +1860,34 @@ module Net
977
1860
  # Unlike #search, +charset+ is a required argument. US-ASCII
978
1861
  # and UTF-8 are sample values.
979
1862
  #
980
- # The THREAD extension is described in [EXT-SORT-THREAD[https://tools.ietf.org/html/rfc5256]].
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]].
981
1869
  def thread(algorithm, search_keys, charset)
982
1870
  return thread_internal("THREAD", algorithm, search_keys, charset)
983
1871
  end
984
1872
 
1873
+ # Sends a {UID THREAD command [RFC5256 §3]}[https://www.rfc-editor.org/rfc/rfc5256#section-3]
985
1874
  # Similar to #thread, but returns unique identifiers instead of
986
1875
  # message sequence numbers.
987
1876
  #
988
- # The THREAD extension is described in [EXT-SORT-THREAD[https://tools.ietf.org/html/rfc5256]].
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]].
989
1883
  def uid_thread(algorithm, search_keys, charset)
990
1884
  return thread_internal("UID THREAD", algorithm, search_keys, charset)
991
1885
  end
992
1886
 
993
- # Sends an IDLE command that waits for notifications of new or expunged
994
- # messages. Yields responses from the server during the IDLE.
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.
995
1891
  #
996
1892
  # Use #idle_done to leave IDLE.
997
1893
  #
@@ -1004,6 +1900,13 @@ module Net
1004
1900
  # ...
1005
1901
  # end
1006
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]].
1007
1910
  def idle(timeout = nil, &response_handler)
1008
1911
  raise LocalJumpError, "no block given" unless response_handler
1009
1912
 
@@ -1034,6 +1937,8 @@ module Net
1034
1937
  end
1035
1938
 
1036
1939
  # Leaves IDLE.
1940
+ #
1941
+ # Related: #idle
1037
1942
  def idle_done
1038
1943
  synchronize do
1039
1944
  if @idle_done_cond.nil?
@@ -1043,6 +1948,28 @@ module Net
1043
1948
  end
1044
1949
  end
1045
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
+
1046
1973
  private
1047
1974
 
1048
1975
  CRLF = "\r\n" # :nodoc:
@@ -1063,9 +1990,7 @@ module Net
1063
1990
  #
1064
1991
  # port:: Port number (default value is 143 for imap, or 993 for imaps)
1065
1992
  # ssl:: If +options[:ssl]+ is true, then an attempt will be made
1066
- # to use SSL (now TLS) to connect to the server. For this to work
1067
- # OpenSSL [OSSL] and the Ruby OpenSSL [RSSL] extensions need to
1068
- # be installed.
1993
+ # to use SSL (now TLS) to connect to the server.
1069
1994
  # If +options[:ssl]+ is a hash, it's passed to
1070
1995
  # OpenSSL::SSL::SSLContext#set_params as parameters.
1071
1996
  # open_timeout:: Seconds to wait until a connection is opened
@@ -1465,3 +2390,4 @@ require_relative "imap/flags"
1465
2390
  require_relative "imap/response_data"
1466
2391
  require_relative "imap/response_parser"
1467
2392
  require_relative "imap/authenticators"
2393
+ require_relative "imap/sasl"