net-imap 0.3.3 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/net/imap/authenticators.rb +30 -10
- data/lib/net/imap/flags.rb +1 -0
- data/lib/net/imap/sasl/stringprep.rb +6 -2
- data/lib/net/imap.rb +979 -257
- data/rakelib/rfcs.rake +3 -1
- metadata +2 -2
data/lib/net/imap.rb
CHANGED
@@ -23,12 +23,14 @@ end
|
|
23
23
|
|
24
24
|
module Net
|
25
25
|
|
26
|
-
#
|
27
|
-
# Net::IMAP implements Internet Message Access Protocol (IMAP) client
|
26
|
+
# Net::IMAP implements Internet Message Access Protocol (\IMAP) client
|
28
27
|
# functionality. The protocol is described in
|
29
|
-
# [
|
28
|
+
# [IMAP4rev1[https://tools.ietf.org/html/rfc3501]].
|
29
|
+
#--
|
30
|
+
# TODO: and [IMAP4rev2[https://tools.ietf.org/html/rfc9051]].
|
31
|
+
#++
|
30
32
|
#
|
31
|
-
# == IMAP Overview
|
33
|
+
# == \IMAP Overview
|
32
34
|
#
|
33
35
|
# An \IMAP client connects to a server, and then authenticates
|
34
36
|
# itself using either #authenticate or #login. Having
|
@@ -41,12 +43,14 @@ module Net
|
|
41
43
|
# within a hierarchy of directories.
|
42
44
|
#
|
43
45
|
# To work on the messages within a mailbox, the client must
|
44
|
-
# first select that mailbox, using either #select or
|
45
|
-
# read-only access)
|
46
|
-
# selected a mailbox, they enter _selected_ state, and that
|
46
|
+
# first select that mailbox, using either #select or #examine
|
47
|
+
# (for read-only access). Once the client has successfully
|
48
|
+
# selected a mailbox, they enter the "_selected_" state, and that
|
47
49
|
# mailbox becomes the _current_ mailbox, on which mail-item
|
48
50
|
# related commands implicitly operate.
|
49
51
|
#
|
52
|
+
# === Sequence numbers and UIDs
|
53
|
+
#
|
50
54
|
# Messages have two sorts of identifiers: message sequence
|
51
55
|
# numbers and UIDs.
|
52
56
|
#
|
@@ -57,15 +61,31 @@ module Net
|
|
57
61
|
# are expunged from the mailbox, remaining messages have their
|
58
62
|
# sequence numbers "shuffled down" to fill the gaps.
|
59
63
|
#
|
64
|
+
# To avoid sequence number race conditions, servers must not expunge messages
|
65
|
+
# when no command is in progress, nor when responding to #fetch, #store, or
|
66
|
+
# #search. Expunges _may_ be sent during any other command, including
|
67
|
+
# #uid_fetch, #uid_store, and #uid_search. The #noop and #idle commands are
|
68
|
+
# both useful for this side-effect: they allow the server to send all mailbox
|
69
|
+
# updates, including expunges.
|
70
|
+
#
|
60
71
|
# UIDs, on the other hand, are permanently guaranteed not to
|
61
72
|
# identify another message within the same mailbox, even if
|
62
73
|
# the existing message is deleted. UIDs are required to
|
63
74
|
# be assigned in ascending (but not necessarily sequential)
|
64
75
|
# order within a mailbox; this means that if a non-IMAP client
|
65
|
-
# rearranges the order of
|
76
|
+
# rearranges the order of mail items within a mailbox, the
|
66
77
|
# UIDs have to be reassigned. An \IMAP client thus cannot
|
67
78
|
# rearrange message orders.
|
68
79
|
#
|
80
|
+
# === Server capabilities and protocol extensions
|
81
|
+
#
|
82
|
+
# Net::IMAP <em>does not modify its behavior</em> according to server
|
83
|
+
# #capability. Users of the class must check for required capabilities before
|
84
|
+
# issuing commands. Special care should be taken to follow all #capability
|
85
|
+
# requirements for #starttls, #login, and #authenticate.
|
86
|
+
#
|
87
|
+
# See the #capability method for more information.
|
88
|
+
#
|
69
89
|
# == Examples of Usage
|
70
90
|
#
|
71
91
|
# === List sender and subject of all recent messages in the default mailbox
|
@@ -108,7 +128,7 @@ module Net
|
|
108
128
|
#
|
109
129
|
# == Errors
|
110
130
|
#
|
111
|
-
# An IMAP server can send three different types of responses to indicate
|
131
|
+
# An \IMAP server can send three different types of responses to indicate
|
112
132
|
# failure:
|
113
133
|
#
|
114
134
|
# NO:: the attempted command could not be successfully completed. For
|
@@ -116,7 +136,7 @@ module Net
|
|
116
136
|
# the selected mailbox does not exist; etc.
|
117
137
|
#
|
118
138
|
# BAD:: the request from the client does not follow the server's
|
119
|
-
# understanding of the IMAP protocol. This includes attempting
|
139
|
+
# understanding of the \IMAP protocol. This includes attempting
|
120
140
|
# commands from the wrong client state; for instance, attempting
|
121
141
|
# to perform a SEARCH command without having SELECTed a current
|
122
142
|
# mailbox. It can also signal an internal server
|
@@ -150,6 +170,355 @@ module Net
|
|
150
170
|
# between UTF-8 and UTF-16), and Net::IMAP::ResponseParseError is
|
151
171
|
# thrown if a server response is non-parseable.
|
152
172
|
#
|
173
|
+
# == What's here?
|
174
|
+
#
|
175
|
+
# * {Connection control}[rdoc-ref:Net::IMAP@Connection+control+methods]
|
176
|
+
# * {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands]
|
177
|
+
# * {...for any state}[rdoc-ref:Net::IMAP@IMAP+commands+for+any+state]
|
178
|
+
# * {...for the "not authenticated" state}[rdoc-ref:Net::IMAP@IMAP+commands+for+the+-22Not+Authenticated-22+state]
|
179
|
+
# * {...for the "authenticated" state}[rdoc-ref:Net::IMAP@IMAP+commands+for+the+-22Authenticated-22+state]
|
180
|
+
# * {...for the "selected" state}[rdoc-ref:Net::IMAP@IMAP+commands+for+the+-22Selected-22+state]
|
181
|
+
# * {...for the "logout" state}[rdoc-ref:Net::IMAP@IMAP+commands+for+the+-22Logout-22+state]
|
182
|
+
# * {Supported IMAP extensions}[rdoc-ref:Net::IMAP@Supported+IMAP+extensions]
|
183
|
+
# * {Handling server responses}[rdoc-ref:Net::IMAP@Handling+server+responses]
|
184
|
+
#
|
185
|
+
# === Connection control methods
|
186
|
+
#
|
187
|
+
# - Net::IMAP.new: A new client connects immediately and waits for a
|
188
|
+
# successful server greeting before returning the new client object.
|
189
|
+
# - #starttls: Asks the server to upgrade a clear-text connection to use TLS.
|
190
|
+
# - #logout: Tells the server to end the session. Enters the "_logout_" state.
|
191
|
+
# - #disconnect: Disconnects the connection (without sending #logout first).
|
192
|
+
# - #disconnected?: True if the connection has been closed.
|
193
|
+
#
|
194
|
+
# === Core \IMAP commands
|
195
|
+
#
|
196
|
+
# The following commands are defined either by
|
197
|
+
# the [IMAP4rev1[https://tools.ietf.org/html/rfc3501]] base specification, or
|
198
|
+
# by one of the following extensions:
|
199
|
+
# [IDLE[https://tools.ietf.org/html/rfc2177]],
|
200
|
+
# [NAMESPACE[https://tools.ietf.org/html/rfc2342]],
|
201
|
+
# [UNSELECT[https://tools.ietf.org/html/rfc3691]],
|
202
|
+
#--
|
203
|
+
# TODO: [ENABLE[https://tools.ietf.org/html/rfc5161]],
|
204
|
+
# TODO: [LIST-EXTENDED[https://tools.ietf.org/html/rfc5258]],
|
205
|
+
# TODO: [LIST-STATUS[https://tools.ietf.org/html/rfc5819]],
|
206
|
+
#++
|
207
|
+
# [MOVE[https://tools.ietf.org/html/rfc6851]].
|
208
|
+
# These extensions are widely supported by modern IMAP4rev1 servers and have
|
209
|
+
# all been integrated into [IMAP4rev2[https://tools.ietf.org/html/rfc9051]].
|
210
|
+
# <em>Note: Net::IMAP doesn't fully support IMAP4rev2 yet.</em>
|
211
|
+
#
|
212
|
+
#--
|
213
|
+
# TODO: When IMAP4rev2 is supported, add the following to the each of the
|
214
|
+
# appropriate commands below.
|
215
|
+
# Note:: CHECK has been removed from IMAP4rev2.
|
216
|
+
# Note:: LSUB is obsoleted by +LIST-EXTENDED and has been removed from IMAP4rev2.
|
217
|
+
# <em>Some arguments require the +LIST-EXTENDED+ or +IMAP4rev2+ capability.</em>
|
218
|
+
# <em>Requires either the +ENABLE+ or +IMAP4rev2+ capability.</em>
|
219
|
+
# <em>Requires either the +NAMESPACE+ or +IMAP4rev2+ capability.</em>
|
220
|
+
# <em>Requires either the +IDLE+ or +IMAP4rev2+ capability.</em>
|
221
|
+
# <em>Requires either the +UNSELECT+ or +IMAP4rev2+ capability.</em>
|
222
|
+
# <em>Requires either the +UIDPLUS+ or +IMAP4rev2+ capability.</em>
|
223
|
+
# <em>Requires either the +MOVE+ or +IMAP4rev2+ capability.</em>
|
224
|
+
#++
|
225
|
+
#
|
226
|
+
# ==== \IMAP commands for any state
|
227
|
+
#
|
228
|
+
# - #capability: Returns the server's capabilities as an array of strings.
|
229
|
+
#
|
230
|
+
# <em>Capabilities may change after</em> #starttls, #authenticate, or #login
|
231
|
+
# <em>and cached capabilities must be reloaded.</em>
|
232
|
+
# - #noop: Allows the server to send unsolicited untagged #responses.
|
233
|
+
# - #logout: Tells the server to end the session. Enters the "_logout_" state.
|
234
|
+
#
|
235
|
+
# ==== \IMAP commands for the "Not Authenticated" state
|
236
|
+
#
|
237
|
+
# In addition to the universal commands, the following commands are valid in
|
238
|
+
# the "<em>not authenticated</em>" state:
|
239
|
+
#
|
240
|
+
# - #starttls: Upgrades a clear-text connection to use TLS.
|
241
|
+
#
|
242
|
+
# <em>Requires the +STARTTLS+ capability.</em>
|
243
|
+
# - #authenticate: Identifies the client to the server using a {SASL
|
244
|
+
# mechanism}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml].
|
245
|
+
# Enters the "_authenticated_" state.
|
246
|
+
#
|
247
|
+
# <em>Requires the <tt>AUTH=#{mechanism}</tt> capability for the chosen
|
248
|
+
# mechanism.</em>
|
249
|
+
# - #login: Identifies the client to the server using a plain text password.
|
250
|
+
# Using #authenticate is generally preferred. Enters the "_authenticated_"
|
251
|
+
# state.
|
252
|
+
#
|
253
|
+
# <em>The +LOGINDISABLED+ capability</em> <b>must NOT</b> <em>be listed.</em>
|
254
|
+
#
|
255
|
+
# ==== \IMAP commands for the "Authenticated" state
|
256
|
+
#
|
257
|
+
# In addition to the universal commands, the following commands are valid in
|
258
|
+
# the "_authenticated_" state:
|
259
|
+
#
|
260
|
+
#--
|
261
|
+
# - #enable: <em>Not implemented by Net::IMAP, yet.</em>
|
262
|
+
#
|
263
|
+
# <em>Requires the +ENABLE+ capability.</em>
|
264
|
+
#++
|
265
|
+
# - #select: Open a mailbox and enter the "_selected_" state.
|
266
|
+
# - #examine: Open a mailbox read-only, and enter the "_selected_" state.
|
267
|
+
# - #create: Creates a new mailbox.
|
268
|
+
# - #delete: Permanently remove a mailbox.
|
269
|
+
# - #rename: Change the name of a mailbox.
|
270
|
+
# - #subscribe: Adds a mailbox to the "subscribed" set.
|
271
|
+
# - #unsubscribe: Removes a mailbox from the "subscribed" set.
|
272
|
+
# - #list: Returns names and attributes of mailboxes matching a given pattern.
|
273
|
+
# - #namespace: Returns mailbox namespaces, with path prefixes and delimiters.
|
274
|
+
#
|
275
|
+
# <em>Requires the +NAMESPACE+ capability.</em>
|
276
|
+
# - #status: Returns mailbox information, e.g. message count, unseen message
|
277
|
+
# count, +UIDVALIDITY+ and +UIDNEXT+.
|
278
|
+
# - #append: Appends a message to the end of a mailbox.
|
279
|
+
# - #idle: Allows the server to send updates to the client, without the client
|
280
|
+
# needing to poll using #noop.
|
281
|
+
#
|
282
|
+
# <em>Requires the +IDLE+ capability.</em>
|
283
|
+
# - #lsub: Lists mailboxes the user has declared "active" or "subscribed".
|
284
|
+
#--
|
285
|
+
# <em>Replaced by</em> <tt>LIST-EXTENDED</tt> <em>and removed from</em>
|
286
|
+
# +IMAP4rev2+. <em>However, Net::IMAP hasn't implemented</em>
|
287
|
+
# <tt>LIST-EXTENDED</tt> _yet_.
|
288
|
+
#++
|
289
|
+
#
|
290
|
+
# ==== \IMAP commands for the "Selected" state
|
291
|
+
#
|
292
|
+
# In addition to the universal commands and the "authenticated" commands, the
|
293
|
+
# following commands are valid in the "_selected_" state:
|
294
|
+
#
|
295
|
+
# - #close: Closes the mailbox and returns to the "_authenticated_" state,
|
296
|
+
# expunging deleted messages, unless the mailbox was opened as read-only.
|
297
|
+
# - #unselect: Closes the mailbox and returns to the "_authenticated_" state,
|
298
|
+
# without expunging any messages.
|
299
|
+
#
|
300
|
+
# <em>Requires the +UNSELECT+ capability.</em>
|
301
|
+
# - #expunge: Permanently removes messages which have the Deleted flag set.
|
302
|
+
# - #uid_expunge: Restricts #expunge to only remove the specified UIDs.
|
303
|
+
#
|
304
|
+
# <em>Requires the +UIDPLUS+ capability.</em>
|
305
|
+
# - #search, #uid_search: Returns sequence numbers or UIDs of messages that
|
306
|
+
# match the given searching criteria.
|
307
|
+
# - #fetch, #uid_fetch: Returns data associated with a set of messages,
|
308
|
+
# specified by sequence number or UID.
|
309
|
+
# - #store, #uid_store: Alters a message's flags.
|
310
|
+
# - #copy, #uid_copy: Copies the specified messages to the end of the
|
311
|
+
# specified destination mailbox.
|
312
|
+
# - #move, #uid_move: Moves the specified messages to the end of the
|
313
|
+
# specified destination mailbox, expunging them from the current mailbox.
|
314
|
+
#
|
315
|
+
# <em>Requires the +MOVE+ capability.</em>
|
316
|
+
# - #check: Mostly obsolete. Can be replaced with #noop or #idle.
|
317
|
+
#--
|
318
|
+
# <em>Removed from IMAP4rev2.</em>
|
319
|
+
#++
|
320
|
+
#
|
321
|
+
# ==== \IMAP commands for the "Logout" state
|
322
|
+
#
|
323
|
+
# No \IMAP commands are valid in the +logout+ state. If the socket is still
|
324
|
+
# open, Net::IMAP will close it after receiving server confirmation.
|
325
|
+
# Exceptions will be raised by \IMAP commands that have already started and
|
326
|
+
# are waiting for a response, as well as any that are called after logout.
|
327
|
+
#
|
328
|
+
# === Supported \IMAP extensions
|
329
|
+
#
|
330
|
+
# ==== RFC9051: +IMAP4rev2+
|
331
|
+
#
|
332
|
+
# Although IMAP4rev2[https://tools.ietf.org/html/rfc9051] is <em>not supported
|
333
|
+
# yet</em>, Net::IMAP supports several extensions that have been folded into
|
334
|
+
# it: +IDLE+, +MOVE+, +NAMESPACE+, +UIDPLUS+, and +UNSELECT+.
|
335
|
+
#--
|
336
|
+
# TODO: RFC4466, ABNF extensions (automatic support for other extensions)
|
337
|
+
# TODO: +ESEARCH+, ExtendedSearchData
|
338
|
+
# TODO: +SEARCHRES+,
|
339
|
+
# TODO: +ENABLE+,
|
340
|
+
# TODO: +SASL-IR+,
|
341
|
+
# TODO: +LIST-EXTENDED+,
|
342
|
+
# TODO: +LIST-STATUS+,
|
343
|
+
# TODO: +LITERAL-+,
|
344
|
+
# TODO: +BINARY+ (only the FETCH side)
|
345
|
+
# TODO: +SPECIAL-USE+
|
346
|
+
# implicitly supported, but we can do better: Response codes: RFC5530, etc
|
347
|
+
# implicitly supported, but we can do better: <tt>STATUS=SIZE</tt>
|
348
|
+
# implicitly supported, but we can do better: <tt>STATUS DELETED</tt>
|
349
|
+
#++
|
350
|
+
# Commands for these extensions are included with the {Core IMAP
|
351
|
+
# commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands], above. Other supported
|
352
|
+
# extensons are listed below.
|
353
|
+
#
|
354
|
+
# ==== RFC2087: +QUOTA+
|
355
|
+
# - #getquota: returns the resource usage and limits for a quota root
|
356
|
+
# - #getquotaroot: returns the list of quota roots for a mailbox, as well as
|
357
|
+
# their resource usage and limits.
|
358
|
+
# - #setquota: sets the resource limits for a given quota root.
|
359
|
+
#
|
360
|
+
# ==== RFC2177: +IDLE+
|
361
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], so it is also
|
362
|
+
# listed with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
|
363
|
+
# - #idle: Allows the server to send updates to the client, without the client
|
364
|
+
# needing to poll using #noop.
|
365
|
+
#
|
366
|
+
# ==== RFC2342: +NAMESPACE+
|
367
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], so it is also
|
368
|
+
# listed with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
|
369
|
+
# - #namespace: Returns mailbox namespaces, with path prefixes and delimiters.
|
370
|
+
#
|
371
|
+
# ==== RFC2971: +ID+
|
372
|
+
# - #id: exchanges client and server implementation information.
|
373
|
+
#
|
374
|
+
#--
|
375
|
+
# ==== RFC3502: +MULTIAPPEND+
|
376
|
+
# TODO...
|
377
|
+
#++
|
378
|
+
#
|
379
|
+
#--
|
380
|
+
# ==== RFC3516: +BINARY+
|
381
|
+
# TODO...
|
382
|
+
#++
|
383
|
+
#
|
384
|
+
# ==== RFC3691: +UNSELECT+
|
385
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], so it is also
|
386
|
+
# listed with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
|
387
|
+
# - #unselect: Closes the mailbox and returns to the "_authenticated_" state,
|
388
|
+
# without expunging any messages.
|
389
|
+
#
|
390
|
+
# ==== RFC4314: +ACL+
|
391
|
+
# - #getacl: lists the authenticated user's access rights to a mailbox.
|
392
|
+
# - #setacl: sets the access rights for a user on a mailbox
|
393
|
+
#--
|
394
|
+
# TODO: #deleteacl, #listrights, #myrights
|
395
|
+
#++
|
396
|
+
# - *_Note:_* +DELETEACL+, +LISTRIGHTS+, and +MYRIGHTS+ are not supported yet.
|
397
|
+
#
|
398
|
+
# ==== RFC4315: +UIDPLUS+
|
399
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], so it is also
|
400
|
+
# listed with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
|
401
|
+
# - #uid_expunge: Restricts #expunge to only remove the specified UIDs.
|
402
|
+
# - Updates #select, #examine with the +UIDNOTSTICKY+ ResponseCode
|
403
|
+
# - Updates #append with the +APPENDUID+ ResponseCode
|
404
|
+
# - Updates #copy, #move with the +COPYUID+ ResponseCode
|
405
|
+
#
|
406
|
+
#--
|
407
|
+
# ==== RFC4466: Collected Extensions to IMAP4 ABNF
|
408
|
+
# TODO...
|
409
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], this RFC updates
|
410
|
+
# the protocol to enable new optional parameters to many commands: #select,
|
411
|
+
# #examine, #create, #rename, #fetch, #uid_fetch, #store, #uid_store, #search,
|
412
|
+
# #uid_search, and #append. However, specific parameters are not defined.
|
413
|
+
# Extensions to these commands use this syntax whenever possible. Net::IMAP
|
414
|
+
# may be partially compatible with extensions to these commands, even without
|
415
|
+
# any explicit support.
|
416
|
+
#++
|
417
|
+
#
|
418
|
+
#--
|
419
|
+
# ==== RFC4731 +ESEARCH+
|
420
|
+
# TODO...
|
421
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
|
422
|
+
# - Updates #search, #uid_search to accept result options: +MIN+, +MAX+,
|
423
|
+
# +ALL+, +COUNT+, and to return ExtendedSearchData.
|
424
|
+
#++
|
425
|
+
#
|
426
|
+
#--
|
427
|
+
# ==== RFC4959: +SASL-IR+
|
428
|
+
# TODO...
|
429
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
|
430
|
+
# - Updates #authenticate to reduce round-trips for supporting mechanisms.
|
431
|
+
#++
|
432
|
+
#
|
433
|
+
#--
|
434
|
+
# ==== RFC4978: COMPRESS=DEFLATE
|
435
|
+
# TODO...
|
436
|
+
#++
|
437
|
+
#
|
438
|
+
#--
|
439
|
+
# ==== RFC5182 +SEARCHRES+
|
440
|
+
# TODO...
|
441
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
|
442
|
+
# - Updates #search, #uid_search with the +SAVE+ result option.
|
443
|
+
# - Updates #copy, #uid_copy, #fetch, #uid_fetch, #move, #uid_move, #search,
|
444
|
+
# #uid_search, #store, #uid_store, and #uid_expunge with ability to
|
445
|
+
# reference the saved result of a previous #search or #uid_search command.
|
446
|
+
#++
|
447
|
+
#
|
448
|
+
# ==== RFC5256: +SORT+
|
449
|
+
# - #sort, #uid_sort: An alternate version of #search or #uid_search which
|
450
|
+
# sorts the results by specified keys.
|
451
|
+
# ==== RFC5256: +THREAD+
|
452
|
+
# - #thread, #uid_thread: An alternate version of #search or #uid_search,
|
453
|
+
# which arranges the results into ordered groups or threads according to a
|
454
|
+
# chosen algorithm.
|
455
|
+
#
|
456
|
+
#--
|
457
|
+
# ==== RFC5258 +LIST-EXTENDED+
|
458
|
+
# TODO...
|
459
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], this updates the
|
460
|
+
# protocol with new optional parameters to the #list command, adding a few of
|
461
|
+
# its own. Net::IMAP may be forward-compatible with future #list extensions,
|
462
|
+
# even without any explicit support.
|
463
|
+
# - Updates #list to accept selection options: +SUBSCRIBED+, +REMOTE+, and
|
464
|
+
# +RECURSIVEMATCH+, and return options: +SUBSCRIBED+ and +CHILDREN+.
|
465
|
+
#++
|
466
|
+
#
|
467
|
+
#--
|
468
|
+
# ==== RFC5819 +LIST-STATUS+
|
469
|
+
# TODO...
|
470
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
|
471
|
+
# - Updates #list with +STATUS+ return option.
|
472
|
+
#++
|
473
|
+
#
|
474
|
+
# ==== +XLIST+ (non-standard, deprecated)
|
475
|
+
# - #xlist: replaced by +SPECIAL-USE+ attributes in #list responses.
|
476
|
+
#
|
477
|
+
#--
|
478
|
+
# ==== RFC6154 +SPECIAL-USE+
|
479
|
+
# TODO...
|
480
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
|
481
|
+
# - Updates #list with the +SPECIAL-USE+ selection and return options.
|
482
|
+
#++
|
483
|
+
#
|
484
|
+
# ==== RFC6851: +MOVE+
|
485
|
+
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], so it is also
|
486
|
+
# listed with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
|
487
|
+
# - #move, #uid_move: Moves the specified messages to the end of the
|
488
|
+
# specified destination mailbox, expunging them from the current mailbox.
|
489
|
+
#
|
490
|
+
#--
|
491
|
+
# ==== RFC6855: UTF8=ACCEPT
|
492
|
+
# TODO...
|
493
|
+
# ==== RFC6855: UTF8=ONLY
|
494
|
+
# TODO...
|
495
|
+
#++
|
496
|
+
#
|
497
|
+
#--
|
498
|
+
# ==== RFC7888: <tt>LITERAL+</tt>, +LITERAL-+
|
499
|
+
# TODO...
|
500
|
+
# ==== RFC7162: +QRESYNC+
|
501
|
+
# TODO...
|
502
|
+
# ==== RFC7162: +CONDSTORE+
|
503
|
+
# TODO...
|
504
|
+
# ==== RFC8474: +OBJECTID+
|
505
|
+
# TODO...
|
506
|
+
# ==== RFC9208: +QUOTA+
|
507
|
+
# TODO...
|
508
|
+
#++
|
509
|
+
#
|
510
|
+
# === Handling server responses
|
511
|
+
#
|
512
|
+
# - #greeting: The server's initial untagged response, which can indicate a
|
513
|
+
# pre-authenticated connection.
|
514
|
+
# - #responses: The untagged responses, as a hash. Keys are the untagged
|
515
|
+
# response type (e.g. "OK", "FETCH", "FLAGS") and response code (e.g.
|
516
|
+
# "ALERT", "UIDVALIDITY", "UIDNEXT", "TRYCREATE", etc). Values are arrays
|
517
|
+
# of UntaggedResponse or ResponseCode.
|
518
|
+
# - #add_response_handler: Add a block to be called inside the receiver thread
|
519
|
+
# with every server response.
|
520
|
+
# - #remove_response_handler: Remove a previously added response handler.
|
521
|
+
#
|
153
522
|
#
|
154
523
|
# == References
|
155
524
|
#--
|
@@ -332,7 +701,7 @@ module Net
|
|
332
701
|
# * {Character sets}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
|
333
702
|
#
|
334
703
|
class IMAP < Protocol
|
335
|
-
VERSION = "0.3.
|
704
|
+
VERSION = "0.3.4"
|
336
705
|
|
337
706
|
include MonitorMixin
|
338
707
|
if defined?(OpenSSL::SSL)
|
@@ -340,10 +709,12 @@ module Net
|
|
340
709
|
include SSL
|
341
710
|
end
|
342
711
|
|
343
|
-
#
|
712
|
+
# Returns the initial greeting the server, an UntaggedResponse.
|
344
713
|
attr_reader :greeting
|
345
714
|
|
346
|
-
# Returns recorded untagged responses.
|
715
|
+
# Returns recorded untagged responses.
|
716
|
+
#
|
717
|
+
# For example:
|
347
718
|
#
|
348
719
|
# imap.select("inbox")
|
349
720
|
# p imap.responses["EXISTS"][-1]
|
@@ -392,6 +763,8 @@ module Net
|
|
392
763
|
end
|
393
764
|
|
394
765
|
# Disconnects from the server.
|
766
|
+
#
|
767
|
+
# Related: #logout
|
395
768
|
def disconnect
|
396
769
|
return if disconnected?
|
397
770
|
begin
|
@@ -415,20 +788,64 @@ module Net
|
|
415
788
|
end
|
416
789
|
|
417
790
|
# Returns true if disconnected from the server.
|
791
|
+
#
|
792
|
+
# Related: #logout, #disconnect
|
418
793
|
def disconnected?
|
419
794
|
return @sock.closed?
|
420
795
|
end
|
421
796
|
|
422
|
-
# Sends a CAPABILITY command
|
423
|
-
# capabilities that the server supports. Each
|
424
|
-
# is a string.
|
425
|
-
#
|
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.
|
426
848
|
#
|
427
|
-
# Note that the Net::IMAP class does not modify its
|
428
|
-
# behaviour according to the capabilities of the server;
|
429
|
-
# it is up to the user of the class to ensure that
|
430
|
-
# a certain capability is supported by a server before
|
431
|
-
# using it.
|
432
849
|
def capability
|
433
850
|
synchronize do
|
434
851
|
send_command("CAPABILITY")
|
@@ -436,8 +853,9 @@ module Net
|
|
436
853
|
end
|
437
854
|
end
|
438
855
|
|
439
|
-
# Sends an ID command
|
440
|
-
# response, or nil if the server does not
|
856
|
+
# Sends an {ID command [RFC2971 §3.1]}[https://www.rfc-editor.org/rfc/rfc2971#section-3.1]
|
857
|
+
# and returns a hash of the server's response, or nil if the server does not
|
858
|
+
# identify itself.
|
441
859
|
#
|
442
860
|
# Note that the user should first check if the server supports the ID
|
443
861
|
# capability. For example:
|
@@ -453,6 +871,11 @@ module Net
|
|
453
871
|
# end
|
454
872
|
#
|
455
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]]
|
456
879
|
def id(client_id=nil)
|
457
880
|
synchronize do
|
458
881
|
send_command("ID", ClientID.new(client_id))
|
@@ -460,18 +883,60 @@ module Net
|
|
460
883
|
end
|
461
884
|
end
|
462
885
|
|
463
|
-
# Sends a NOOP command
|
886
|
+
# Sends a {NOOP command [IMAP4rev1 §6.1.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.1.2]
|
887
|
+
# to the server.
|
888
|
+
#
|
889
|
+
# This allows the server to send unsolicited untagged EXPUNGE #responses,
|
890
|
+
# but does not execute any client request. \IMAP servers are permitted to
|
891
|
+
# send unsolicited untagged responses at any time, except for `EXPUNGE`.
|
892
|
+
#
|
893
|
+
# * +EXPUNGE+ can only be sent while a command is in progress.
|
894
|
+
# * +EXPUNGE+ must _not_ be sent during #fetch, #store, or #search.
|
895
|
+
# * +EXPUNGE+ may be sent during #uid_fetch, #uid_store, or #uid_search.
|
896
|
+
#
|
897
|
+
# Related: #idle, #check
|
464
898
|
def noop
|
465
899
|
send_command("NOOP")
|
466
900
|
end
|
467
901
|
|
468
|
-
# Sends a LOGOUT command
|
469
|
-
#
|
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
|
470
907
|
def logout
|
471
908
|
send_command("LOGOUT")
|
472
909
|
end
|
473
910
|
|
474
|
-
# Sends a STARTTLS command
|
911
|
+
# Sends a {STARTTLS command [IMAP4rev1 §6.2.1]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.2.1]
|
912
|
+
# to start a TLS session.
|
913
|
+
#
|
914
|
+
# Any +options+ are forwarded to OpenSSL::SSL::SSLContext#set_params.
|
915
|
+
#
|
916
|
+
# This method returns after TLS negotiation and hostname verification are
|
917
|
+
# both successful. Any error indicates that the connection has not been
|
918
|
+
# secured.
|
919
|
+
#
|
920
|
+
# *Note:*
|
921
|
+
# >>>
|
922
|
+
# Any #response_handlers added before STARTTLS should be aware that the
|
923
|
+
# TaggedResponse to STARTTLS is sent clear-text, _before_ TLS negotiation.
|
924
|
+
# TLS negotiation starts immediately after that response.
|
925
|
+
#
|
926
|
+
# Related: Net::IMAP.new, #login, #authenticate
|
927
|
+
#
|
928
|
+
# ===== Capability
|
929
|
+
#
|
930
|
+
# The server's capabilities must include +STARTTLS+.
|
931
|
+
#
|
932
|
+
# Server capabilities may change after #starttls, #login, and #authenticate.
|
933
|
+
# Cached capabilities _must_ be invalidated after this method completes.
|
934
|
+
#
|
935
|
+
# The TaggedResponse to #starttls is sent clear-text, so the server <em>must
|
936
|
+
# *not*</em> send capabilities in the #starttls response and clients <em>must
|
937
|
+
# not</em> use them if they are sent. Servers will generally send an
|
938
|
+
# unsolicited untagged response immeditely _after_ #starttls completes.
|
939
|
+
#
|
475
940
|
def starttls(options = {}, verify = true)
|
476
941
|
send_command("STARTTLS") do |resp|
|
477
942
|
if resp.kind_of?(TaggedResponse) && resp.name == "OK"
|
@@ -486,43 +951,95 @@ module Net
|
|
486
951
|
end
|
487
952
|
end
|
488
953
|
|
489
|
-
#
|
490
|
-
#
|
491
|
-
#
|
492
|
-
#
|
493
|
-
#
|
494
|
-
#
|
495
|
-
# See Net::IMAP::PlainAuthenticator.
|
496
|
-
# CRAM-MD5:: DEPRECATED: Use PLAIN (or DIGEST-MD5) with TLS.
|
497
|
-
# DIGEST-MD5:: DEPRECATED by RFC6331. Must be secured using TLS.
|
498
|
-
# See Net::IMAP::DigestMD5Authenticator.
|
499
|
-
# LOGIN:: DEPRECATED: Use PLAIN.
|
500
|
-
#
|
501
|
-
# Most mechanisms require two args: authentication identity (e.g. username)
|
502
|
-
# and credentials (e.g. a password). But each mechanism requires and allows
|
503
|
-
# different arguments; please consult the documentation for the specific
|
504
|
-
# mechanisms you are using. <em>Several obsolete mechanisms are available
|
505
|
-
# for backwards compatibility. Using deprecated mechanisms will issue
|
506
|
-
# warnings.</em>
|
507
|
-
#
|
508
|
-
# Servers do not support all mechanisms and clients must not attempt to use
|
509
|
-
# a mechanism unless "AUTH=#{mechanism}" is listed as a #capability.
|
510
|
-
# Clients must not attempt to authenticate or #login when +LOGINDISABLED+ is
|
511
|
-
# listed with the capabilities. Server capabilities, especially auth
|
512
|
-
# mechanisms, do change after calling #starttls so they need to be checked
|
513
|
-
# again.
|
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
|
514
960
|
#
|
515
|
-
#
|
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.
|
516
964
|
#
|
517
|
-
#
|
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>
|
518
970
|
#
|
519
|
-
#
|
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.
|
520
992
|
#
|
521
|
-
#
|
522
|
-
#
|
523
|
-
|
524
|
-
|
525
|
-
|
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
|
1039
|
+
#
|
1040
|
+
def authenticate(mechanism, *args, **props, &cb)
|
1041
|
+
authenticator = self.class.authenticator(mechanism, *args, **props, &cb)
|
1042
|
+
send_command("AUTHENTICATE", mechanism) do |resp|
|
526
1043
|
if resp.instance_of?(ContinuationRequest)
|
527
1044
|
data = authenticator.process(resp.data.text.unpack("m")[0])
|
528
1045
|
s = [data].pack("m0")
|
@@ -532,18 +1049,33 @@ module Net
|
|
532
1049
|
end
|
533
1050
|
end
|
534
1051
|
|
535
|
-
# Sends a LOGIN command
|
536
|
-
# the plaintext +password+ authenticating
|
537
|
-
#
|
538
|
-
#
|
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+.
|
539
1059
|
#
|
540
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
|
+
#
|
541
1073
|
def login(user, password)
|
542
1074
|
send_command("LOGIN", user, password)
|
543
1075
|
end
|
544
1076
|
|
545
|
-
# Sends a SELECT command
|
546
|
-
# 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.
|
547
1079
|
#
|
548
1080
|
# After you have selected a mailbox, you may retrieve the number of items in
|
549
1081
|
# that mailbox from <tt>imap.responses["EXISTS"][-1]</tt>, and the number of
|
@@ -555,7 +1087,9 @@ module Net
|
|
555
1087
|
# A Net::IMAP::NoResponseError is raised if the mailbox does not
|
556
1088
|
# exist or is for some reason non-selectable.
|
557
1089
|
#
|
558
|
-
#
|
1090
|
+
# Related: #examine
|
1091
|
+
#
|
1092
|
+
# ===== Capabilities
|
559
1093
|
#
|
560
1094
|
# If [UIDPLUS[https://www.rfc-editor.org/rfc/rfc4315.html]] is supported,
|
561
1095
|
# the server may return an untagged "NO" response with a "UIDNOTSTICKY"
|
@@ -569,12 +1103,15 @@ module Net
|
|
569
1103
|
end
|
570
1104
|
end
|
571
1105
|
|
572
|
-
# Sends a EXAMINE command
|
573
|
-
# in the +mailbox+ can be accessed.
|
574
|
-
# except that the selected +mailbox+ is
|
1106
|
+
# Sends a {EXAMINE command [IMAP4rev1 §6.3.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.2]
|
1107
|
+
# to select a +mailbox+ so that messages in the +mailbox+ can be accessed.
|
1108
|
+
# Behaves the same as #select, except that the selected +mailbox+ is
|
1109
|
+
# identified as read-only.
|
575
1110
|
#
|
576
1111
|
# A Net::IMAP::NoResponseError is raised if the mailbox does not
|
577
1112
|
# exist or is for some reason non-examinable.
|
1113
|
+
#
|
1114
|
+
# Related: #select
|
578
1115
|
def examine(mailbox)
|
579
1116
|
synchronize do
|
580
1117
|
@responses.clear
|
@@ -582,69 +1119,86 @@ module Net
|
|
582
1119
|
end
|
583
1120
|
end
|
584
1121
|
|
585
|
-
# Sends a CREATE command
|
1122
|
+
# Sends a {CREATE command [IMAP4rev1 §6.3.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.3]
|
1123
|
+
# to create a new +mailbox+.
|
586
1124
|
#
|
587
1125
|
# A Net::IMAP::NoResponseError is raised if a mailbox with that name
|
588
1126
|
# cannot be created.
|
1127
|
+
#
|
1128
|
+
# Related: #rename, #delete
|
589
1129
|
def create(mailbox)
|
590
1130
|
send_command("CREATE", mailbox)
|
591
1131
|
end
|
592
1132
|
|
593
|
-
# Sends a DELETE command
|
1133
|
+
# Sends a {DELETE command [IMAP4rev1 §6.3.4]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.4]
|
1134
|
+
# to remove the +mailbox+.
|
594
1135
|
#
|
595
1136
|
# A Net::IMAP::NoResponseError is raised if a mailbox with that name
|
596
1137
|
# cannot be deleted, either because it does not exist or because the
|
597
1138
|
# client does not have permission to delete it.
|
1139
|
+
#
|
1140
|
+
# Related: #create, #rename
|
598
1141
|
def delete(mailbox)
|
599
1142
|
send_command("DELETE", mailbox)
|
600
1143
|
end
|
601
1144
|
|
602
|
-
# Sends a RENAME command
|
603
|
-
# +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+.
|
604
1147
|
#
|
605
1148
|
# A Net::IMAP::NoResponseError is raised if a mailbox with the
|
606
1149
|
# name +mailbox+ cannot be renamed to +newname+ for whatever
|
607
1150
|
# reason; for instance, because +mailbox+ does not exist, or
|
608
1151
|
# because there is already a mailbox with the name +newname+.
|
1152
|
+
#
|
1153
|
+
# Related: #create, #delete
|
609
1154
|
def rename(mailbox, newname)
|
610
1155
|
send_command("RENAME", mailbox, newname)
|
611
1156
|
end
|
612
1157
|
|
613
|
-
# Sends a SUBSCRIBE command
|
614
|
-
# the server's set of "active" or
|
615
|
-
# 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.
|
616
1161
|
#
|
617
1162
|
# A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be
|
618
1163
|
# subscribed to; for instance, because it does not exist.
|
1164
|
+
#
|
1165
|
+
# Related: #unsubscribe, #lsub, #list
|
619
1166
|
def subscribe(mailbox)
|
620
1167
|
send_command("SUBSCRIBE", mailbox)
|
621
1168
|
end
|
622
1169
|
|
623
|
-
# Sends
|
624
|
-
# from the server's set of "active"
|
1170
|
+
# Sends an {UNSUBSCRIBE command [IMAP4rev1 §6.3.7]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.7]
|
1171
|
+
# to remove the specified +mailbox+ name from the server's set of "active"
|
1172
|
+
# or "subscribed" mailboxes.
|
625
1173
|
#
|
626
1174
|
# A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be
|
627
1175
|
# unsubscribed from; for instance, because the client is not currently
|
628
1176
|
# subscribed to it.
|
1177
|
+
#
|
1178
|
+
# Related: #subscribe, #lsub, #list
|
629
1179
|
def unsubscribe(mailbox)
|
630
1180
|
send_command("UNSUBSCRIBE", mailbox)
|
631
1181
|
end
|
632
1182
|
|
633
|
-
# Sends a LIST command
|
634
|
-
# the complete set of all names available
|
635
|
-
# +refname+ provides a context (for instance, a base
|
636
|
-
# in a directory-based mailbox hierarchy). +mailbox+ specifies
|
637
|
-
#
|
638
|
-
#
|
639
|
-
#
|
640
|
-
#
|
641
|
-
#
|
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.
|
642
1192
|
#
|
643
1193
|
# If +refname+ is empty, +mailbox+ is used directly to determine
|
644
1194
|
# which mailboxes to match. If +mailbox+ is empty, the root
|
645
1195
|
# name of +refname+ and the hierarchy delimiter are returned.
|
646
1196
|
#
|
647
|
-
# The return value is an array of
|
1197
|
+
# The return value is an array of MailboxList.
|
1198
|
+
#
|
1199
|
+
# Related: #lsub, MailboxList
|
1200
|
+
#
|
1201
|
+
# ===== For example:
|
648
1202
|
#
|
649
1203
|
# imap.create("foo/bar")
|
650
1204
|
# imap.create("foo/baz")
|
@@ -652,6 +1206,10 @@ module Net
|
|
652
1206
|
# #=> [#<Net::IMAP::MailboxList attr=[:Noselect], delim="/", name="foo/">, \\
|
653
1207
|
# #<Net::IMAP::MailboxList attr=[:Noinferiors, :Marked], delim="/", name="foo/bar">, \\
|
654
1208
|
# #<Net::IMAP::MailboxList attr=[:Noinferiors], delim="/", name="foo/baz">]
|
1209
|
+
#
|
1210
|
+
#--
|
1211
|
+
# TODO: support LIST-EXTENDED extension [RFC5258]. Needed for IMAP4rev2.
|
1212
|
+
#++
|
655
1213
|
def list(refname, mailbox)
|
656
1214
|
synchronize do
|
657
1215
|
send_command("LIST", refname, mailbox)
|
@@ -659,41 +1217,39 @@ module Net
|
|
659
1217
|
end
|
660
1218
|
end
|
661
1219
|
|
662
|
-
# Sends a NAMESPACE command
|
663
|
-
#
|
664
|
-
# namespaces used by a server
|
665
|
-
# 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.
|
666
1224
|
#
|
667
|
-
# The
|
668
|
-
#
|
669
|
-
#
|
670
|
-
# hierarchy delimiter. In that common case, the naive client may not have
|
671
|
-
# 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+.
|
672
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.
|
673
1232
|
# But many servers are configured with the default personal namespace as
|
674
|
-
# e.g.
|
675
|
-
# as the hierarchy delimiter. If the client does not check for
|
676
|
-
# naively assumes it can use the same folder names for all
|
677
|
-
# folder creation (and listing, moving, etc) can lead to
|
1233
|
+
# e.g. <tt>("INBOX." ".")</tt>, placing all personal folders under INBOX,
|
1234
|
+
# with "+.+" as the hierarchy delimiter. If the client does not check for
|
1235
|
+
# this, but naively assumes it can use the same folder names for all
|
1236
|
+
# servers, then folder creation (and listing, moving, etc) can lead to
|
1237
|
+
# errors.
|
678
1238
|
#
|
679
1239
|
# From RFC2342:
|
680
1240
|
#
|
681
1241
|
# Although typically a server will support only a single Personal
|
682
1242
|
# Namespace, and a single Other User's Namespace, circumstances exist
|
683
1243
|
# where there MAY be multiples of these, and a client MUST be prepared
|
684
|
-
# for them.
|
1244
|
+
# for them. If a client is configured such that it is required to create
|
685
1245
|
# a certain mailbox, there can be circumstances where it is unclear which
|
686
|
-
# Personal Namespaces it should create the mailbox in.
|
1246
|
+
# Personal Namespaces it should create the mailbox in. In these
|
687
1247
|
# situations a client SHOULD let the user select which namespaces to
|
688
1248
|
# create the mailbox in.
|
689
1249
|
#
|
690
|
-
#
|
691
|
-
# NAMESPACE capability. The return value is a +Net::IMAP::Namespaces+
|
692
|
-
# object which has +personal+, +other+, and +shared+ fields, each an array
|
693
|
-
# of +Net::IMAP::Namespace+ objects. These arrays will be empty when the
|
694
|
-
# server responds with nil.
|
1250
|
+
# Related: #list, Namespaces, Namespace
|
695
1251
|
#
|
696
|
-
# For example:
|
1252
|
+
# ===== For example:
|
697
1253
|
#
|
698
1254
|
# capabilities = imap.capability
|
699
1255
|
# if capabilities.include?("NAMESPACE")
|
@@ -708,7 +1264,10 @@ module Net
|
|
708
1264
|
# end
|
709
1265
|
# end
|
710
1266
|
#
|
711
|
-
#
|
1267
|
+
# ===== Capabilities
|
1268
|
+
#
|
1269
|
+
# The server's capabilities must include +NAMESPACE+
|
1270
|
+
# [RFC2342[https://tools.ietf.org/html/rfc2342]].
|
712
1271
|
def namespace
|
713
1272
|
synchronize do
|
714
1273
|
send_command("NAMESPACE")
|
@@ -733,7 +1292,7 @@ module Net
|
|
733
1292
|
# The XLIST command is like the LIST command except that the flags
|
734
1293
|
# returned refer to the function of the folder/mailbox, e.g. :Sent
|
735
1294
|
#
|
736
|
-
# The return value is an array of
|
1295
|
+
# The return value is an array of MailboxList objects. For example:
|
737
1296
|
#
|
738
1297
|
# imap.create("foo/bar")
|
739
1298
|
# imap.create("foo/baz")
|
@@ -741,6 +1300,18 @@ module Net
|
|
741
1300
|
# #=> [#<Net::IMAP::MailboxList attr=[:Noselect], delim="/", name="foo/">, \\
|
742
1301
|
# #<Net::IMAP::MailboxList attr=[:Noinferiors, :Marked], delim="/", name="foo/bar">, \\
|
743
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
|
+
#++
|
744
1315
|
def xlist(refname, mailbox)
|
745
1316
|
synchronize do
|
746
1317
|
send_command("XLIST", refname, mailbox)
|
@@ -748,12 +1319,17 @@ module Net
|
|
748
1319
|
end
|
749
1320
|
end
|
750
1321
|
|
751
|
-
# Sends
|
752
|
-
# This command is generally available
|
753
|
-
# If this mailbox exists, it returns an array
|
754
|
-
#
|
1322
|
+
# Sends a {GETQUOTAROOT command [RFC2087 §4.3]}[https://www.rfc-editor.org/rfc/rfc2087#section-4.3]
|
1323
|
+
# along with the specified +mailbox+. This command is generally available
|
1324
|
+
# to both admin and user. If this mailbox exists, it returns an array
|
1325
|
+
# containing objects of type MailboxQuotaRoot and MailboxQuota.
|
1326
|
+
#
|
1327
|
+
# Related: #getquota, #setquota, MailboxQuotaRoot, MailboxQuota
|
1328
|
+
#
|
1329
|
+
# ===== Capabilities
|
755
1330
|
#
|
756
|
-
# The
|
1331
|
+
# The server's capabilities must include +QUOTA+
|
1332
|
+
# [RFC2087[https://tools.ietf.org/html/rfc2087]].
|
757
1333
|
def getquotaroot(mailbox)
|
758
1334
|
synchronize do
|
759
1335
|
send_command("GETQUOTAROOT", mailbox)
|
@@ -764,12 +1340,17 @@ module Net
|
|
764
1340
|
end
|
765
1341
|
end
|
766
1342
|
|
767
|
-
# Sends
|
768
|
-
# If this mailbox exists, then an array
|
769
|
-
#
|
770
|
-
#
|
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.
|
771
1347
|
#
|
772
|
-
#
|
1348
|
+
# Related: #getquotaroot, #setquota, MailboxQuota
|
1349
|
+
#
|
1350
|
+
# ===== Capabilities
|
1351
|
+
#
|
1352
|
+
# The server's capabilities must include +QUOTA+
|
1353
|
+
# [RFC2087[https://tools.ietf.org/html/rfc2087]].
|
773
1354
|
def getquota(mailbox)
|
774
1355
|
synchronize do
|
775
1356
|
send_command("GETQUOTA", mailbox)
|
@@ -777,12 +1358,17 @@ module Net
|
|
777
1358
|
end
|
778
1359
|
end
|
779
1360
|
|
780
|
-
# Sends a SETQUOTA command
|
781
|
-
# +quota+. If +quota+ is nil, then
|
782
|
-
# mailbox. Typically one needs to be logged
|
783
|
-
# 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
|
784
1369
|
#
|
785
|
-
# The
|
1370
|
+
# The server's capabilities must include +QUOTA+
|
1371
|
+
# [RFC2087[https://tools.ietf.org/html/rfc2087]].
|
786
1372
|
def setquota(mailbox, quota)
|
787
1373
|
if quota.nil?
|
788
1374
|
data = '()'
|
@@ -792,11 +1378,17 @@ module Net
|
|
792
1378
|
send_command("SETQUOTA", mailbox, RawData.new(data))
|
793
1379
|
end
|
794
1380
|
|
795
|
-
# Sends
|
796
|
-
# +rights+ that user is to have on that
|
797
|
-
# then that user will be stripped of any
|
1381
|
+
# Sends a {SETACL command [RFC4314 §3.1]}[https://www.rfc-editor.org/rfc/rfc4314#section-3.1]
|
1382
|
+
# along with +mailbox+, +user+ and the +rights+ that user is to have on that
|
1383
|
+
# mailbox. If +rights+ is nil, then that user will be stripped of any
|
1384
|
+
# rights to that mailbox.
|
1385
|
+
#
|
1386
|
+
# Related: #getacl
|
798
1387
|
#
|
799
|
-
#
|
1388
|
+
# ===== Capabilities
|
1389
|
+
#
|
1390
|
+
# The server's capabilities must include +ACL+
|
1391
|
+
# [RFC4314[https://tools.ietf.org/html/rfc4314]].
|
800
1392
|
def setacl(mailbox, user, rights)
|
801
1393
|
if rights.nil?
|
802
1394
|
send_command("SETACL", mailbox, user, "")
|
@@ -805,11 +1397,16 @@ module Net
|
|
805
1397
|
end
|
806
1398
|
end
|
807
1399
|
|
808
|
-
#
|
809
|
-
# If this mailbox exists, an array
|
810
|
-
#
|
1400
|
+
# Sends a {GETACL command [RFC4314 §3.3]}[https://www.rfc-editor.org/rfc/rfc4314#section-3.3]
|
1401
|
+
# along with a specified +mailbox+. If this mailbox exists, an array
|
1402
|
+
# containing objects of MailboxACLItem will be returned.
|
1403
|
+
#
|
1404
|
+
# Related: #setacl, MailboxACLItem
|
811
1405
|
#
|
812
|
-
#
|
1406
|
+
# ===== Capabilities
|
1407
|
+
#
|
1408
|
+
# The server's capabilities must include +ACL+
|
1409
|
+
# [RFC4314[https://tools.ietf.org/html/rfc4314]].
|
813
1410
|
def getacl(mailbox)
|
814
1411
|
synchronize do
|
815
1412
|
send_command("GETACL", mailbox)
|
@@ -817,12 +1414,14 @@ module Net
|
|
817
1414
|
end
|
818
1415
|
end
|
819
1416
|
|
820
|
-
# Sends a LSUB command
|
821
|
-
# of names
|
822
|
-
# "subscribed." +refname+ and +mailbox+ are
|
823
|
-
# for #list.
|
1417
|
+
# Sends a {LSUB command [IMAP4rev1 §6.3.9]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.9]
|
1418
|
+
# and returns a subset of names from the set of names that the user has
|
1419
|
+
# declared as being "active" or "subscribed." +refname+ and +mailbox+ are
|
1420
|
+
# interpreted as for #list.
|
1421
|
+
#
|
1422
|
+
# The return value is an array of MailboxList objects.
|
824
1423
|
#
|
825
|
-
#
|
1424
|
+
# Related: #subscribe, #unsubscribe, #list, MailboxList
|
826
1425
|
def lsub(refname, mailbox)
|
827
1426
|
synchronize do
|
828
1427
|
send_command("LSUB", refname, mailbox)
|
@@ -830,9 +1429,10 @@ module Net
|
|
830
1429
|
end
|
831
1430
|
end
|
832
1431
|
|
833
|
-
# Sends a STATUS
|
834
|
-
# +mailbox+. +attr+ is a list of one
|
835
|
-
# statuses are to be requested. Supported
|
1432
|
+
# Sends a {STATUS commands [IMAP4rev1 §6.3.10]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.10]
|
1433
|
+
# and returns the status of the indicated +mailbox+. +attr+ is a list of one
|
1434
|
+
# or more attributes whose statuses are to be requested. Supported
|
1435
|
+
# attributes include:
|
836
1436
|
#
|
837
1437
|
# MESSAGES:: the number of messages in the mailbox.
|
838
1438
|
# RECENT:: the number of recent messages in the mailbox.
|
@@ -853,11 +1453,12 @@ module Net
|
|
853
1453
|
end
|
854
1454
|
end
|
855
1455
|
|
856
|
-
# Sends
|
857
|
-
# the +mailbox+. The optional +flags+
|
858
|
-
# flags initially passed to the new message. The
|
859
|
-
# +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
|
860
1460
|
# new message; it defaults to the current time.
|
1461
|
+
#
|
861
1462
|
# For example:
|
862
1463
|
#
|
863
1464
|
# imap.append("inbox", <<EOF.gsub(/\n/, "\r\n"), [:Seen], Time.now)
|
@@ -872,12 +1473,13 @@ module Net
|
|
872
1473
|
# not exist (it is not created automatically), or if the flags,
|
873
1474
|
# date_time, or message arguments contain errors.
|
874
1475
|
#
|
875
|
-
#
|
1476
|
+
# ===== Capabilities
|
876
1477
|
#
|
877
1478
|
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
|
878
|
-
# supported
|
879
|
-
#
|
880
|
-
# of the
|
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.
|
881
1483
|
#
|
882
1484
|
#--
|
883
1485
|
# TODO: add MULTIAPPEND support
|
@@ -892,26 +1494,33 @@ module Net
|
|
892
1494
|
send_command("APPEND", mailbox, *args)
|
893
1495
|
end
|
894
1496
|
|
895
|
-
# Sends a CHECK command
|
896
|
-
# selected mailbox. This performs
|
897
|
-
# housekeeping; for instance, reconciling the
|
898
|
-
# 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
|
899
1503
|
def check
|
900
1504
|
send_command("CHECK")
|
901
1505
|
end
|
902
1506
|
|
903
|
-
# Sends a CLOSE command
|
904
|
-
#
|
905
|
-
# messages that have the
|
1507
|
+
# Sends a {CLOSE command [IMAP4rev1 §6.4.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.2]
|
1508
|
+
# to close the currently selected mailbox. The CLOSE command permanently
|
1509
|
+
# removes from the mailbox all messages that have the <tt>\\Deleted</tt>
|
1510
|
+
# flag set.
|
1511
|
+
#
|
1512
|
+
# Related: #unselect
|
906
1513
|
def close
|
907
1514
|
send_command("CLOSE")
|
908
1515
|
end
|
909
1516
|
|
910
|
-
# Sends an {UNSELECT command [
|
911
|
-
# §6.4.2]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.2]
|
912
|
-
# session resources for a mailbox and return to the
|
913
|
-
# This is the same as #close, except that
|
914
|
-
# not removed from the mailbox.
|
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
|
915
1524
|
#
|
916
1525
|
# ===== Capabilities
|
917
1526
|
#
|
@@ -921,8 +1530,11 @@ module Net
|
|
921
1530
|
send_command("UNSELECT")
|
922
1531
|
end
|
923
1532
|
|
1533
|
+
# Sends an {EXPUNGE command [IMAP4rev1 §6.4.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.3]
|
924
1534
|
# Sends a EXPUNGE command to permanently remove from the currently
|
925
1535
|
# selected mailbox all messages that have the \Deleted flag set.
|
1536
|
+
#
|
1537
|
+
# Related: #uid_expunge
|
926
1538
|
def expunge
|
927
1539
|
synchronize do
|
928
1540
|
send_command("EXPUNGE")
|
@@ -930,27 +1542,31 @@ module Net
|
|
930
1542
|
end
|
931
1543
|
end
|
932
1544
|
|
933
|
-
#
|
934
|
-
#
|
935
|
-
# messages that have both the
|
936
|
-
# included in +uid_set+.
|
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+.
|
937
1549
|
#
|
938
|
-
# By using
|
1550
|
+
# By using #uid_expunge instead of #expunge when resynchronizing with
|
939
1551
|
# the server, the client can ensure that it does not inadvertantly
|
940
|
-
# remove any messages that have been marked as
|
1552
|
+
# remove any messages that have been marked as <tt>\\Deleted</tt> by other
|
941
1553
|
# clients between the time that the client was last connected and
|
942
1554
|
# the time the client resynchronizes.
|
943
1555
|
#
|
944
|
-
# Note
|
1556
|
+
# *Note:*
|
1557
|
+
# >>>
|
1558
|
+
# Although the command takes a set of UIDs for its argument, the
|
945
1559
|
# server still returns regular EXPUNGE responses, which contain
|
946
1560
|
# a <em>sequence number</em>. These will be deleted from
|
947
1561
|
# #responses and this method returns them as an array of
|
948
1562
|
# <em>sequence number</em> integers.
|
949
1563
|
#
|
950
|
-
#
|
1564
|
+
# Related: #expunge
|
1565
|
+
#
|
1566
|
+
# ===== Capabilities
|
951
1567
|
#
|
952
|
-
#
|
953
|
-
#
|
1568
|
+
# The server's capabilities must include +UIDPLUS+
|
1569
|
+
# [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]].
|
954
1570
|
def uid_expunge(uid_set)
|
955
1571
|
synchronize do
|
956
1572
|
send_command("UID EXPUNGE", MessageSet.new(uid_set))
|
@@ -958,20 +1574,33 @@ module Net
|
|
958
1574
|
end
|
959
1575
|
end
|
960
1576
|
|
961
|
-
# Sends a SEARCH command
|
962
|
-
#
|
963
|
-
# numbers. +keys+ can either be a
|
964
|
-
# search string, or a single-dimension array of
|
965
|
-
#
|
966
|
-
#
|
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
|
967
1586
|
#
|
968
|
-
#
|
969
|
-
#
|
970
|
-
#
|
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>".
|
971
1599
|
#
|
972
1600
|
# BEFORE <date>:: messages with an internal date strictly before
|
973
|
-
# <date>. The date argument has a format similar
|
974
|
-
# 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.
|
975
1604
|
#
|
976
1605
|
# BODY <string>:: messages that contain <string> within their body.
|
977
1606
|
#
|
@@ -994,21 +1623,26 @@ module Net
|
|
994
1623
|
#
|
995
1624
|
# TO <string>:: messages with <string> in their TO field.
|
996
1625
|
#
|
997
|
-
# For example:
|
1626
|
+
# ===== For example:
|
998
1627
|
#
|
999
1628
|
# p imap.search(["SUBJECT", "hello", "NOT", "NEW"])
|
1000
1629
|
# #=> [1, 6, 7, 8]
|
1630
|
+
#
|
1001
1631
|
def search(keys, charset = nil)
|
1002
1632
|
return search_internal("SEARCH", keys, charset)
|
1003
1633
|
end
|
1004
1634
|
|
1005
|
-
#
|
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.
|
1006
1640
|
def uid_search(keys, charset = nil)
|
1007
1641
|
return search_internal("UID SEARCH", keys, charset)
|
1008
1642
|
end
|
1009
1643
|
|
1010
|
-
# Sends a FETCH command
|
1011
|
-
# 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.
|
1012
1646
|
#
|
1013
1647
|
# The +set+ parameter is a number or a range between two numbers,
|
1014
1648
|
# or an array of those. The number is a message sequence number,
|
@@ -1020,12 +1654,14 @@ module Net
|
|
1020
1654
|
# equivalent to 1..5.
|
1021
1655
|
#
|
1022
1656
|
# +attr+ is a list of attributes to fetch; see the documentation
|
1023
|
-
# for
|
1657
|
+
# for FetchData for a list of valid attributes.
|
1024
1658
|
#
|
1025
|
-
# The return value is an array of
|
1659
|
+
# The return value is an array of FetchData or nil
|
1026
1660
|
# (instead of an empty array) if there is no matching message.
|
1027
1661
|
#
|
1028
|
-
#
|
1662
|
+
# Related: #uid_search, FetchData
|
1663
|
+
#
|
1664
|
+
# ===== For example:
|
1029
1665
|
#
|
1030
1666
|
# p imap.fetch(6..8, "UID")
|
1031
1667
|
# #=> [#<Net::IMAP::FetchData seqno=6, attr={"UID"=>98}>, \\
|
@@ -1046,20 +1682,35 @@ module Net
|
|
1046
1682
|
return fetch_internal("FETCH", set, attr, mod)
|
1047
1683
|
end
|
1048
1684
|
|
1049
|
-
#
|
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
|
1050
1697
|
def uid_fetch(set, attr, mod = nil)
|
1051
1698
|
return fetch_internal("UID FETCH", set, attr, mod)
|
1052
1699
|
end
|
1053
1700
|
|
1054
|
-
# Sends a STORE command
|
1055
|
-
# in the mailbox, in particular their
|
1056
|
-
# is a number, an array of numbers, or a Range
|
1057
|
-
# is a message sequence number. +attr+ is the name of a
|
1058
|
-
# to store: 'FLAGS' will replace the message's flag list
|
1059
|
-
#
|
1060
|
-
#
|
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
|
1061
1710
|
#
|
1062
|
-
#
|
1711
|
+
# Related: #uid_store
|
1712
|
+
#
|
1713
|
+
# ===== For example:
|
1063
1714
|
#
|
1064
1715
|
# p imap.store(6..8, "+FLAGS", [:Deleted])
|
1065
1716
|
# #=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\
|
@@ -1069,110 +1720,137 @@ module Net
|
|
1069
1720
|
return store_internal("STORE", set, attr, flags)
|
1070
1721
|
end
|
1071
1722
|
|
1072
|
-
#
|
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
|
1073
1731
|
def uid_store(set, attr, flags)
|
1074
1732
|
return store_internal("UID STORE", set, attr, flags)
|
1075
1733
|
end
|
1076
1734
|
|
1077
|
-
# Sends a COPY command
|
1078
|
-
#
|
1079
|
-
# a number, an array of numbers, or a
|
1080
|
-
# 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.
|
1081
1739
|
#
|
1082
|
-
#
|
1740
|
+
# Related: #uid_copy
|
1741
|
+
#
|
1742
|
+
# ===== Capabilities
|
1083
1743
|
#
|
1084
1744
|
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
|
1085
1745
|
# supported, the server's response should include a +COPYUID+ response code
|
1086
|
-
# with
|
1087
|
-
# messages, and the assigned UID set of
|
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.
|
1088
1749
|
def copy(set, mailbox)
|
1089
1750
|
copy_internal("COPY", set, mailbox)
|
1090
1751
|
end
|
1091
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
|
+
#
|
1092
1757
|
# Similar to #copy, but +set+ contains unique identifiers.
|
1093
1758
|
#
|
1094
|
-
#
|
1759
|
+
# ===== Capabilities
|
1095
1760
|
#
|
1096
1761
|
# +UIDPLUS+ affects #uid_copy the same way it affects #copy.
|
1097
1762
|
def uid_copy(set, mailbox)
|
1098
1763
|
copy_internal("UID COPY", set, mailbox)
|
1099
1764
|
end
|
1100
1765
|
|
1101
|
-
# Sends a MOVE command
|
1102
|
-
#
|
1103
|
-
#
|
1104
|
-
# a
|
1766
|
+
# Sends a {MOVE command [RFC6851 §3.1]}[https://www.rfc-editor.org/rfc/rfc6851#section-3.1]
|
1767
|
+
# {[IMAP4rev2 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.8]
|
1768
|
+
# to move the specified message(s) to the end of the specified destination
|
1769
|
+
# +mailbox+. The +set+ parameter is a number, an array of numbers, or a
|
1770
|
+
# Range object. The number is a message sequence number.
|
1771
|
+
#
|
1772
|
+
# Related: #uid_move
|
1105
1773
|
#
|
1106
|
-
#
|
1774
|
+
# ===== Capabilities
|
1107
1775
|
#
|
1108
|
-
#
|
1109
|
-
#
|
1776
|
+
# The server's capabilities must include +MOVE+
|
1777
|
+
# [RFC6851[https://tools.ietf.org/html/rfc6851]].
|
1110
1778
|
#
|
1111
1779
|
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
|
1112
|
-
#
|
1113
|
-
#
|
1114
|
-
# source messages, and the assigned UID set of
|
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.
|
1115
1784
|
#
|
1116
1785
|
def move(set, mailbox)
|
1117
1786
|
copy_internal("MOVE", set, mailbox)
|
1118
1787
|
end
|
1119
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
|
+
#
|
1120
1794
|
# Similar to #move, but +set+ contains unique identifiers.
|
1121
1795
|
#
|
1122
|
-
#
|
1796
|
+
# Related: #move
|
1123
1797
|
#
|
1124
|
-
#
|
1125
|
-
#
|
1126
|
-
#
|
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.
|
1127
1803
|
def uid_move(set, mailbox)
|
1128
1804
|
copy_internal("UID MOVE", set, mailbox)
|
1129
1805
|
end
|
1130
1806
|
|
1131
|
-
# Sends a SORT command
|
1132
|
-
#
|
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:
|
1133
1819
|
#
|
1134
1820
|
# p imap.sort(["FROM"], ["ALL"], "US-ASCII")
|
1135
1821
|
# #=> [1, 2, 3, 5, 6, 7, 8, 4, 9]
|
1136
1822
|
# p imap.sort(["DATE"], ["SUBJECT", "hello"], "US-ASCII")
|
1137
1823
|
# #=> [6, 7, 8, 1]
|
1138
1824
|
#
|
1139
|
-
#
|
1825
|
+
# ===== Capabilities
|
1826
|
+
#
|
1827
|
+
# The server's capabilities must include +SORT+
|
1828
|
+
# [RFC5256[https://tools.ietf.org/html/rfc5256]].
|
1140
1829
|
def sort(sort_keys, search_keys, charset)
|
1141
1830
|
return sort_internal("SORT", sort_keys, search_keys, charset)
|
1142
1831
|
end
|
1143
1832
|
|
1144
|
-
#
|
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.
|
1145
1837
|
#
|
1146
|
-
#
|
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]].
|
1147
1844
|
def uid_sort(sort_keys, search_keys, charset)
|
1148
1845
|
return sort_internal("UID SORT", sort_keys, search_keys, charset)
|
1149
1846
|
end
|
1150
1847
|
|
1151
|
-
#
|
1152
|
-
#
|
1153
|
-
#
|
1154
|
-
#
|
1155
|
-
# mailbox:
|
1848
|
+
# Sends a {THREAD command [RFC5256 §3]}[https://www.rfc-editor.org/rfc/rfc5256#section-3]
|
1849
|
+
# to search a mailbox and return message sequence numbers in threaded
|
1850
|
+
# format, as a ThreadMember tree. +search_keys+ are interpreted the same as
|
1851
|
+
# for #search.
|
1156
1852
|
#
|
1157
|
-
#
|
1158
|
-
# if resp.kind_of?(Net::IMAP::UntaggedResponse) and resp.name == "EXISTS"
|
1159
|
-
# puts "Mailbox now has #{resp.data} messages"
|
1160
|
-
# end
|
1161
|
-
# }
|
1162
|
-
#
|
1163
|
-
def add_response_handler(handler = nil, &block)
|
1164
|
-
raise ArgumentError, "two Procs are passed" if handler && block
|
1165
|
-
@response_handlers.push(block || handler)
|
1166
|
-
end
|
1167
|
-
|
1168
|
-
# Removes the response handler.
|
1169
|
-
def remove_response_handler(handler)
|
1170
|
-
@response_handlers.delete(handler)
|
1171
|
-
end
|
1172
|
-
|
1173
|
-
# Similar to #search, but returns message sequence numbers in threaded
|
1174
|
-
# format, as a Net::IMAP::ThreadMember tree. The supported algorithms
|
1175
|
-
# are:
|
1853
|
+
# The supported algorithms are:
|
1176
1854
|
#
|
1177
1855
|
# ORDEREDSUBJECT:: split into single-level threads according to subject,
|
1178
1856
|
# ordered by date.
|
@@ -1182,21 +1860,34 @@ module Net
|
|
1182
1860
|
# Unlike #search, +charset+ is a required argument. US-ASCII
|
1183
1861
|
# and UTF-8 are sample values.
|
1184
1862
|
#
|
1185
|
-
#
|
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]].
|
1186
1869
|
def thread(algorithm, search_keys, charset)
|
1187
1870
|
return thread_internal("THREAD", algorithm, search_keys, charset)
|
1188
1871
|
end
|
1189
1872
|
|
1873
|
+
# Sends a {UID THREAD command [RFC5256 §3]}[https://www.rfc-editor.org/rfc/rfc5256#section-3]
|
1190
1874
|
# Similar to #thread, but returns unique identifiers instead of
|
1191
1875
|
# message sequence numbers.
|
1192
1876
|
#
|
1193
|
-
#
|
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]].
|
1194
1883
|
def uid_thread(algorithm, search_keys, charset)
|
1195
1884
|
return thread_internal("UID THREAD", algorithm, search_keys, charset)
|
1196
1885
|
end
|
1197
1886
|
|
1198
|
-
# Sends an IDLE command
|
1199
|
-
#
|
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.
|
1200
1891
|
#
|
1201
1892
|
# Use #idle_done to leave IDLE.
|
1202
1893
|
#
|
@@ -1209,6 +1900,13 @@ module Net
|
|
1209
1900
|
# ...
|
1210
1901
|
# end
|
1211
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]].
|
1212
1910
|
def idle(timeout = nil, &response_handler)
|
1213
1911
|
raise LocalJumpError, "no block given" unless response_handler
|
1214
1912
|
|
@@ -1239,6 +1937,8 @@ module Net
|
|
1239
1937
|
end
|
1240
1938
|
|
1241
1939
|
# Leaves IDLE.
|
1940
|
+
#
|
1941
|
+
# Related: #idle
|
1242
1942
|
def idle_done
|
1243
1943
|
synchronize do
|
1244
1944
|
if @idle_done_cond.nil?
|
@@ -1248,6 +1948,28 @@ module Net
|
|
1248
1948
|
end
|
1249
1949
|
end
|
1250
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
|
+
|
1251
1973
|
private
|
1252
1974
|
|
1253
1975
|
CRLF = "\r\n" # :nodoc:
|