net-imap 0.3.1 → 0.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of net-imap might be problematic. Click here for more details.

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