@@ -539,6 +539,12 @@ module Net
539
539
# ESearchResult#partial return data.
540
540
# - Updates #uid_fetch with the +partial+ modifier.
541
541
#
542
+ # ==== RFC9586: +UIDONLY+
543
+ # - Updates #enable with +UIDONLY+ parameter.
544
+ # - Updates #uid_fetch and #uid_store to return +UIDFETCH+ response.
545
+ # - Updates #expunge and #uid_expunge to return +VANISHED+ response.
546
+ # - Prohibits use of message sequence numbers in responses or requests.
547
+ #
542
548
# == References
543
549
#
544
550
# [{IMAP4rev1}[https://www.rfc-editor.org/rfc/rfc3501.html]]::
@@ -711,6 +717,11 @@ module Net
711
717
# "IMAP PARTIAL Extension for Paged SEARCH and FETCH", RFC 9394,
712
718
# DOI 10.17487/RFC9394, June 2023,
713
719
# <https://www.rfc-editor.org/info/rfc9394>.
720
+ # [UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.pdf]]::
721
+ # Melnikov, A., Achuthan, A., Nagulakonda, V., Singh, A., and L. Alves,
722
+ # "\IMAP Extension for Using and Returning Unique Identifiers (UIDs) Only",
723
+ # RFC 9586, DOI 10.17487/RFC9586, May 2024,
724
+ # <https://www.rfc-editor.org/info/rfc9586>.
714
725
#
715
726
# === IANA registries
716
727
# * {IMAP Capabilities}[http://www.iana.org/assignments/imap4-capabilities]
@@ -724,7 +735,7 @@ module Net
724
735
# * {GSSAPI/Kerberos/SASL Service Names}[https://www.iana.org/assignments/gssapi-service-names/gssapi-service-names.xhtml]:
725
736
# +imap+
726
737
# * {Character sets}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
727
- # ===== For currently unsupported features:
738
+ # ==== For currently unsupported features:
728
739
# * {IMAP Quota Resource Types}[http://www.iana.org/assignments/imap4-capabilities#imap-capabilities-2]
729
740
# * {LIST-EXTENDED options and responses}[https://www.iana.org/assignments/imap-list-extended/imap-list-extended.xhtml]
730
741
# * {IMAP METADATA Server Entry and Mailbox Entry Registries}[https://www.iana.org/assignments/imap-metadata/imap-metadata.xhtml]
@@ -2366,6 +2377,9 @@ def uid_expunge(uid_set)
2366
2377
# result = imap.search(["SUBJECT", "hi there", "not", "new"])
2367
2378
# #=> Net::IMAP::SearchResult[1, 6, 7, 8, modseq: 5594]
2368
2379
# result.modseq # => 5594
2380
+ #
2381
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled,
2382
+ # the +SEARCH+ command is prohibited. Use #uid_search instead.
2369
2383
def search ( ...)
2370
2384
search_internal ( "SEARCH" , ...)
2371
2385
end
@@ -2383,6 +2397,16 @@ def search(...)
2383
2397
# capability has been enabled.
2384
2398
#
2385
2399
# See #search for documentation of parameters.
2400
+ #
2401
+ # ==== Capabilities
2402
+ #
2403
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled,
2404
+ # #uid_search must be used instead of #search, and the <tt><message
2405
+ # set></tt> search criterion is prohibited. Use +ALL+ or <tt>UID
2406
+ # sequence-set</tt> instead.
2407
+ #
2408
+ # Otherwise, #uid_search is updated by extensions in the same way as
2409
+ # #search.
2386
2410
def uid_search ( ...)
2387
2411
search_internal ( "UID SEARCH" , ...)
2388
2412
end
@@ -2397,8 +2421,8 @@ def uid_search(...)
2397
2421
# to {SequenceSet[...]}[rdoc-ref:SequenceSet@Creating+sequence+sets].
2398
2422
# (For UIDs, use #uid_fetch instead.)
2399
2423
#
2400
- # +attr+ is a list of attributes to fetch; see the documentation
2401
- # for FetchData for a list of valid attributes.
2424
+ # +attr+ is a list of attributes to fetch; see FetchStruct documentation for
2425
+ # a list of supported attributes.
2402
2426
#
2403
2427
# +changedsince+ is an optional integer mod-sequence. It limits results to
2404
2428
# messages with a mod-sequence greater than +changedsince+.
@@ -2427,19 +2451,22 @@ def uid_search(...)
2427
2451
#
2428
2452
# ==== Capabilities
2429
2453
#
2430
- # Many extensions define new message +attr+ names. See FetchData for a list
2431
- # of supported extension fields.
2454
+ # Many extensions define new message +attr+ names. See FetchStruct for a
2455
+ # list of supported extension fields.
2432
2456
#
2433
2457
# The server's capabilities must include +CONDSTORE+
2434
2458
# {[RFC7162]}[https://tools.ietf.org/html/rfc7162] in order to use the
2435
2459
# +changedsince+ argument. Using +changedsince+ implicitly enables the
2436
2460
# +CONDSTORE+ extension.
2461
+ #
2462
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled, the
2463
+ # +FETCH+ command is prohibited. Use #uid_fetch instead.
2437
2464
def fetch ( ...)
2438
2465
fetch_internal ( "FETCH" , ...)
2439
2466
end
2440
2467
2441
2468
# :call-seq:
2442
- # uid_fetch(set, attr, changedsince: nil, partial: nil) -> array of FetchData
2469
+ # uid_fetch(set, attr, changedsince: nil, partial: nil) -> array of FetchData (or UIDFetchData)
2443
2470
#
2444
2471
# Sends a {UID FETCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
2445
2472
# to retrieve data associated with a message in the mailbox.
@@ -2491,7 +2518,11 @@ def fetch(...)
2491
2518
# {[RFC9394]}[https://rfc-editor.org/rfc/rfc9394] in order to use the
2492
2519
# +partial+ argument.
2493
2520
#
2494
- # Otherwise, the same as #fetch.
2521
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled,
2522
+ # #uid_fetch must be used instead of #fetch, and UIDFetchData will be
2523
+ # returned instead of FetchData.
2524
+ #
2525
+ # Otherwise, #uid_fetch is updated by extensions in the same way as #fetch.
2495
2526
def uid_fetch ( ...)
2496
2527
fetch_internal ( "UID FETCH" , ...)
2497
2528
end
@@ -2539,12 +2570,15 @@ def uid_fetch(...)
2539
2570
# {[RFC7162]}[https://tools.ietf.org/html/rfc7162] in order to use the
2540
2571
# +unchangedsince+ argument. Using +unchangedsince+ implicitly enables the
2541
2572
# +CONDSTORE+ extension.
2573
+ #
2574
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled, the
2575
+ # +STORE+ command is prohibited. Use #uid_store instead.
2542
2576
def store ( set , attr , flags , unchangedsince : nil )
2543
2577
store_internal ( "STORE" , set , attr , flags , unchangedsince : unchangedsince )
2544
2578
end
2545
2579
2546
2580
# :call-seq:
2547
- # uid_store(set, attr, value, unchangedsince: nil) -> array of FetchData
2581
+ # uid_store(set, attr, value, unchangedsince: nil) -> array of FetchData (or UIDFetchData)
2548
2582
#
2549
2583
# Sends a {UID STORE command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
2550
2584
# to alter data associated with messages in the mailbox, in particular their
@@ -2556,7 +2590,12 @@ def store(set, attr, flags, unchangedsince: nil)
2556
2590
# Related: #store
2557
2591
#
2558
2592
# ==== Capabilities
2559
- # Same as #store.
2593
+ #
2594
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled,
2595
+ # #uid_store must be used instead of #store, and UIDFetchData will be
2596
+ # returned instead of FetchData.
2597
+ #
2598
+ # Otherwise, #uid_store is updated by extensions in the same way as #store.
2560
2599
def uid_store ( set , attr , flags , unchangedsince : nil )
2561
2600
store_internal ( "UID STORE" , set , attr , flags , unchangedsince : unchangedsince )
2562
2601
end
@@ -2575,6 +2614,9 @@ def uid_store(set, attr, flags, unchangedsince: nil)
2575
2614
# with UIDPlusData. This will report the UIDVALIDITY of the destination
2576
2615
# mailbox, the UID set of the source messages, and the assigned UID set of
2577
2616
# the moved messages.
2617
+ #
2618
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled, the
2619
+ # +COPY+ command is prohibited. Use #uid_copy instead.
2578
2620
def copy ( set , mailbox )
2579
2621
copy_internal ( "COPY" , set , mailbox )
2580
2622
end
@@ -2587,7 +2629,10 @@ def copy(set, mailbox)
2587
2629
#
2588
2630
# ==== Capabilities
2589
2631
#
2590
- # +UIDPLUS+ affects #uid_copy the same way it affects #copy.
2632
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] in enabled,
2633
+ # #uid_copy must be used instead of #copy.
2634
+ #
2635
+ # Otherwise, #uid_copy is updated by extensions in the same way as #copy.
2591
2636
def uid_copy ( set , mailbox )
2592
2637
copy_internal ( "UID COPY" , set , mailbox )
2593
2638
end
@@ -2611,6 +2656,8 @@ def uid_copy(set, mailbox)
2611
2656
# mailbox, the UID set of the source messages, and the assigned UID set of
2612
2657
# the moved messages.
2613
2658
#
2659
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled, the
2660
+ # +MOVE+ command is prohibited. Use #uid_move instead.
2614
2661
def move ( set , mailbox )
2615
2662
copy_internal ( "MOVE" , set , mailbox )
2616
2663
end
@@ -2626,9 +2673,13 @@ def move(set, mailbox)
2626
2673
#
2627
2674
# ==== Capabilities
2628
2675
#
2629
- # Same as #move: The server's capabilities must include +MOVE+
2630
- # [RFC6851[https://tools.ietf.org/html/rfc6851]]. +UIDPLUS+ also affects
2631
- # #uid_move the same way it affects #move.
2676
+ # The server's capabilities must include either +IMAP4rev2+ or +MOVE+
2677
+ # [RFC6851[https://tools.ietf.org/html/rfc6851]].
2678
+ #
2679
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled,
2680
+ # #uid_move must be used instead of #move.
2681
+ #
2682
+ # Otherwise, #uid_move is updated by extensions in the same way as #move.
2632
2683
def uid_move ( set , mailbox )
2633
2684
copy_internal ( "UID MOVE" , set , mailbox )
2634
2685
end
@@ -2773,6 +2824,16 @@ def uid_thread(algorithm, search_keys, charset)
2773
2824
# selected. For convenience, <tt>enable("UTF8=ONLY")</tt> is aliased to
2774
2825
# <tt>enable("UTF8=ACCEPT")</tt>.
2775
2826
#
2827
+ # [+UIDONLY+ {[RFC9586]}[https://www.rfc-editor.org/rfc/rfc9586.pdf]]
2828
+ #
2829
+ # When UIDONLY is enabled, the #fetch, #store, #search, #copy, and #move
2830
+ # commands are prohibited and result in a tagged BAD response. Clients
2831
+ # should instead use uid_fetch, uid_store, uid_search, uid_copy, or
2832
+ # uid_move, respectively. All +FETCH+ responses that would be returned are
2833
+ # replaced by +UIDFETCH+ responses. All +EXPUNGED+ responses that would be
2834
+ # returned are replaced by +VANISHED+ responses. The "<sequence set>"
2835
+ # uid_search criterion is prohibited.
2836
+ #
2776
2837
# ===== Unsupported capabilities
2777
2838
#
2778
2839
# *Note:* Some extensions that use ENABLE permit the server to send syntax
@@ -3458,26 +3519,27 @@ def fetch_internal(cmd, set, attr, mod = nil, partial: nil, changedsince: nil)
3458
3519
}
3459
3520
end
3460
3521
3461
- synchronize do
3462
- clear_responses ( "FETCH" )
3463
- if mod
3464
- send_command ( cmd , set , attr , mod )
3465
- else
3466
- send_command ( cmd , set , attr )
3467
- end
3468
- clear_responses ( "FETCH" )
3469
- end
3522
+ args = [ cmd , set , attr ]
3523
+ args << mod if mod
3524
+ send_command_returning_fetch_results ( *args )
3470
3525
end
3471
3526
3472
3527
def store_internal ( cmd , set , attr , flags , unchangedsince : nil )
3473
3528
attr = RawData . new ( attr ) if attr . instance_of? ( String )
3474
3529
args = [ SequenceSet . new ( set ) ]
3475
3530
args << [ "UNCHANGEDSINCE" , Integer ( unchangedsince ) ] if unchangedsince
3476
3531
args << attr << flags
3532
+ send_command_returning_fetch_results ( cmd , *args )
3533
+ end
3534
+
3535
+ def send_command_returning_fetch_results ( ...)
3477
3536
synchronize do
3478
3537
clear_responses ( "FETCH" )
3479
- send_command ( cmd , *args )
3480
- clear_responses ( "FETCH" )
3538
+ clear_responses ( "UIDFETCH" )
3539
+ send_command ( ...)
3540
+ fetches = clear_responses ( "FETCH" )
3541
+ uidfetches = clear_responses ( "UIDFETCH" )
3542
+ uidfetches . any? ? uidfetches : fetches
3481
3543
end
3482
3544
end
3483
3545
0 commit comments