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