net-imap 0.5.1 → 0.5.6

Sign up to get free protection for your applications and to get access to all the features.
data/lib/net/imap.rb CHANGED
@@ -25,8 +25,8 @@ module Net
25
25
 
26
26
  # Net::IMAP implements Internet Message Access Protocol (\IMAP) client
27
27
  # functionality. The protocol is described
28
- # in {IMAP4rev1 [RFC3501]}[https://tools.ietf.org/html/rfc3501]
29
- # and {IMAP4rev2 [RFC9051]}[https://tools.ietf.org/html/rfc9051].
28
+ # in {IMAP4rev1 [RFC3501]}[https://www.rfc-editor.org/rfc/rfc3501]
29
+ # and {IMAP4rev2 [RFC9051]}[https://www.rfc-editor.org/rfc/rfc9051].
30
30
  #
31
31
  # == \IMAP Overview
32
32
  #
@@ -299,15 +299,15 @@ module Net
299
299
  # === Core \IMAP commands
300
300
  #
301
301
  # The following commands are defined either by
302
- # the [IMAP4rev1[https://tools.ietf.org/html/rfc3501]] base specification, or
302
+ # the [IMAP4rev1[https://www.rfc-editor.org/rfc/rfc3501]] base specification, or
303
303
  # by one of the following extensions:
304
- # [IDLE[https://tools.ietf.org/html/rfc2177]],
305
- # [NAMESPACE[https://tools.ietf.org/html/rfc2342]],
306
- # [UNSELECT[https://tools.ietf.org/html/rfc3691]],
307
- # [ENABLE[https://tools.ietf.org/html/rfc5161]],
308
- # [MOVE[https://tools.ietf.org/html/rfc6851]].
304
+ # [IDLE[https://www.rfc-editor.org/rfc/rfc2177]],
305
+ # [NAMESPACE[https://www.rfc-editor.org/rfc/rfc2342]],
306
+ # [UNSELECT[https://www.rfc-editor.org/rfc/rfc3691]],
307
+ # [ENABLE[https://www.rfc-editor.org/rfc/rfc5161]],
308
+ # [MOVE[https://www.rfc-editor.org/rfc/rfc6851]].
309
309
  # These extensions are widely supported by modern IMAP4rev1 servers and have
310
- # all been integrated into [IMAP4rev2[https://tools.ietf.org/html/rfc9051]].
310
+ # all been integrated into [IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051]].
311
311
  # <em>*NOTE:* Net::IMAP doesn't support IMAP4rev2 yet.</em>
312
312
  #
313
313
  # ==== Any state
@@ -404,7 +404,7 @@ module Net
404
404
  #
405
405
  # ==== RFC9051: +IMAP4rev2+
406
406
  #
407
- # Although IMAP4rev2[https://tools.ietf.org/html/rfc9051] is not supported
407
+ # Although IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] is not supported
408
408
  # yet, Net::IMAP supports several extensions that have been folded into it:
409
409
  # +ENABLE+, +IDLE+, +MOVE+, +NAMESPACE+, +SASL-IR+, +UIDPLUS+, +UNSELECT+,
410
410
  # <tt>STATUS=SIZE</tt>, and the fetch side of +BINARY+.
@@ -414,7 +414,7 @@ module Net
414
414
  # >>>
415
415
  # <em>The following are folded into +IMAP4rev2+ but are currently
416
416
  # unsupported or incompletely supported by</em> Net::IMAP<em>: RFC4466
417
- # extensions, +ESEARCH+, +SEARCHRES+, +LIST-EXTENDED+, +LIST-STATUS+,
417
+ # extensions, +SEARCHRES+, +LIST-EXTENDED+, +LIST-STATUS+,
418
418
  # +LITERAL-+, and +SPECIAL-USE+.</em>
419
419
  #
420
420
  # ==== RFC2087: +QUOTA+
@@ -424,13 +424,13 @@ module Net
424
424
  # - #setquota: sets the resource limits for a given quota root.
425
425
  #
426
426
  # ==== RFC2177: +IDLE+
427
- # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051] and also included
427
+ # Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] and also included
428
428
  # above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
429
429
  # - #idle: Allows the server to send updates to the client, without the client
430
430
  # needing to poll using #noop.
431
431
  #
432
432
  # ==== RFC2342: +NAMESPACE+
433
- # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051] and also included
433
+ # Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] and also included
434
434
  # above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
435
435
  # - #namespace: Returns mailbox namespaces, with path prefixes and delimiters.
436
436
  #
@@ -439,7 +439,7 @@ module Net
439
439
  #
440
440
  # ==== RFC3516: +BINARY+
441
441
  # The fetch side of +BINARY+ has been folded into
442
- # IMAP4rev2[https://tools.ietf.org/html/rfc9051].
442
+ # IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051].
443
443
  # - Updates #fetch and #uid_fetch with the +BINARY+, +BINARY.PEEK+, and
444
444
  # +BINARY.SIZE+ items. See FetchData#binary and FetchData#binary_size.
445
445
  #
@@ -447,7 +447,7 @@ module Net
447
447
  # *NOTE:* The binary extension the #append command is _not_ supported yet.
448
448
  #
449
449
  # ==== RFC3691: +UNSELECT+
450
- # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051] and also included
450
+ # Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] and also included
451
451
  # above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
452
452
  # - #unselect: Closes the mailbox and returns to the "_authenticated_" state,
453
453
  # without expunging any messages.
@@ -459,19 +459,23 @@ module Net
459
459
  # *NOTE:* +DELETEACL+, +LISTRIGHTS+, and +MYRIGHTS+ are not supported yet.
460
460
  #
461
461
  # ==== RFC4315: +UIDPLUS+
462
- # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051] and also included
462
+ # Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] and also included
463
463
  # above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
464
464
  # - #uid_expunge: Restricts #expunge to only remove the specified UIDs.
465
465
  # - Updates #select, #examine with the +UIDNOTSTICKY+ ResponseCode
466
466
  # - Updates #append with the +APPENDUID+ ResponseCode
467
467
  # - Updates #copy, #move with the +COPYUID+ ResponseCode
468
468
  #
469
+ # ==== RFC4731: +ESEARCH+
470
+ # Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051].
471
+ # - Updates #search, #uid_search with +return+ options and ESearchResult.
472
+ #
469
473
  # ==== RFC4959: +SASL-IR+
470
- # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
474
+ # Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051].
471
475
  # - Updates #authenticate with the option to send an initial response.
472
476
  #
473
477
  # ==== RFC5161: +ENABLE+
474
- # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051] and also included
478
+ # Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] and also included
475
479
  # above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
476
480
  # - #enable: Enables backwards incompatible server extensions.
477
481
  #
@@ -495,7 +499,7 @@ module Net
495
499
  # +X-GM-THRID+, but Gmail does not support it (as of 2023-11-10).
496
500
  #
497
501
  # ==== RFC6851: +MOVE+
498
- # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051] and also included
502
+ # Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] and also included
499
503
  # above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
500
504
  # - #move, #uid_move: Moves the specified messages to the end of the
501
505
  # specified destination mailbox, expunging them from the current mailbox.
@@ -530,6 +534,17 @@ module Net
530
534
  # See FetchData#emailid and FetchData#emailid.
531
535
  # - Updates #status with support for the +MAILBOXID+ status attribute.
532
536
  #
537
+ # ==== RFC9394: +PARTIAL+
538
+ # - Updates #search, #uid_search with the +PARTIAL+ return option which adds
539
+ # ESearchResult#partial return data.
540
+ # - Updates #uid_fetch with the +partial+ modifier.
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
+ #
533
548
  # == References
534
549
  #
535
550
  # [{IMAP4rev1}[https://www.rfc-editor.org/rfc/rfc3501.html]]::
@@ -560,57 +575,57 @@ module Net
560
575
  # Gahrns, M., "IMAP4 Multi-Accessed Mailbox Practice", RFC 2180, DOI
561
576
  # 10.17487/RFC2180, July 1997, <https://www.rfc-editor.org/info/rfc2180>.
562
577
  #
563
- # [UTF7[https://tools.ietf.org/html/rfc2152]]::
578
+ # [UTF7[https://www.rfc-editor.org/rfc/rfc2152]]::
564
579
  # Goldsmith, D. and M. Davis, "UTF-7 A Mail-Safe Transformation Format of
565
580
  # Unicode", RFC 2152, DOI 10.17487/RFC2152, May 1997,
566
581
  # <https://www.rfc-editor.org/info/rfc2152>.
567
582
  #
568
583
  # === Message envelope and body structure
569
584
  #
570
- # [RFC5322[https://tools.ietf.org/html/rfc5322]]::
585
+ # [RFC5322[https://www.rfc-editor.org/rfc/rfc5322]]::
571
586
  # Resnick, P., Ed., "Internet Message Format",
572
587
  # RFC 5322, DOI 10.17487/RFC5322, October 2008,
573
588
  # <https://www.rfc-editor.org/info/rfc5322>.
574
589
  #
575
590
  # <em>Note: obsoletes</em>
576
- # RFC-2822[https://tools.ietf.org/html/rfc2822]<em> (April 2001) and</em>
577
- # RFC-822[https://tools.ietf.org/html/rfc822]<em> (August 1982).</em>
591
+ # RFC-2822[https://www.rfc-editor.org/rfc/rfc2822]<em> (April 2001) and</em>
592
+ # RFC-822[https://www.rfc-editor.org/rfc/rfc822]<em> (August 1982).</em>
578
593
  #
579
- # [CHARSET[https://tools.ietf.org/html/rfc2978]]::
594
+ # [CHARSET[https://www.rfc-editor.org/rfc/rfc2978]]::
580
595
  # Freed, N. and J. Postel, "IANA Charset Registration Procedures", BCP 19,
581
596
  # RFC 2978, DOI 10.17487/RFC2978, October 2000,
582
597
  # <https://www.rfc-editor.org/info/rfc2978>.
583
598
  #
584
- # [DISPOSITION[https://tools.ietf.org/html/rfc2183]]::
599
+ # [DISPOSITION[https://www.rfc-editor.org/rfc/rfc2183]]::
585
600
  # Troost, R., Dorner, S., and K. Moore, Ed., "Communicating Presentation
586
601
  # Information in Internet Messages: The Content-Disposition Header
587
602
  # Field", RFC 2183, DOI 10.17487/RFC2183, August 1997,
588
603
  # <https://www.rfc-editor.org/info/rfc2183>.
589
604
  #
590
- # [MIME-IMB[https://tools.ietf.org/html/rfc2045]]::
605
+ # [MIME-IMB[https://www.rfc-editor.org/rfc/rfc2045]]::
591
606
  # Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions
592
607
  # (MIME) Part One: Format of Internet Message Bodies",
593
608
  # RFC 2045, DOI 10.17487/RFC2045, November 1996,
594
609
  # <https://www.rfc-editor.org/info/rfc2045>.
595
610
  #
596
- # [MIME-IMT[https://tools.ietf.org/html/rfc2046]]::
611
+ # [MIME-IMT[https://www.rfc-editor.org/rfc/rfc2046]]::
597
612
  # Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions
598
613
  # (MIME) Part Two: Media Types", RFC 2046, DOI 10.17487/RFC2046,
599
614
  # November 1996, <https://www.rfc-editor.org/info/rfc2046>.
600
615
  #
601
- # [MIME-HDRS[https://tools.ietf.org/html/rfc2047]]::
616
+ # [MIME-HDRS[https://www.rfc-editor.org/rfc/rfc2047]]::
602
617
  # Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part Three:
603
618
  # Message Header Extensions for Non-ASCII Text",
604
619
  # RFC 2047, DOI 10.17487/RFC2047, November 1996,
605
620
  # <https://www.rfc-editor.org/info/rfc2047>.
606
621
  #
607
- # [RFC2231[https://tools.ietf.org/html/rfc2231]]::
622
+ # [RFC2231[https://www.rfc-editor.org/rfc/rfc2231]]::
608
623
  # Freed, N. and K. Moore, "MIME Parameter Value and Encoded Word
609
624
  # Extensions: Character Sets, Languages, and Continuations",
610
625
  # RFC 2231, DOI 10.17487/RFC2231, November 1997,
611
626
  # <https://www.rfc-editor.org/info/rfc2231>.
612
627
  #
613
- # [I18n-HDRS[https://tools.ietf.org/html/rfc6532]]::
628
+ # [I18n-HDRS[https://www.rfc-editor.org/rfc/rfc6532]]::
614
629
  # Yang, A., Steele, S., and N. Freed, "Internationalized Email Headers",
615
630
  # RFC 6532, DOI 10.17487/RFC6532, February 2012,
616
631
  # <https://www.rfc-editor.org/info/rfc6532>.
@@ -626,12 +641,12 @@ module Net
626
641
  # RFC 2557, DOI 10.17487/RFC2557, March 1999,
627
642
  # <https://www.rfc-editor.org/info/rfc2557>.
628
643
  #
629
- # [MD5[https://tools.ietf.org/html/rfc1864]]::
644
+ # [MD5[https://www.rfc-editor.org/rfc/rfc1864]]::
630
645
  # Myers, J. and M. Rose, "The Content-MD5 Header Field",
631
646
  # RFC 1864, DOI 10.17487/RFC1864, October 1995,
632
647
  # <https://www.rfc-editor.org/info/rfc1864>.
633
648
  #
634
- # [RFC3503[https://tools.ietf.org/html/rfc3503]]::
649
+ # [RFC3503[https://www.rfc-editor.org/rfc/rfc3503]]::
635
650
  # Melnikov, A., "Message Disposition Notification (MDN)
636
651
  # profile for Internet Message Access Protocol (IMAP)",
637
652
  # RFC 3503, DOI 10.17487/RFC3503, March 2003,
@@ -639,27 +654,27 @@ module Net
639
654
  #
640
655
  # === \IMAP Extensions
641
656
  #
642
- # [QUOTA[https://tools.ietf.org/html/rfc9208]]::
657
+ # [QUOTA[https://www.rfc-editor.org/rfc/rfc9208]]::
643
658
  # Melnikov, A., "IMAP QUOTA Extension", RFC 9208, DOI 10.17487/RFC9208,
644
659
  # March 2022, <https://www.rfc-editor.org/info/rfc9208>.
645
660
  #
646
661
  # <em>Note: obsoletes</em>
647
- # RFC-2087[https://tools.ietf.org/html/rfc2087]<em> (January 1997)</em>.
662
+ # RFC-2087[https://www.rfc-editor.org/rfc/rfc2087]<em> (January 1997)</em>.
648
663
  # <em>Net::IMAP does not fully support the RFC9208 updates yet.</em>
649
- # [IDLE[https://tools.ietf.org/html/rfc2177]]::
664
+ # [IDLE[https://www.rfc-editor.org/rfc/rfc2177]]::
650
665
  # Leiba, B., "IMAP4 IDLE command", RFC 2177, DOI 10.17487/RFC2177,
651
666
  # June 1997, <https://www.rfc-editor.org/info/rfc2177>.
652
- # [NAMESPACE[https://tools.ietf.org/html/rfc2342]]::
667
+ # [NAMESPACE[https://www.rfc-editor.org/rfc/rfc2342]]::
653
668
  # Gahrns, M. and C. Newman, "IMAP4 Namespace", RFC 2342,
654
669
  # DOI 10.17487/RFC2342, May 1998, <https://www.rfc-editor.org/info/rfc2342>.
655
- # [ID[https://tools.ietf.org/html/rfc2971]]::
670
+ # [ID[https://www.rfc-editor.org/rfc/rfc2971]]::
656
671
  # Showalter, T., "IMAP4 ID extension", RFC 2971, DOI 10.17487/RFC2971,
657
672
  # October 2000, <https://www.rfc-editor.org/info/rfc2971>.
658
- # [BINARY[https://tools.ietf.org/html/rfc3516]]::
673
+ # [BINARY[https://www.rfc-editor.org/rfc/rfc3516]]::
659
674
  # Nerenberg, L., "IMAP4 Binary Content Extension", RFC 3516,
660
675
  # DOI 10.17487/RFC3516, April 2003,
661
676
  # <https://www.rfc-editor.org/info/rfc3516>.
662
- # [ACL[https://tools.ietf.org/html/rfc4314]]::
677
+ # [ACL[https://www.rfc-editor.org/rfc/rfc4314]]::
663
678
  # Melnikov, A., "IMAP4 Access Control List (ACL) Extension", RFC 4314,
664
679
  # DOI 10.17487/RFC4314, December 2005,
665
680
  # <https://www.rfc-editor.org/info/rfc4314>.
@@ -667,36 +682,46 @@ module Net
667
682
  # Crispin, M., "Internet Message Access Protocol (\IMAP) - UIDPLUS
668
683
  # extension", RFC 4315, DOI 10.17487/RFC4315, December 2005,
669
684
  # <https://www.rfc-editor.org/info/rfc4315>.
670
- # [SORT[https://tools.ietf.org/html/rfc5256]]::
685
+ # [SORT[https://www.rfc-editor.org/rfc/rfc5256]]::
671
686
  # Crispin, M. and K. Murchison, "Internet Message Access Protocol - SORT and
672
687
  # THREAD Extensions", RFC 5256, DOI 10.17487/RFC5256, June 2008,
673
688
  # <https://www.rfc-editor.org/info/rfc5256>.
674
- # [THREAD[https://tools.ietf.org/html/rfc5256]]::
689
+ # [THREAD[https://www.rfc-editor.org/rfc/rfc5256]]::
675
690
  # Crispin, M. and K. Murchison, "Internet Message Access Protocol - SORT and
676
691
  # THREAD Extensions", RFC 5256, DOI 10.17487/RFC5256, June 2008,
677
692
  # <https://www.rfc-editor.org/info/rfc5256>.
678
693
  # [RFC5530[https://www.rfc-editor.org/rfc/rfc5530.html]]::
679
694
  # Gulbrandsen, A., "IMAP Response Codes", RFC 5530, DOI 10.17487/RFC5530,
680
695
  # May 2009, <https://www.rfc-editor.org/info/rfc5530>.
681
- # [MOVE[https://tools.ietf.org/html/rfc6851]]::
696
+ # [MOVE[https://www.rfc-editor.org/rfc/rfc6851]]::
682
697
  # Gulbrandsen, A. and N. Freed, Ed., "Internet Message Access Protocol
683
698
  # (\IMAP) - MOVE Extension", RFC 6851, DOI 10.17487/RFC6851, January 2013,
684
699
  # <https://www.rfc-editor.org/info/rfc6851>.
685
- # [UTF8=ACCEPT[https://tools.ietf.org/html/rfc6855]]::
686
- # [UTF8=ONLY[https://tools.ietf.org/html/rfc6855]]::
700
+ # [UTF8=ACCEPT[https://www.rfc-editor.org/rfc/rfc6855]]::
701
+ # [UTF8=ONLY[https://www.rfc-editor.org/rfc/rfc6855]]::
687
702
  # Resnick, P., Ed., Newman, C., Ed., and S. Shen, Ed.,
688
703
  # "IMAP Support for UTF-8", RFC 6855, DOI 10.17487/RFC6855, March 2013,
689
704
  # <https://www.rfc-editor.org/info/rfc6855>.
690
- # [CONDSTORE[https://tools.ietf.org/html/rfc7162]]::
691
- # [QRESYNC[https://tools.ietf.org/html/rfc7162]]::
705
+ # [CONDSTORE[https://www.rfc-editor.org/rfc/rfc7162]]::
706
+ # [QRESYNC[https://www.rfc-editor.org/rfc/rfc7162]]::
692
707
  # Melnikov, A. and D. Cridland, "IMAP Extensions: Quick Flag Changes
693
708
  # Resynchronization (CONDSTORE) and Quick Mailbox Resynchronization
694
709
  # (QRESYNC)", RFC 7162, DOI 10.17487/RFC7162, May 2014,
695
710
  # <https://www.rfc-editor.org/info/rfc7162>.
696
- # [OBJECTID[https://tools.ietf.org/html/rfc8474]]::
711
+ # [OBJECTID[https://www.rfc-editor.org/rfc/rfc8474]]::
697
712
  # Gondwana, B., Ed., "IMAP Extension for Object Identifiers",
698
713
  # RFC 8474, DOI 10.17487/RFC8474, September 2018,
699
714
  # <https://www.rfc-editor.org/info/rfc8474>.
715
+ # [PARTIAL[https://www.rfc-editor.org/info/rfc9394]]::
716
+ # Melnikov, A., Achuthan, A., Nagulakonda, V., and L. Alves,
717
+ # "IMAP PARTIAL Extension for Paged SEARCH and FETCH", RFC 9394,
718
+ # DOI 10.17487/RFC9394, June 2023,
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>.
700
725
  #
701
726
  # === IANA registries
702
727
  # * {IMAP Capabilities}[http://www.iana.org/assignments/imap4-capabilities]
@@ -710,7 +735,7 @@ module Net
710
735
  # * {GSSAPI/Kerberos/SASL Service Names}[https://www.iana.org/assignments/gssapi-service-names/gssapi-service-names.xhtml]:
711
736
  # +imap+
712
737
  # * {Character sets}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
713
- # ===== For currently unsupported features:
738
+ # ==== For currently unsupported features:
714
739
  # * {IMAP Quota Resource Types}[http://www.iana.org/assignments/imap4-capabilities#imap-capabilities-2]
715
740
  # * {LIST-EXTENDED options and responses}[https://www.iana.org/assignments/imap-list-extended/imap-list-extended.xhtml]
716
741
  # * {IMAP METADATA Server Entry and Mailbox Entry Registries}[https://www.iana.org/assignments/imap-metadata/imap-metadata.xhtml]
@@ -719,7 +744,7 @@ module Net
719
744
  # * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
720
745
  #
721
746
  class IMAP < Protocol
722
- VERSION = "0.5.1"
747
+ VERSION = "0.5.6"
723
748
 
724
749
  # Aliases for supported capabilities, to be used with the #enable command.
725
750
  ENABLE_ALIASES = {
@@ -1121,12 +1146,12 @@ module Net
1121
1146
  # )
1122
1147
  # end
1123
1148
  #
1124
- # See [ID[https://tools.ietf.org/html/rfc2971]] for field definitions.
1149
+ # See [ID[https://www.rfc-editor.org/rfc/rfc2971]] for field definitions.
1125
1150
  #
1126
- # ===== Capabilities
1151
+ # ==== Capabilities
1127
1152
  #
1128
1153
  # The server's capabilities must include +ID+
1129
- # [RFC2971[https://tools.ietf.org/html/rfc2971]].
1154
+ # [RFC2971[https://www.rfc-editor.org/rfc/rfc2971]].
1130
1155
  def id(client_id=nil)
1131
1156
  synchronize do
1132
1157
  send_command("ID", ClientID.new(client_id))
@@ -1205,7 +1230,7 @@ module Net
1205
1230
  #
1206
1231
  # Related: Net::IMAP.new, #login, #authenticate
1207
1232
  #
1208
- # ===== Capability
1233
+ # ==== Capability
1209
1234
  # Clients should not call #starttls unless the server advertises the
1210
1235
  # +STARTTLS+ capability.
1211
1236
  #
@@ -1214,13 +1239,21 @@ module Net
1214
1239
  #
1215
1240
  def starttls(**options)
1216
1241
  @ssl_ctx_params, @ssl_ctx = build_ssl_ctx(options)
1217
- send_command("STARTTLS") do |resp|
1242
+ error = nil
1243
+ ok = send_command("STARTTLS") do |resp|
1218
1244
  if resp.kind_of?(TaggedResponse) && resp.name == "OK"
1219
1245
  clear_cached_capabilities
1220
1246
  clear_responses
1221
1247
  start_tls_session
1222
1248
  end
1249
+ rescue Exception => error
1250
+ raise # note that the error backtrace is in the receiver_thread
1251
+ end
1252
+ if error
1253
+ disconnect
1254
+ raise error
1223
1255
  end
1256
+ ok
1224
1257
  end
1225
1258
 
1226
1259
  # :call-seq:
@@ -1352,7 +1385,7 @@ module Net
1352
1385
  #
1353
1386
  # Related: #authenticate, #starttls
1354
1387
  #
1355
- # ===== Capabilities
1388
+ # ==== Capabilities
1356
1389
  #
1357
1390
  # An IMAP client MUST NOT call #login when the server advertises the
1358
1391
  # +LOGINDISABLED+ capability. By default, Net::IMAP will raise a
@@ -1393,7 +1426,7 @@ module Net
1393
1426
  #
1394
1427
  # Related: #examine
1395
1428
  #
1396
- # ===== Capabilities
1429
+ # ==== Capabilities
1397
1430
  #
1398
1431
  # If [UIDPLUS[https://www.rfc-editor.org/rfc/rfc4315.html]] is supported,
1399
1432
  # the server may return an untagged "NO" response with a "UIDNOTSTICKY"
@@ -1511,7 +1544,7 @@ module Net
1511
1544
  #
1512
1545
  # Related: #lsub, MailboxList
1513
1546
  #
1514
- # ===== For example:
1547
+ # ==== For example:
1515
1548
  #
1516
1549
  # imap.create("foo/bar")
1517
1550
  # imap.create("foo/baz")
@@ -1549,7 +1582,7 @@ module Net
1549
1582
  # servers, then folder creation (and listing, moving, etc) can lead to
1550
1583
  # errors.
1551
1584
  #
1552
- # From RFC2342[https://tools.ietf.org/html/rfc2342]:
1585
+ # From RFC2342[https://www.rfc-editor.org/rfc/rfc2342]:
1553
1586
  # >>>
1554
1587
  # <em>Although typically a server will support only a single Personal
1555
1588
  # Namespace, and a single Other User's Namespace, circumstances exist
@@ -1562,7 +1595,7 @@ module Net
1562
1595
  #
1563
1596
  # Related: #list, Namespaces, Namespace
1564
1597
  #
1565
- # ===== For example:
1598
+ # ==== For example:
1566
1599
  #
1567
1600
  # if capable?("NAMESPACE")
1568
1601
  # namespaces = imap.namespace
@@ -1576,10 +1609,10 @@ module Net
1576
1609
  # end
1577
1610
  # end
1578
1611
  #
1579
- # ===== Capabilities
1612
+ # ==== Capabilities
1580
1613
  #
1581
- # The server's capabilities must include +NAMESPACE+
1582
- # [RFC2342[https://tools.ietf.org/html/rfc2342]].
1614
+ # The server's capabilities must include either +IMAP4rev2+ or +NAMESPACE+
1615
+ # [RFC2342[https://www.rfc-editor.org/rfc/rfc2342]].
1583
1616
  def namespace
1584
1617
  synchronize do
1585
1618
  send_command("NAMESPACE")
@@ -1615,7 +1648,7 @@ module Net
1615
1648
  #
1616
1649
  # Related: #list, MailboxList
1617
1650
  #
1618
- # ===== Capabilities
1651
+ # ==== Capabilities
1619
1652
  #
1620
1653
  # The server's capabilities must include +XLIST+,
1621
1654
  # a deprecated Gmail extension (replaced by +SPECIAL-USE+).
@@ -1638,10 +1671,10 @@ module Net
1638
1671
  #
1639
1672
  # Related: #getquota, #setquota, MailboxQuotaRoot, MailboxQuota
1640
1673
  #
1641
- # ===== Capabilities
1674
+ # ==== Capabilities
1642
1675
  #
1643
1676
  # The server's capabilities must include +QUOTA+
1644
- # [RFC2087[https://tools.ietf.org/html/rfc2087]].
1677
+ # [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]].
1645
1678
  def getquotaroot(mailbox)
1646
1679
  synchronize do
1647
1680
  send_command("GETQUOTAROOT", mailbox)
@@ -1659,10 +1692,10 @@ module Net
1659
1692
  #
1660
1693
  # Related: #getquotaroot, #setquota, MailboxQuota
1661
1694
  #
1662
- # ===== Capabilities
1695
+ # ==== Capabilities
1663
1696
  #
1664
1697
  # The server's capabilities must include +QUOTA+
1665
- # [RFC2087[https://tools.ietf.org/html/rfc2087]].
1698
+ # [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]].
1666
1699
  def getquota(mailbox)
1667
1700
  synchronize do
1668
1701
  send_command("GETQUOTA", mailbox)
@@ -1677,10 +1710,10 @@ module Net
1677
1710
  #
1678
1711
  # Related: #getquota, #getquotaroot
1679
1712
  #
1680
- # ===== Capabilities
1713
+ # ==== Capabilities
1681
1714
  #
1682
1715
  # The server's capabilities must include +QUOTA+
1683
- # [RFC2087[https://tools.ietf.org/html/rfc2087]].
1716
+ # [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]].
1684
1717
  def setquota(mailbox, quota)
1685
1718
  if quota.nil?
1686
1719
  data = '()'
@@ -1697,10 +1730,10 @@ module Net
1697
1730
  #
1698
1731
  # Related: #getacl
1699
1732
  #
1700
- # ===== Capabilities
1733
+ # ==== Capabilities
1701
1734
  #
1702
1735
  # The server's capabilities must include +ACL+
1703
- # [RFC4314[https://tools.ietf.org/html/rfc4314]].
1736
+ # [RFC4314[https://www.rfc-editor.org/rfc/rfc4314]].
1704
1737
  def setacl(mailbox, user, rights)
1705
1738
  if rights.nil?
1706
1739
  send_command("SETACL", mailbox, user, "")
@@ -1715,10 +1748,10 @@ module Net
1715
1748
  #
1716
1749
  # Related: #setacl, MailboxACLItem
1717
1750
  #
1718
- # ===== Capabilities
1751
+ # ==== Capabilities
1719
1752
  #
1720
1753
  # The server's capabilities must include +ACL+
1721
- # [RFC4314[https://tools.ietf.org/html/rfc4314]].
1754
+ # [RFC4314[https://www.rfc-editor.org/rfc/rfc4314]].
1722
1755
  def getacl(mailbox)
1723
1756
  synchronize do
1724
1757
  send_command("GETACL", mailbox)
@@ -1752,7 +1785,7 @@ module Net
1752
1785
  # for +mailbox+ cannot be returned; for instance, because it
1753
1786
  # does not exist.
1754
1787
  #
1755
- # ===== Supported attributes
1788
+ # ==== Supported attributes
1756
1789
  #
1757
1790
  # +MESSAGES+:: The number of messages in the mailbox.
1758
1791
  #
@@ -1783,12 +1816,12 @@ module Net
1783
1816
  # Unsupported attributes may be requested. The attribute value will be
1784
1817
  # either an Integer or an ExtensionData object.
1785
1818
  #
1786
- # ===== For example:
1819
+ # ==== For example:
1787
1820
  #
1788
1821
  # p imap.status("inbox", ["MESSAGES", "RECENT"])
1789
1822
  # #=> {"RECENT"=>0, "MESSAGES"=>44}
1790
1823
  #
1791
- # ===== Capabilities
1824
+ # ==== Capabilities
1792
1825
  #
1793
1826
  # +SIZE+ requires the server's capabilities to include either +IMAP4rev2+ or
1794
1827
  # <tt>STATUS=SIZE</tt>
@@ -1828,7 +1861,7 @@ module Net
1828
1861
  # not exist (it is not created automatically), or if the flags,
1829
1862
  # date_time, or message arguments contain errors.
1830
1863
  #
1831
- # ===== Capabilities
1864
+ # ==== Capabilities
1832
1865
  #
1833
1866
  # If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
1834
1867
  # supported and the destination supports persistent UIDs, the server's
@@ -1877,118 +1910,277 @@ module Net
1877
1910
  #
1878
1911
  # Related: #close
1879
1912
  #
1880
- # ===== Capabilities
1913
+ # ==== Capabilities
1881
1914
  #
1882
- # The server's capabilities must include +UNSELECT+
1883
- # [RFC3691[https://tools.ietf.org/html/rfc3691]].
1915
+ # The server's capabilities must include either +IMAP4rev2+ or +UNSELECT+
1916
+ # [RFC3691[https://www.rfc-editor.org/rfc/rfc3691]].
1884
1917
  def unselect
1885
1918
  send_command("UNSELECT")
1886
1919
  end
1887
1920
 
1921
+ # call-seq:
1922
+ # expunge -> array of message sequence numbers
1923
+ # expunge -> VanishedData of UIDs
1924
+ #
1888
1925
  # Sends an {EXPUNGE command [IMAP4rev1 §6.4.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.3]
1889
- # Sends a EXPUNGE command to permanently remove from the currently
1890
- # selected mailbox all messages that have the \Deleted flag set.
1926
+ # to permanently remove all messages with the +\Deleted+ flag from the
1927
+ # currently selected mailbox.
1928
+ #
1929
+ # Returns either an array of expunged message <em>sequence numbers</em> or
1930
+ # (when the appropriate capability is enabled) VanishedData of expunged
1931
+ # UIDs. Previously unhandled +EXPUNGE+ or +VANISHED+ responses are merged
1932
+ # with the direct response to this command. <tt>VANISHED (EARLIER)</tt>
1933
+ # responses will _not_ be merged.
1934
+ #
1935
+ # When no messages have been expunged, an empty array is returned,
1936
+ # regardless of which extensions are enabled. In a future release, an empty
1937
+ # VanishedData may be returned, based on the currently enabled extensions.
1891
1938
  #
1892
1939
  # Related: #uid_expunge
1940
+ #
1941
+ # ==== Capabilities
1942
+ #
1943
+ # When either QRESYNC[https://www.rfc-editor.org/rfc/rfc7162] or
1944
+ # UIDONLY[https://www.rfc-editor.org/rfc/rfc9586] are enabled, #expunge
1945
+ # returns VanishedData, which contains UIDs---<em>not message sequence
1946
+ # numbers</em>.
1893
1947
  def expunge
1894
- synchronize do
1895
- send_command("EXPUNGE")
1896
- clear_responses("EXPUNGE")
1897
- end
1948
+ expunge_internal("EXPUNGE")
1898
1949
  end
1899
1950
 
1951
+ # call-seq:
1952
+ # uid_expunge{uid_set) -> array of message sequence numbers
1953
+ # uid_expunge{uid_set) -> VanishedData of UIDs
1954
+ #
1900
1955
  # Sends a {UID EXPUNGE command [RFC4315 §2.1]}[https://www.rfc-editor.org/rfc/rfc4315#section-2.1]
1901
1956
  # {[IMAP4rev2 §6.4.9]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.9]
1902
1957
  # to permanently remove all messages that have both the <tt>\\Deleted</tt>
1903
1958
  # flag set and a UID that is included in +uid_set+.
1904
1959
  #
1960
+ # Returns the same result type as #expunge.
1961
+ #
1905
1962
  # By using #uid_expunge instead of #expunge when resynchronizing with
1906
1963
  # the server, the client can ensure that it does not inadvertantly
1907
1964
  # remove any messages that have been marked as <tt>\\Deleted</tt> by other
1908
1965
  # clients between the time that the client was last connected and
1909
1966
  # the time the client resynchronizes.
1910
1967
  #
1911
- # *Note:*
1912
- # >>>
1913
- # Although the command takes a set of UIDs for its argument, the
1914
- # server still returns regular EXPUNGE responses, which contain
1915
- # a <em>sequence number</em>. These will be deleted from
1916
- # #responses and this method returns them as an array of
1917
- # <em>sequence number</em> integers.
1918
- #
1919
1968
  # Related: #expunge
1920
1969
  #
1921
- # ===== Capabilities
1970
+ # ==== Capabilities
1922
1971
  #
1923
- # The server's capabilities must include +UIDPLUS+
1972
+ # The server's capabilities must include either +IMAP4rev2+ or +UIDPLUS+
1924
1973
  # [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]].
1974
+ #
1975
+ # Otherwise, #uid_expunge is updated by extensions in the same way as
1976
+ # #expunge.
1925
1977
  def uid_expunge(uid_set)
1926
- synchronize do
1927
- send_command("UID EXPUNGE", SequenceSet.new(uid_set))
1928
- clear_responses("EXPUNGE")
1929
- end
1978
+ expunge_internal("UID EXPUNGE", SequenceSet.new(uid_set))
1930
1979
  end
1931
1980
 
1932
1981
  # :call-seq:
1933
1982
  # search(criteria, charset = nil) -> result
1983
+ # search(criteria, charset: nil, return: nil) -> result
1934
1984
  #
1935
1985
  # Sends a {SEARCH command [IMAP4rev1 §6.4.4]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.4]
1936
1986
  # to search the mailbox for messages that match the given search +criteria+,
1937
- # and returns a SearchResult. SearchResult inherits from Array (for
1938
- # backward compatibility) but adds SearchResult#modseq when the +CONDSTORE+
1939
- # capability has been enabled.
1987
+ # and returns either a SearchResult or an ESearchResult. SearchResult
1988
+ # inherits from Array (for backward compatibility) but adds
1989
+ # SearchResult#modseq when the +CONDSTORE+ capability has been enabled.
1990
+ # ESearchResult also implements {#to_a}[rdoc-ref:ESearchResult#to_a], for
1991
+ # compatibility with SearchResult.
1940
1992
  #
1941
1993
  # +criteria+ is one or more search keys and their arguments, which may be
1942
1994
  # provided as an array or a string.
1943
- # See {"Search criteria"}[rdoc-ref:#search@Search+criteria], below.
1944
- #
1945
- # * When +criteria+ is an array, each member is a +SEARCH+ command argument:
1946
- # * Any SequenceSet sends SequenceSet#valid_string.
1947
- # These types are converted to SequenceSet for validation and encoding:
1948
- # * +Set+
1949
- # * +Range+
1950
- # * <tt>-1</tt> and +:*+ -- both translate to <tt>*</tt>
1951
- # * responds to +#to_sequence_set+
1952
- # * +Array+, when each element is one of the above types, a positive
1953
- # +Integer+, a sequence-set formatted +String+, or a deeply nested
1954
- # +Array+ of these same types.
1955
- # * Any +String+ is sent verbatim when it is a valid \IMAP atom,
1956
- # and encoded as an \IMAP quoted or literal string otherwise.
1957
- # * Any other nested +Array+ is encoded as a parenthesized list, to group
1958
- # multiple search keys (e.g., for use with +OR+ and +NOT+).
1959
- # * Any other +Integer+ (besides <tt>-1</tt>) will be sent as +#to_s+.
1960
- # * +Date+ objects will be encoded as an \IMAP date (see ::encode_date).
1961
- #
1962
- # * When +criteria+ is a string, it will be sent directly to the server
1963
- # <em>without any validation or encoding</em>. *WARNING:* This is
1964
- # vulnerable to injection attacks when external inputs are used.
1995
+ # See {"Argument translation"}[rdoc-ref:#search@Argument+translation]
1996
+ # and {"Search criteria"}[rdoc-ref:#search@Search+criteria], below.
1997
+ #
1998
+ # +return+ options control what kind of information is returned about
1999
+ # messages matching the search +criteria+. Specifying +return+ should force
2000
+ # the server to return an ESearchResult instead of a SearchResult, but some
2001
+ # servers disobey this requirement. <em>Requires an extended search
2002
+ # capability, such as +ESEARCH+ or +IMAP4rev2+.</em>
2003
+ # See {"Argument translation"}[rdoc-ref:#search@Argument+translation] and
2004
+ # {"Supported return options"}[rdoc-ref:#search@Supported+return+options],
2005
+ # below.
1965
2006
  #
1966
2007
  # +charset+ is the name of the {registered character
1967
2008
  # set}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
1968
2009
  # used by strings in the search +criteria+. When +charset+ isn't specified,
1969
2010
  # either <tt>"US-ASCII"</tt> or <tt>"UTF-8"</tt> is assumed, depending on
1970
- # the server's capabilities. +charset+ may be sent inside +criteria+
1971
- # instead of as a separate argument.
2011
+ # the server's capabilities.
2012
+ #
2013
+ # _NOTE:_ Return options and charset may be sent as part of +criteria+. Do
2014
+ # not use the +return+ or +charset+ arguments when either return options or
2015
+ # charset are embedded in +criteria+.
1972
2016
  #
1973
2017
  # Related: #uid_search
1974
2018
  #
1975
- # ===== For example:
2019
+ # ==== For example:
1976
2020
  #
1977
- # p imap.search(["SUBJECT", "hello", "NOT", "SEEN"])
2021
+ # imap.search(["SUBJECT", "hello", "NOT", "SEEN"])
1978
2022
  # #=> [1, 6, 7, 8]
1979
2023
  #
1980
- # The following searches send the exact same command to the server:
1981
- #
1982
- # # criteria array, charset arg
1983
- # imap.search(["OR", "UNSEEN", %w(FLAGGED SUBJECT foo)], "UTF-8")
1984
- # # criteria string, charset arg
1985
- # imap.search("OR UNSEEN (FLAGGED SUBJECT foo)", "UTF-8")
1986
- # # criteria array contains charset arg
1987
- # imap.search([*%w[CHARSET UTF-8], "OR", "UNSEEN", %w(FLAGGED SUBJECT foo)])
1988
- # # criteria string contains charset arg
1989
- # imap.search("CHARSET UTF-8 OR UNSEEN (FLAGGED SUBJECT foo)")
1990
- #
1991
- # ===== Search keys
2024
+ # The following assumes the server supports +ESEARCH+ and +CONDSTORE+:
2025
+ #
2026
+ # result = imap.uid_search(["UID", 12345.., "MODSEQ", 620_162_338],
2027
+ # return: %w(all count min max))
2028
+ # # => #<data Net::IMAP::ESearchResult tag="RUBY0123", uid=true,
2029
+ # # data=[["ALL", Net::IMAP::SequenceSet["12346:12349,22222:22230"]],
2030
+ # # ["COUNT", 13], ["MIN", 12346], ["MAX", 22230],
2031
+ # # ["MODSEQ", 917162488]]>
2032
+ # result.to_a # => [12346, 12347, 12348, 12349, 22222, 22223, 22224,
2033
+ # # 22225, 22226, 22227, 22228, 22229, 22230]
2034
+ # result.uid? # => true
2035
+ # result.count # => 13
2036
+ # result.min # => 12346
2037
+ # result.max # => 22230
2038
+ # result.modseq # => 917162488
2039
+ #
2040
+ # Using +return+ options to limit the result to only min, max, and count:
2041
+ #
2042
+ # result = imap.uid_search(["UID", 12345..,], return: %w(count min max))
2043
+ # # => #<data Net::IMAP::ESearchResult tag="RUBY0124", uid=true,
2044
+ # # data=[["COUNT", 13], ["MIN", 12346], ["MAX", 22230]]>
2045
+ # result.to_a # => []
2046
+ # result.count # => 13
2047
+ # result.min # => 12346
2048
+ # result.max # => 22230
2049
+ #
2050
+ # Return options and charset may be sent as keyword args or embedded in the
2051
+ # +criteria+ arg, but they must be in the correct order: <tt>"RETURN (...)
2052
+ # CHARSET ... criteria..."</tt>. The following searches
2053
+ # send the exact same command to the server:
2054
+ #
2055
+ # # Return options and charset as keyword arguments (preferred)
2056
+ # imap.search(%w(OR UNSEEN FLAGGED), return: %w(MIN MAX), charset: "UTF-8")
2057
+ # # Embedding return and charset in the criteria array
2058
+ # imap.search(["RETURN", %w(MIN MAX), "CHARSET", "UTF-8", *%w(OR UNSEEN FLAGGED)])
2059
+ # # Embedding return and charset in the criteria string
2060
+ # imap.search("RETURN (MIN MAX) CHARSET UTF-8 OR UNSEEN FLAGGED")
2061
+ #
2062
+ # Sending charset as the second positional argument is supported for
2063
+ # backward compatibility. Future versions may print a deprecation warning:
2064
+ # imap.search(%w(OR UNSEEN FLAGGED), "UTF-8", return: %w(MIN MAX))
2065
+ #
2066
+ # ==== Argument translation
2067
+ #
2068
+ # [+return+ options]
2069
+ # Must be an Array. Return option names may be either strings or symbols.
2070
+ # +Range+ elements which begin and end with negative integers are encoded
2071
+ # for use with +PARTIAL+--any other ranges are converted to SequenceSet.
2072
+ # Unlike +criteria+, other return option arguments are not automatically
2073
+ # converted to SequenceSet.
2074
+ #
2075
+ # [When +criteria+ is an Array]
2076
+ # When the array begins with <tt>"RETURN"</tt> (case insensitive), the
2077
+ # second array element is translated like the +return+ parameter (as
2078
+ # described above).
2079
+ #
2080
+ # Every other member is a +SEARCH+ command argument:
2081
+ # [SequenceSet]
2082
+ # Encoded as an \IMAP +sequence-set+ with SequenceSet#valid_string.
2083
+ # [Set, Range, <tt>-1</tt>, +:*+, responds to +#to_sequence_set+]
2084
+ # Converted to SequenceSet for validation and encoding.
2085
+ # [nested sequence-set +Array+]
2086
+ # When every element in a nested array is one of the above types, a
2087
+ # positive +Integer+, a sequence-set formatted +String+, or a deeply
2088
+ # nested +Array+ of these same types, the array will be converted to
2089
+ # SequenceSet for validation and encoding.
2090
+ # [Any other nested +Array+]
2091
+ # Otherwise, a nested array is encoded as a parenthesized list, to
2092
+ # combine multiple search keys (e.g., for use with +OR+ and +NOT+).
2093
+ # [+String+]
2094
+ # Sent verbatim when it is a valid \IMAP +atom+, and encoded as an \IMAP
2095
+ # +quoted+ or +literal+ string otherwise. Every standard search key
2096
+ # name is a valid \IMAP +atom+ and every standard search key string
2097
+ # argument is an +astring+ which may be encoded as +atom+, +quoted+, or
2098
+ # +literal+.
2099
+ #
2100
+ # *Note:* <tt>*</tt> is not a valid \IMAP +atom+ character. Any string
2101
+ # containing <tt>*</tt> will be encoded as a +quoted+ string, _not_ a
2102
+ # +sequence-set+.
2103
+ # [+Integer+ (except for <tt>-1</tt>)]
2104
+ # Encoded using +#to_s+.
2105
+ # [+Date+]
2106
+ # Encoded as an \IMAP date (see ::encode_date).
2107
+ #
2108
+ # [When +criteria+ is a String]
2109
+ # +criteria+ will be sent directly to the server <em>without any
2110
+ # validation or encoding</em>.
2111
+ #
2112
+ # <em>*WARNING:* This is vulnerable to injection attacks when external
2113
+ # inputs are used.</em>
2114
+ #
2115
+ # ==== Supported return options
2116
+ #
2117
+ # For full definitions of the standard return options and return data, see
2118
+ # the relevant RFCs.
2119
+ #
2120
+ # [+ALL+]
2121
+ # Returns ESearchResult#all with a SequenceSet of all matching sequence
2122
+ # numbers or UIDs. This is the default, when return options are empty.
2123
+ #
2124
+ # For compatibility with SearchResult, ESearchResult#to_a returns an
2125
+ # Array of message sequence numbers or UIDs.
2126
+ #
2127
+ # <em>Requires either the +ESEARCH+ or +IMAP4rev2+ capabability.</em>
2128
+ # {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731]
2129
+ # {[RFC9051]}[https://rfc-editor.org/rfc/rfc9051]
2130
+ #
2131
+ # [+COUNT+]
2132
+ # Returns ESearchResult#count with the number of matching messages.
2133
+ #
2134
+ # <em>Requires either the +ESEARCH+ or +IMAP4rev2+ capabability.</em>
2135
+ # {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731]
2136
+ # {[RFC9051]}[https://rfc-editor.org/rfc/rfc9051]
2137
+ #
2138
+ # [+MAX+]
2139
+ # Returns ESearchResult#max with the highest matching sequence number or
2140
+ # UID.
2141
+ #
2142
+ # <em>Requires either the +ESEARCH+ or +IMAP4rev2+ capabability.</em>
2143
+ # {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731]
2144
+ # {[RFC9051]}[https://rfc-editor.org/rfc/rfc9051]
2145
+ #
2146
+ # [+MIN+]
2147
+ # Returns ESearchResult#min with the lowest matching sequence number or
2148
+ # UID.
2149
+ #
2150
+ # <em>Requires either the +ESEARCH+ or +IMAP4rev2+ capabability.</em>
2151
+ # {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731]
2152
+ # {[RFC9051]}[https://rfc-editor.org/rfc/rfc9051]
2153
+ #
2154
+ # [+PARTIAL+ _range_]
2155
+ # Returns ESearchResult#partial with a SequenceSet of a subset of
2156
+ # matching sequence numbers or UIDs, as selected by _range_. As with
2157
+ # sequence numbers, the first result is +1+: <tt>1..500</tt> selects the
2158
+ # first 500 search results (in mailbox order), <tt>501..1000</tt> the
2159
+ # second 500, and so on. _range_ may also be negative: <tt>-500..-1</tt>
2160
+ # selects the last 500 search results.
2161
+ #
2162
+ # <em>Requires either the <tt>CONTEXT=SEARCH</tt> or +PARTIAL+ capabability.</em>
2163
+ # {[RFC5267]}[https://rfc-editor.org/rfc/rfc5267]
2164
+ # {[RFC9394]}[https://rfc-editor.org/rfc/rfc9394]
2165
+ #
2166
+ # ===== +MODSEQ+ return data
2167
+ #
2168
+ # ESearchResult#modseq return data does not have a corresponding return
2169
+ # option. Instead, it is returned if the +MODSEQ+ search key is used or
2170
+ # when the +CONDSTORE+ extension is enabled for the selected mailbox.
2171
+ # See [{RFC4731 §3.2}[https://www.rfc-editor.org/rfc/rfc4731#section-3.2]]
2172
+ # or [{RFC7162 §2.1.5}[https://www.rfc-editor.org/rfc/rfc7162#section-3.1.5]].
2173
+ #
2174
+ # ===== +RFC4466+ compatible extensions
2175
+ #
2176
+ # {RFC4466 §2.6}[https://www.rfc-editor.org/rfc/rfc4466.html#section-2.6]
2177
+ # defines standard syntax for search extensions. Net::IMAP allows sending
2178
+ # unsupported search return options and will parse unsupported search
2179
+ # extensions' return values into ExtensionData. Please note that this is an
2180
+ # intentionally _unstable_ API. Future releases may return different
2181
+ # (incompatible) objects, <em>without deprecation or warning</em>.
2182
+ #
2183
+ # ==== Search keys
1992
2184
  #
1993
2185
  # For full definitions of the standard search +criteria+,
1994
2186
  # see [{IMAP4rev1 §6.4.4}[https://www.rfc-editor.org/rfc/rfc3501.html#section-6.4.4]],
@@ -2003,23 +2195,21 @@ module Net
2003
2195
  # arguments. The number and type of arguments is specific to each search
2004
2196
  # key.
2005
2197
  #
2006
- # +ALL+::
2007
- # Matches every message in the mailbox.
2198
+ # ===== Search keys that match all messages
2008
2199
  #
2009
- # (_search-key_ _search-key_...)::
2010
- # Combines one or more _search-key_ arguments to match
2011
- # messages which match all contained search keys. Useful for +OR+, +NOT+,
2012
- # and other search keys with _search-key_ arguments.
2200
+ # [+ALL+]
2201
+ # The default initial key. Matches every message in the mailbox.
2013
2202
  #
2014
- # _Note:_ this search key has no label.
2203
+ # [+SAVEDATESUPPORTED+]
2204
+ # Matches every message in the mailbox when the mailbox supports the save
2205
+ # date attribute. Otherwise, it matches no messages.
2015
2206
  #
2016
- # +OR+ _search-key_ _search-key_::
2017
- # Matches messages which match either _search-key_ argument.
2207
+ # <em>Requires +SAVEDATE+ capability</em>.
2208
+ # {[RFC8514]}[https://www.rfc-editor.org/rfc/rfc8514.html#section-4.3]
2018
2209
  #
2019
- # +NOT+ _search-key_::
2020
- # Matches messages which do not match _search-key_.
2210
+ # ===== Sequence set search keys
2021
2211
  #
2022
- # _sequence-set_::
2212
+ # [_sequence-set_]
2023
2213
  # Matches messages with message sequence numbers in _sequence-set_.
2024
2214
  #
2025
2215
  # _Note:_ this search key has no label.
@@ -2027,121 +2217,139 @@ module Net
2027
2217
  # <em>+UIDONLY+ must *not* be enabled.</em>
2028
2218
  # {[RFC9586]}[https://www.rfc-editor.org/rfc/rfc9586.html]
2029
2219
  #
2030
- # +UID+ _sequence-set_::
2220
+ # [+UID+ _sequence-set_]
2031
2221
  # Matches messages with a UID in _sequence-set_.
2032
2222
  #
2033
- # +ANSWERED+::
2034
- # +UNANSWERED+::
2223
+ # ===== Compound search keys
2224
+ #
2225
+ # [(_search-key_ _search-key_...)]
2226
+ # Combines one or more _search-key_ arguments to match
2227
+ # messages which match all contained search keys. Useful for +OR+, +NOT+,
2228
+ # and other search keys with _search-key_ arguments.
2229
+ #
2230
+ # _Note:_ this search key has no label.
2231
+ #
2232
+ # [+OR+ _search-key_ _search-key_]
2233
+ # Matches messages which match either _search-key_ argument.
2234
+ #
2235
+ # [+NOT+ _search-key_]
2236
+ # Matches messages which do not match _search-key_.
2237
+ #
2238
+ # [+FUZZY+ _search-key_]
2239
+ # Uses fuzzy matching for the specified search key.
2240
+ #
2241
+ # <em>Requires <tt>SEARCH=FUZZY</tt> capability.</em>
2242
+ # {[RFC6203]}[https://www.rfc-editor.org/rfc/rfc6203.html#section-6].
2243
+ #
2244
+ # ===== Flags search keys
2245
+ #
2246
+ # [+ANSWERED+, +UNANSWERED+]
2035
2247
  # Matches messages with or without the <tt>\\Answered</tt> flag.
2036
- # +DELETED+::
2037
- # +UNDELETED+::
2248
+ # [+DELETED+, +UNDELETED+]
2038
2249
  # Matches messages with or without the <tt>\\Deleted</tt> flag.
2039
- # +DRAFT+::
2040
- # +UNDRAFT+::
2250
+ # [+DRAFT+, +UNDRAFT+]
2041
2251
  # Matches messages with or without the <tt>\\Draft</tt> flag.
2042
- # +FLAGGED+::
2043
- # +UNFLAGGED+::
2252
+ # [+FLAGGED+, +UNFLAGGED+]
2044
2253
  # Matches messages with or without the <tt>\\Flagged</tt> flag.
2045
- # +SEEN+::
2046
- # +UNSEEN+::
2254
+ # [+SEEN+, +UNSEEN+]
2047
2255
  # Matches messages with or without the <tt>\\Seen</tt> flag.
2048
- #
2049
- # +KEYWORD+ _keyword_::
2050
- # +UNKEYWORD+ _keyword_::
2256
+ # [+KEYWORD+ _keyword_, +UNKEYWORD+ _keyword_]
2051
2257
  # Matches messages with or without the specified _keyword_.
2052
2258
  #
2053
- # +BCC+ _substring_::
2054
- # Matches when _substring_ is in the envelope's BCC field.
2055
- # +CC+ _substring_::
2056
- # Matches when _substring_ is in the envelope's CC field.
2057
- # +FROM+ _substring_::
2058
- # Matches when _substring_ is in the envelope's FROM field.
2059
- # +SUBJECT+ _substring_::
2060
- # Matches when _substring_ is in the envelope's SUBJECT field.
2061
- # +TO+ _substring_::
2062
- # Matches when _substring_ is in the envelope's TO field.
2063
- #
2064
- # +HEADER+ _field_ _substring_::
2259
+ # [+RECENT+, +UNRECENT+]
2260
+ # Matches messages with or without the <tt>\\Recent</tt> flag.
2261
+ #
2262
+ # *NOTE:* The <tt>\\Recent</tt> flag has been removed from +IMAP4rev2+.
2263
+ # [+NEW+]
2264
+ # Equivalent to <tt>(RECENT UNSEEN)</tt>.
2265
+ #
2266
+ # *NOTE:* The <tt>\\Recent</tt> flag has been removed from +IMAP4rev2+.
2267
+ #
2268
+ # ===== Header field substring search keys
2269
+ #
2270
+ # [+BCC+ _substring_]
2271
+ # Matches when _substring_ is in the envelope's +BCC+ field.
2272
+ # [+CC+ _substring_]
2273
+ # Matches when _substring_ is in the envelope's +CC+ field.
2274
+ # [+FROM+ _substring_]
2275
+ # Matches when _substring_ is in the envelope's +FROM+ field.
2276
+ # [+SUBJECT+ _substring_]
2277
+ # Matches when _substring_ is in the envelope's +SUBJECT+ field.
2278
+ # [+TO+ _substring_]
2279
+ # Matches when _substring_ is in the envelope's +TO+ field.
2280
+ #
2281
+ # [+HEADER+ _field_ _substring_]
2065
2282
  # Matches when _substring_ is in the specified header _field_.
2066
2283
  #
2067
- # +BODY+ _string_::
2284
+ # ===== Body text search keys
2285
+ # [+BODY+ _string_]
2068
2286
  # Matches when _string_ is in the body of the message.
2069
2287
  # Does not match on header fields.
2070
2288
  #
2071
2289
  # The server _may_ use flexible matching, rather than simple substring
2072
2290
  # matches. For example, this may use stemming or match only full words.
2073
2291
  #
2074
- # +TEXT+ _string_::
2292
+ # [+TEXT+ _string_]
2075
2293
  # Matches when _string_ is in the header or body of the message.
2076
2294
  #
2077
2295
  # The server _may_ use flexible matching, rather than simple substring
2078
2296
  # matches. For example, this may use stemming or match only full words.
2079
2297
  #
2080
- # +BEFORE+ _date_::
2081
- # +ON+ _date_::
2082
- # +SINCE+ _date_::
2083
- # Matches when the +INTERNALDATE+ is earlier than, on, or later than
2084
- # _date_.
2298
+ # ===== Date/Time search keys
2085
2299
  #
2086
- # +SENTBEFORE+ _date_::
2087
- # +SENTON+ _date_::
2088
- # +SENTSINCE+ _date_::
2300
+ # [+SENTBEFORE+ _date_]
2301
+ # [+SENTON+ _date_]
2302
+ # [+SENTSINCE+ _date_]
2089
2303
  # Matches when the +Date+ header is earlier than, on, or later than _date_.
2090
2304
  #
2091
- # +SMALLER+ _bytes_::
2092
- # +LARGER+ _bytes_::
2093
- # Matches when +RFC822.SIZE+ is smaller/larger than _bytes_.
2094
- #
2095
- # ====== Removed from +IMAP4rev2+
2096
- #
2097
- # The <tt>\\Recent</tt> flag has been removed from +IMAP4rev2+. So these
2098
- # search keys require the +IMAP4rev1+ capability.
2305
+ # [+BEFORE+ _date_]
2306
+ # [+ON+ _date_]
2307
+ # [+SINCE+ _date_]
2308
+ # Matches when the +INTERNALDATE+ is earlier than, on, or later than
2309
+ # _date_.
2099
2310
  #
2100
- # +RECENT+::
2101
- # +UNRECENT+::
2102
- # Matches messages with or without the <tt>\\Recent</tt> flag.
2311
+ # [+OLDER+ _interval_]
2312
+ # [+YOUNGER+ _interval_]
2313
+ # Matches when the +INTERNALDATE+ is more/less than _interval_ seconds ago.
2103
2314
  #
2104
- # +NEW+::
2105
- # Equivalent to <tt>(RECENT UNSEEN)</tt>.
2315
+ # <em>Requires +WITHIN+ capability</em>.
2316
+ # {[RFC5032]}[https://www.rfc-editor.org/rfc/rfc5032.html]
2106
2317
  #
2107
- # ====== Extension search keys
2318
+ # [+SAVEDBEFORE+ _date_]
2319
+ # [+SAVEDON+ _date_]
2320
+ # [+SAVEDSINCE+ _date_]
2321
+ # Matches when the save date is earlier than, on, or later than _date_.
2108
2322
  #
2109
- # The search keys described below are defined by standard \IMAP extensions.
2323
+ # <em>Requires +SAVEDATE+ capability.</em>
2324
+ # {[RFC8514]}[https://www.rfc-editor.org/rfc/rfc8514.html#section-4.3]
2110
2325
  #
2111
- # +OLDER+ _interval_::
2112
- # +YOUNGER+ _interval_::
2113
- # Matches when +INTERNALDATE+ is more/less than _interval_ seconds ago.
2326
+ # ===== Other message attribute search keys
2114
2327
  #
2115
- # <em>Requires the +WITHIN+ capability</em>.
2116
- # {[RFC5032]}[https://www.rfc-editor.org/rfc/rfc5032.html]
2328
+ # [+SMALLER+ _bytes_]
2329
+ # [+LARGER+ _bytes_]
2330
+ # Matches when +RFC822.SIZE+ is smaller or larger than _bytes_.
2117
2331
  #
2118
- # +ANNOTATION+ _entry_ _attr_ _value_::
2332
+ # [+ANNOTATION+ _entry_ _attr_ _value_]
2119
2333
  # Matches messages that have annotations with entries matching _entry_,
2120
2334
  # attributes matching _attr_, and _value_ in the attribute's values.
2121
2335
  #
2122
- # <em>Requires the +ANNOTATE-EXPERIMENT-1+ capability</em>.
2336
+ # <em>Requires +ANNOTATE-EXPERIMENT-1+ capability</em>.
2123
2337
  # {[RFC5257]}[https://www.rfc-editor.org/rfc/rfc5257.html].
2124
2338
  #
2125
- # +FILTER+ _filter_::
2339
+ # [+FILTER+ _filter_]
2126
2340
  # References a _filter_ that is stored on the server and matches all
2127
2341
  # messages which would be matched by that filter's search criteria.
2128
2342
  #
2129
- # <em>Requires the +FILTERS+ capability</em>.
2343
+ # <em>Requires +FILTERS+ capability</em>.
2130
2344
  # {[RFC5466]}[https://www.rfc-editor.org/rfc/rfc5466.html#section-3.1]
2131
2345
  #
2132
- # +FUZZY+ _search-key_::
2133
- # Uses fuzzy matching for the specified search key.
2134
- #
2135
- # <em>Requires the <tt>SEARCH=FUZZY</tt> capability.</em>
2136
- # {[RFC6203]}[https://www.rfc-editor.org/rfc/rfc6203.html#section-6].
2137
- #
2138
- # +MODSEQ+ _modseq_::
2346
+ # [+MODSEQ+ _modseq_]
2139
2347
  # Matches when +MODSEQ+ is greater than or equal to _modseq_.
2140
2348
  #
2141
- # <em>Requires the +CONDSTORE+ capability</em>.
2349
+ # <em>Requires +CONDSTORE+ capability</em>.
2142
2350
  # {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html#section-3.1.5].
2143
2351
  #
2144
- # +MODSEQ+ _entry_ _entry-type_ _modseq_::
2352
+ # [+MODSEQ+ _entry_ _entry-type_ _modseq_]
2145
2353
  # Matches when a specific metadata _entry_ has been updated since
2146
2354
  # _modseq_.
2147
2355
  #
@@ -2150,33 +2358,25 @@ module Net
2150
2358
  # <tt>\\</tt> prefix. _entry-type_ can be one of <tt>"shared"</tt>,
2151
2359
  # <tt>"priv"</tt> (private), or <tt>"all"</tt>.
2152
2360
  #
2153
- # <em>Requires the +CONDSTORE+ capability</em>.
2361
+ # <em>Requires +CONDSTORE+ capability</em>.
2154
2362
  # {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html#section-3.1.5].
2155
2363
  #
2156
- # +EMAILID+ _objectid_::
2157
- # +THREADID+ _objectid_::
2364
+ # [+EMAILID+ _objectid_]
2365
+ # [+THREADID+ _objectid_]
2158
2366
  # Matches when +EMAILID+/+THREADID+ is equal to _objectid_
2159
2367
  # (substring matches are not supported).
2160
2368
  #
2161
- # <em>Requires the +OBJECTID+ capability</em>.
2369
+ # <em>Requires +OBJECTID+ capability</em>.
2162
2370
  # {[RFC8474]}[https://www.rfc-editor.org/rfc/rfc8474.html#section-6]
2163
2371
  #
2164
- # +SAVEDATESUPPORTED+::
2165
- # Matches every message in the mailbox when the mailbox supports the save
2166
- # date attribute. Otherwise, it matches no messages.
2167
- #
2168
- # <em>Requires the +SAVEDATE+ capability</em>.
2169
- # {[RFC8514]}[https://www.rfc-editor.org/rfc/rfc8514.html#section-4.3]
2170
- #
2171
- # +SAVEDBEFORE+ _date_::
2172
- # +SAVEDON+ _date_::
2173
- # +SAVEDSINCE+ _date_::
2174
- # Matches when the save date is earlier than, on, or later than _date_.
2372
+ # ==== Capabilities
2175
2373
  #
2176
- # <em>Requires the +SAVEDATE+ capability.</em>
2177
- # {[RFC8514]}[https://www.rfc-editor.org/rfc/rfc8514.html#section-4.3]
2374
+ # Return options should only be specified when the server supports
2375
+ # +IMAP4rev2+ or an extension that allows them, such as +ESEARCH+
2376
+ # [RFC4731[https://rfc-editor.org/rfc/rfc4731#section-3.1]].
2178
2377
  #
2179
- # ===== Capabilities
2378
+ # When +IMAP4rev2+ is enabled, or when the server supports +IMAP4rev2+ but
2379
+ # not +IMAP4rev1+, ESearchResult is always returned instead of SearchResult.
2180
2380
  #
2181
2381
  # If CONDSTORE[https://www.rfc-editor.org/rfc/rfc7162.html] is supported
2182
2382
  # and enabled for the selected mailbox, a non-empty SearchResult will
@@ -2185,12 +2385,16 @@ module Net
2185
2385
  # result = imap.search(["SUBJECT", "hi there", "not", "new"])
2186
2386
  # #=> Net::IMAP::SearchResult[1, 6, 7, 8, modseq: 5594]
2187
2387
  # result.modseq # => 5594
2388
+ #
2389
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled,
2390
+ # the +SEARCH+ command is prohibited. Use #uid_search instead.
2188
2391
  def search(...)
2189
2392
  search_internal("SEARCH", ...)
2190
2393
  end
2191
2394
 
2192
2395
  # :call-seq:
2193
2396
  # uid_search(criteria, charset = nil) -> result
2397
+ # uid_search(criteria, charset: nil, return: nil) -> result
2194
2398
  #
2195
2399
  # Sends a {UID SEARCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
2196
2400
  # to search the mailbox for messages that match the given searching
@@ -2201,6 +2405,16 @@ module Net
2201
2405
  # capability has been enabled.
2202
2406
  #
2203
2407
  # See #search for documentation of parameters.
2408
+ #
2409
+ # ==== Capabilities
2410
+ #
2411
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled,
2412
+ # #uid_search must be used instead of #search, and the <tt><message
2413
+ # set></tt> search criterion is prohibited. Use +ALL+ or <tt>UID
2414
+ # sequence-set</tt> instead.
2415
+ #
2416
+ # Otherwise, #uid_search is updated by extensions in the same way as
2417
+ # #search.
2204
2418
  def uid_search(...)
2205
2419
  search_internal("UID SEARCH", ...)
2206
2420
  end
@@ -2211,26 +2425,21 @@ module Net
2211
2425
  # Sends a {FETCH command [IMAP4rev1 §6.4.5]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.5]
2212
2426
  # to retrieve data associated with a message in the mailbox.
2213
2427
  #
2214
- # The +set+ parameter is a number or a range between two numbers,
2215
- # or an array of those. The number is a message sequence number,
2216
- # where -1 represents a '*' for use in range notation like 100..-1
2217
- # being interpreted as '100:*'. Beware that the +exclude_end?+
2218
- # property of a Range object is ignored, and the contents of a
2219
- # range are independent of the order of the range endpoints as per
2220
- # the protocol specification, so 1...5, 5..1 and 5...1 are all
2221
- # equivalent to 1..5.
2428
+ # +set+ is the message sequence numbers to fetch, and may be any valid input
2429
+ # to {SequenceSet[...]}[rdoc-ref:SequenceSet@Creating+sequence+sets].
2430
+ # (For UIDs, use #uid_fetch instead.)
2222
2431
  #
2223
- # +attr+ is a list of attributes to fetch; see the documentation
2224
- # for FetchData for a list of valid attributes.
2432
+ # +attr+ is a list of attributes to fetch; see FetchStruct documentation for
2433
+ # a list of supported attributes.
2225
2434
  #
2226
2435
  # +changedsince+ is an optional integer mod-sequence. It limits results to
2227
2436
  # messages with a mod-sequence greater than +changedsince+.
2228
2437
  #
2229
2438
  # The return value is an array of FetchData.
2230
2439
  #
2231
- # Related: #uid_search, FetchData
2440
+ # Related: #uid_fetch, FetchData
2232
2441
  #
2233
- # ===== For example:
2442
+ # ==== For example:
2234
2443
  #
2235
2444
  # p imap.fetch(6..8, "UID")
2236
2445
  # #=> [#<Net::IMAP::FetchData seqno=6, attr={"UID"=>98}>, \\
@@ -2248,39 +2457,82 @@ module Net
2248
2457
  # p data.attr["UID"]
2249
2458
  # #=> 98
2250
2459
  #
2251
- # ===== Capabilities
2460
+ # ==== Capabilities
2252
2461
  #
2253
- # Many extensions define new message +attr+ names. See FetchData for a list
2254
- # of supported extension fields.
2462
+ # Many extensions define new message +attr+ names. See FetchStruct for a
2463
+ # list of supported extension fields.
2255
2464
  #
2256
2465
  # The server's capabilities must include +CONDSTORE+
2257
- # {[RFC7162]}[https://tools.ietf.org/html/rfc7162] in order to use the
2466
+ # {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162] in order to use the
2258
2467
  # +changedsince+ argument. Using +changedsince+ implicitly enables the
2259
2468
  # +CONDSTORE+ extension.
2260
- def fetch(set, attr, mod = nil, changedsince: nil)
2261
- fetch_internal("FETCH", set, attr, mod, changedsince: changedsince)
2469
+ #
2470
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled, the
2471
+ # +FETCH+ command is prohibited. Use #uid_fetch instead.
2472
+ def fetch(...)
2473
+ fetch_internal("FETCH", ...)
2262
2474
  end
2263
2475
 
2264
2476
  # :call-seq:
2265
- # uid_fetch(set, attr, changedsince: nil) -> array of FetchData
2477
+ # uid_fetch(set, attr, changedsince: nil, partial: nil) -> array of FetchData (or UIDFetchData)
2266
2478
  #
2267
2479
  # Sends a {UID FETCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
2268
2480
  # to retrieve data associated with a message in the mailbox.
2269
2481
  #
2270
- # Similar to #fetch, but the +set+ parameter contains unique identifiers
2271
- # instead of message sequence numbers.
2482
+ # +set+ is the message UIDs to fetch, and may be any valid input to
2483
+ # {SequenceSet[...]}[rdoc-ref:SequenceSet@Creating+sequence+sets].
2484
+ # (For message sequence numbers, use #fetch instead.)
2272
2485
  #
2486
+ # +attr+ behaves the same as with #fetch.
2273
2487
  # >>>
2274
2488
  # *Note:* Servers _MUST_ implicitly include the +UID+ message data item as
2275
2489
  # part of any +FETCH+ response caused by a +UID+ command, regardless of
2276
2490
  # whether a +UID+ was specified as a message data item to the +FETCH+.
2277
2491
  #
2492
+ # +changedsince+ (optional) behaves the same as with #fetch.
2493
+ #
2494
+ # +partial+ is an optional range to limit the number of results returned.
2495
+ # It's useful when +set+ contains an unknown number of messages.
2496
+ # <tt>1..500</tt> returns the first 500 messages in +set+ (in mailbox
2497
+ # order), <tt>501..1000</tt> the second 500, and so on. +partial+ may also
2498
+ # be negative: <tt>-500..-1</tt> selects the last 500 messages in +set+.
2499
+ # <em>Requires the +PARTIAL+ capabability.</em>
2500
+ # {[RFC9394]}[https://rfc-editor.org/rfc/rfc9394]
2501
+ #
2502
+ # For example:
2503
+ #
2504
+ # # Without partial, the size of the results may be unknown beforehand:
2505
+ # results = imap.uid_fetch(next_uid_to_fetch.., %w(UID FLAGS))
2506
+ # # ... maybe wait for a long time ... and allocate a lot of memory ...
2507
+ # results.size # => 0..2**32-1
2508
+ # process results # may also take a long time and use a lot of memory...
2509
+ #
2510
+ # # Using partial, the results may be paginated:
2511
+ # loop do
2512
+ # results = imap.uid_fetch(next_uid_to_fetch.., %w(UID FLAGS),
2513
+ # partial: 1..500)
2514
+ # # fetch should return quickly and allocate little memory
2515
+ # results.size # => 0..500
2516
+ # break if results.empty?
2517
+ # next_uid_to_fetch = results.last.uid + 1
2518
+ # process results
2519
+ # end
2520
+ #
2278
2521
  # Related: #fetch, FetchData
2279
2522
  #
2280
- # ===== Capabilities
2281
- # Same as #fetch.
2282
- def uid_fetch(set, attr, mod = nil, changedsince: nil)
2283
- fetch_internal("UID FETCH", set, attr, mod, changedsince: changedsince)
2523
+ # ==== Capabilities
2524
+ #
2525
+ # The server's capabilities must include +PARTIAL+
2526
+ # {[RFC9394]}[https://rfc-editor.org/rfc/rfc9394] in order to use the
2527
+ # +partial+ argument.
2528
+ #
2529
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled,
2530
+ # #uid_fetch must be used instead of #fetch, and UIDFetchData will be
2531
+ # returned instead of FetchData.
2532
+ #
2533
+ # Otherwise, #uid_fetch is updated by extensions in the same way as #fetch.
2534
+ def uid_fetch(...)
2535
+ fetch_internal("UID FETCH", ...)
2284
2536
  end
2285
2537
 
2286
2538
  # :call-seq:
@@ -2311,27 +2563,30 @@ module Net
2311
2563
  #
2312
2564
  # Related: #uid_store
2313
2565
  #
2314
- # ===== For example:
2566
+ # ==== For example:
2315
2567
  #
2316
2568
  # p imap.store(6..8, "+FLAGS", [:Deleted])
2317
2569
  # #=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>,
2318
2570
  # #<Net::IMAP::FetchData seqno=7, attr={"FLAGS"=>[:Seen, :Deleted]}>,
2319
2571
  # #<Net::IMAP::FetchData seqno=8, attr={"FLAGS"=>[:Seen, :Deleted]}>]
2320
2572
  #
2321
- # ===== Capabilities
2573
+ # ==== Capabilities
2322
2574
  #
2323
2575
  # Extensions may define new data items to be used with #store.
2324
2576
  #
2325
2577
  # The server's capabilities must include +CONDSTORE+
2326
- # {[RFC7162]}[https://tools.ietf.org/html/rfc7162] in order to use the
2578
+ # {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162] in order to use the
2327
2579
  # +unchangedsince+ argument. Using +unchangedsince+ implicitly enables the
2328
2580
  # +CONDSTORE+ extension.
2581
+ #
2582
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled, the
2583
+ # +STORE+ command is prohibited. Use #uid_store instead.
2329
2584
  def store(set, attr, flags, unchangedsince: nil)
2330
2585
  store_internal("STORE", set, attr, flags, unchangedsince: unchangedsince)
2331
2586
  end
2332
2587
 
2333
2588
  # :call-seq:
2334
- # uid_store(set, attr, value, unchangedsince: nil) -> array of FetchData
2589
+ # uid_store(set, attr, value, unchangedsince: nil) -> array of FetchData (or UIDFetchData)
2335
2590
  #
2336
2591
  # Sends a {UID STORE command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
2337
2592
  # to alter data associated with messages in the mailbox, in particular their
@@ -2342,8 +2597,13 @@ module Net
2342
2597
  #
2343
2598
  # Related: #store
2344
2599
  #
2345
- # ===== Capabilities
2346
- # Same as #store.
2600
+ # ==== Capabilities
2601
+ #
2602
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled,
2603
+ # #uid_store must be used instead of #store, and UIDFetchData will be
2604
+ # returned instead of FetchData.
2605
+ #
2606
+ # Otherwise, #uid_store is updated by extensions in the same way as #store.
2347
2607
  def uid_store(set, attr, flags, unchangedsince: nil)
2348
2608
  store_internal("UID STORE", set, attr, flags, unchangedsince: unchangedsince)
2349
2609
  end
@@ -2355,13 +2615,16 @@ module Net
2355
2615
  #
2356
2616
  # Related: #uid_copy
2357
2617
  #
2358
- # ===== Capabilities
2618
+ # ==== Capabilities
2359
2619
  #
2360
2620
  # If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
2361
2621
  # supported, the server's response should include a +COPYUID+ response code
2362
2622
  # with UIDPlusData. This will report the UIDVALIDITY of the destination
2363
2623
  # mailbox, the UID set of the source messages, and the assigned UID set of
2364
2624
  # the moved messages.
2625
+ #
2626
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled, the
2627
+ # +COPY+ command is prohibited. Use #uid_copy instead.
2365
2628
  def copy(set, mailbox)
2366
2629
  copy_internal("COPY", set, mailbox)
2367
2630
  end
@@ -2372,9 +2635,12 @@ module Net
2372
2635
  #
2373
2636
  # Similar to #copy, but +set+ contains unique identifiers.
2374
2637
  #
2375
- # ===== Capabilities
2638
+ # ==== Capabilities
2639
+ #
2640
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] in enabled,
2641
+ # #uid_copy must be used instead of #copy.
2376
2642
  #
2377
- # +UIDPLUS+ affects #uid_copy the same way it affects #copy.
2643
+ # Otherwise, #uid_copy is updated by extensions in the same way as #copy.
2378
2644
  def uid_copy(set, mailbox)
2379
2645
  copy_internal("UID COPY", set, mailbox)
2380
2646
  end
@@ -2387,10 +2653,10 @@ module Net
2387
2653
  #
2388
2654
  # Related: #uid_move
2389
2655
  #
2390
- # ===== Capabilities
2656
+ # ==== Capabilities
2391
2657
  #
2392
- # The server's capabilities must include +MOVE+
2393
- # [RFC6851[https://tools.ietf.org/html/rfc6851]].
2658
+ # The server's capabilities must include either +IMAP4rev2+ or +MOVE+
2659
+ # [RFC6851[https://www.rfc-editor.org/rfc/rfc6851]].
2394
2660
  #
2395
2661
  # If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
2396
2662
  # supported, the server's response should include a +COPYUID+ response code
@@ -2398,6 +2664,8 @@ module Net
2398
2664
  # mailbox, the UID set of the source messages, and the assigned UID set of
2399
2665
  # the moved messages.
2400
2666
  #
2667
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled, the
2668
+ # +MOVE+ command is prohibited. Use #uid_move instead.
2401
2669
  def move(set, mailbox)
2402
2670
  copy_internal("MOVE", set, mailbox)
2403
2671
  end
@@ -2411,11 +2679,15 @@ module Net
2411
2679
  #
2412
2680
  # Related: #move
2413
2681
  #
2414
- # ===== Capabilities
2682
+ # ==== Capabilities
2683
+ #
2684
+ # The server's capabilities must include either +IMAP4rev2+ or +MOVE+
2685
+ # [RFC6851[https://www.rfc-editor.org/rfc/rfc6851]].
2415
2686
  #
2416
- # Same as #move: The server's capabilities must include +MOVE+
2417
- # [RFC6851[https://tools.ietf.org/html/rfc6851]]. +UIDPLUS+ also affects
2418
- # #uid_move the same way it affects #move.
2687
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled,
2688
+ # #uid_move must be used instead of #move.
2689
+ #
2690
+ # Otherwise, #uid_move is updated by extensions in the same way as #move.
2419
2691
  def uid_move(set, mailbox)
2420
2692
  copy_internal("UID MOVE", set, mailbox)
2421
2693
  end
@@ -2431,17 +2703,17 @@ module Net
2431
2703
  #
2432
2704
  # Related: #uid_sort, #search, #uid_search, #thread, #uid_thread
2433
2705
  #
2434
- # ===== For example:
2706
+ # ==== For example:
2435
2707
  #
2436
2708
  # p imap.sort(["FROM"], ["ALL"], "US-ASCII")
2437
2709
  # #=> [1, 2, 3, 5, 6, 7, 8, 4, 9]
2438
2710
  # p imap.sort(["DATE"], ["SUBJECT", "hello"], "US-ASCII")
2439
2711
  # #=> [6, 7, 8, 1]
2440
2712
  #
2441
- # ===== Capabilities
2713
+ # ==== Capabilities
2442
2714
  #
2443
2715
  # The server's capabilities must include +SORT+
2444
- # [RFC5256[https://tools.ietf.org/html/rfc5256]].
2716
+ # [RFC5256[https://www.rfc-editor.org/rfc/rfc5256]].
2445
2717
  def sort(sort_keys, search_keys, charset)
2446
2718
  return sort_internal("SORT", sort_keys, search_keys, charset)
2447
2719
  end
@@ -2453,10 +2725,10 @@ module Net
2453
2725
  #
2454
2726
  # Related: #sort, #search, #uid_search, #thread, #uid_thread
2455
2727
  #
2456
- # ===== Capabilities
2728
+ # ==== Capabilities
2457
2729
  #
2458
2730
  # The server's capabilities must include +SORT+
2459
- # [RFC5256[https://tools.ietf.org/html/rfc5256]].
2731
+ # [RFC5256[https://www.rfc-editor.org/rfc/rfc5256]].
2460
2732
  def uid_sort(sort_keys, search_keys, charset)
2461
2733
  return sort_internal("UID SORT", sort_keys, search_keys, charset)
2462
2734
  end
@@ -2478,10 +2750,10 @@ module Net
2478
2750
  #
2479
2751
  # Related: #uid_thread, #search, #uid_search, #sort, #uid_sort
2480
2752
  #
2481
- # ===== Capabilities
2753
+ # ==== Capabilities
2482
2754
  #
2483
2755
  # The server's capabilities must include +THREAD+
2484
- # [RFC5256[https://tools.ietf.org/html/rfc5256]].
2756
+ # [RFC5256[https://www.rfc-editor.org/rfc/rfc5256]].
2485
2757
  def thread(algorithm, search_keys, charset)
2486
2758
  return thread_internal("THREAD", algorithm, search_keys, charset)
2487
2759
  end
@@ -2492,10 +2764,10 @@ module Net
2492
2764
  #
2493
2765
  # Related: #thread, #search, #uid_search, #sort, #uid_sort
2494
2766
  #
2495
- # ===== Capabilities
2767
+ # ==== Capabilities
2496
2768
  #
2497
2769
  # The server's capabilities must include +THREAD+
2498
- # [RFC5256[https://tools.ietf.org/html/rfc5256]].
2770
+ # [RFC5256[https://www.rfc-editor.org/rfc/rfc5256]].
2499
2771
  def uid_thread(algorithm, search_keys, charset)
2500
2772
  return thread_internal("UID THREAD", algorithm, search_keys, charset)
2501
2773
  end
@@ -2511,11 +2783,11 @@ module Net
2511
2783
  #
2512
2784
  # Related: #capable?, #capabilities, #capability
2513
2785
  #
2514
- # ===== Capabilities
2786
+ # ==== Capabilities
2515
2787
  #
2516
2788
  # The server's capabilities must include
2517
- # +ENABLE+ [RFC5161[https://tools.ietf.org/html/rfc5161]]
2518
- # or +IMAP4REV2+ [RFC9051[https://tools.ietf.org/html/rfc9051]].
2789
+ # +ENABLE+ [RFC5161[https://www.rfc-editor.org/rfc/rfc5161]]
2790
+ # or +IMAP4REV2+ [RFC9051[https://www.rfc-editor.org/rfc/rfc9051]].
2519
2791
  #
2520
2792
  # Additionally, the server capabilities must include a capability matching
2521
2793
  # each enabled extension (usually the same name as the enabled extension).
@@ -2534,7 +2806,7 @@ module Net
2534
2806
  # <tt>"UTF8=ACCEPT"</tt> or <tt>"IMAP4rev2"</tt>, depending on server
2535
2807
  # capabilities.
2536
2808
  #
2537
- # [<tt>"UTF8=ACCEPT"</tt> [RFC6855[https://tools.ietf.org/html/rfc6855]]]
2809
+ # [<tt>"UTF8=ACCEPT"</tt> [RFC6855[https://www.rfc-editor.org/rfc/rfc6855]]]
2538
2810
  #
2539
2811
  # The server's capabilities must include <tt>UTF8=ACCEPT</tt> _or_
2540
2812
  # <tt>UTF8=ONLY</tt>.
@@ -2553,13 +2825,23 @@ module Net
2553
2825
  # encoding, even if they generally contain UTF-8 data, if they are
2554
2826
  # text at all.
2555
2827
  #
2556
- # [<tt>"UTF8=ONLY"</tt> [RFC6855[https://tools.ietf.org/html/rfc6855]]]
2828
+ # [<tt>"UTF8=ONLY"</tt> [RFC6855[https://www.rfc-editor.org/rfc/rfc6855]]]
2557
2829
  #
2558
2830
  # A server that reports the <tt>UTF8=ONLY</tt> capability _requires_ that
2559
2831
  # the client <tt>enable("UTF8=ACCEPT")</tt> before any mailboxes may be
2560
2832
  # selected. For convenience, <tt>enable("UTF8=ONLY")</tt> is aliased to
2561
2833
  # <tt>enable("UTF8=ACCEPT")</tt>.
2562
2834
  #
2835
+ # [+UIDONLY+ {[RFC9586]}[https://www.rfc-editor.org/rfc/rfc9586.pdf]]
2836
+ #
2837
+ # When UIDONLY is enabled, the #fetch, #store, #search, #copy, and #move
2838
+ # commands are prohibited and result in a tagged BAD response. Clients
2839
+ # should instead use uid_fetch, uid_store, uid_search, uid_copy, or
2840
+ # uid_move, respectively. All +FETCH+ responses that would be returned are
2841
+ # replaced by +UIDFETCH+ responses. All +EXPUNGED+ responses that would be
2842
+ # returned are replaced by +VANISHED+ responses. The "<sequence set>"
2843
+ # uid_search criterion is prohibited.
2844
+ #
2563
2845
  # ===== Unsupported capabilities
2564
2846
  #
2565
2847
  # *Note:* Some extensions that use ENABLE permit the server to send syntax
@@ -2613,10 +2895,10 @@ module Net
2613
2895
  #
2614
2896
  # Related: #idle_done, #noop, #check
2615
2897
  #
2616
- # ===== Capabilities
2898
+ # ==== Capabilities
2617
2899
  #
2618
- # The server's capabilities must include +IDLE+
2619
- # [RFC2177[https://tools.ietf.org/html/rfc2177]].
2900
+ # The server's capabilities must include either +IMAP4rev2+ or +IDLE+
2901
+ # [RFC2177[https://www.rfc-editor.org/rfc/rfc2177]].
2620
2902
  def idle(timeout = nil, &response_handler)
2621
2903
  raise LocalJumpError, "no block given" unless response_handler
2622
2904
 
@@ -2730,7 +3012,7 @@ module Net
2730
3012
  #
2731
3013
  # Related: #extract_responses, #clear_responses, #response_handlers, #greeting
2732
3014
  #
2733
- # ===== Thread safety
3015
+ # ==== Thread safety
2734
3016
  # >>>
2735
3017
  # *Note:* Access to the responses hash is synchronized for thread-safety.
2736
3018
  # The receiver thread and response_handlers cannot process new responses
@@ -2744,7 +3026,7 @@ module Net
2744
3026
  # thread, but will not modify any responses after adding them to the
2745
3027
  # responses hash.
2746
3028
  #
2747
- # ===== Clearing responses
3029
+ # ==== Clearing responses
2748
3030
  #
2749
3031
  # Previously unhandled responses are automatically cleared before entering a
2750
3032
  # mailbox with #select or #examine. Long-lived connections can receive many
@@ -2753,7 +3035,7 @@ module Net
2753
3035
  # the block, or remove responses with #extract_responses, #clear_responses,
2754
3036
  # or #add_response_handler.
2755
3037
  #
2756
- # ===== Missing responses
3038
+ # ==== Missing responses
2757
3039
  #
2758
3040
  # Only non-+nil+ data is stored. Many important response codes have no data
2759
3041
  # of their own, but are used as "tags" on the ResponseText object they are
@@ -3131,16 +3413,107 @@ module Net
3131
3413
  end
3132
3414
  end
3133
3415
 
3134
- def search_internal(cmd, keys, charset = nil)
3135
- keys = normalize_searching_criteria(keys)
3136
- args = charset ? ["CHARSET", charset, *keys] : keys
3416
+ def expunge_internal(...)
3137
3417
  synchronize do
3138
- send_command(cmd, *args)
3139
- clear_responses("SEARCH").last || []
3418
+ send_command(...)
3419
+ expunged_array = clear_responses("EXPUNGE")
3420
+ vanished_array = extract_responses("VANISHED") { !_1.earlier? }
3421
+ if vanished_array.empty?
3422
+ expunged_array
3423
+ elsif vanished_array.length == 1
3424
+ vanished_array.first
3425
+ else
3426
+ merged_uids = SequenceSet[*vanished_array.map(&:uids)]
3427
+ VanishedData[uids: merged_uids, earlier: false]
3428
+ end
3140
3429
  end
3141
3430
  end
3142
3431
 
3143
- def fetch_internal(cmd, set, attr, mod = nil, changedsince: nil)
3432
+ RETURN_WHOLE = /\ARETURN\z/i
3433
+ RETURN_START = /\ARETURN\b/i
3434
+ private_constant :RETURN_WHOLE, :RETURN_START
3435
+
3436
+ def search_args(keys, charset_arg = nil, return: nil, charset: nil)
3437
+ {return:} => {return: return_kw}
3438
+ case [return_kw, keys]
3439
+ in [nil, Array[RETURN_WHOLE, return_opts, *keys]]
3440
+ return_opts = convert_return_opts(return_opts)
3441
+ esearch = true
3442
+ in [nil => return_opts, RETURN_START]
3443
+ esearch = true
3444
+ in [nil => return_opts, keys]
3445
+ esearch = false
3446
+ in [_, Array[RETURN_WHOLE, _, *] | RETURN_START]
3447
+ raise ArgumentError, "conflicting return options"
3448
+ in [_, Array[RETURN_WHOLE, _, *]] # workaround for https://bugs.ruby-lang.org/issues/20956
3449
+ raise ArgumentError, "conflicting return options"
3450
+ in [_, RETURN_START] # workaround for https://bugs.ruby-lang.org/issues/20956
3451
+ raise ArgumentError, "conflicting return options"
3452
+ in [return_opts, keys]
3453
+ return_opts = convert_return_opts(return_opts)
3454
+ esearch = true
3455
+ end
3456
+ if charset && charset_arg
3457
+ raise ArgumentError, "multiple charset arguments"
3458
+ end
3459
+ charset ||= charset_arg
3460
+ # NOTE: not handling combined RETURN and CHARSET for raw strings
3461
+ if charset && keys in /\ACHARSET\b/i | Array[/\ACHARSET\z/i, *]
3462
+ raise ArgumentError, "multiple charset arguments"
3463
+ end
3464
+ args = normalize_searching_criteria(keys)
3465
+ args.prepend("CHARSET", charset) if charset
3466
+ args.prepend("RETURN", return_opts) if return_opts
3467
+ return args, esearch
3468
+ end
3469
+
3470
+ def convert_return_opts(unconverted)
3471
+ return_opts = Array.try_convert(unconverted) or
3472
+ raise TypeError, "expected return options to be Array, got %s" % [
3473
+ unconverted.class
3474
+ ]
3475
+ return_opts.map {|opt|
3476
+ case opt
3477
+ when Symbol then opt.to_s
3478
+ when PartialRange::Negative then PartialRange[opt]
3479
+ when Range then SequenceSet[opt]
3480
+ else opt
3481
+ end
3482
+ }
3483
+ end
3484
+
3485
+ def search_internal(cmd, ...)
3486
+ args, esearch = search_args(...)
3487
+ synchronize do
3488
+ tagged = send_command(cmd, *args)
3489
+ tag = tagged.tag
3490
+ # Only the last ESEARCH or SEARCH is used. Excess results are ignored.
3491
+ esearch_result = extract_responses("ESEARCH") {|response|
3492
+ response in ESearchResult(tag: ^tag)
3493
+ }.last
3494
+ search_result = clear_responses("SEARCH").last
3495
+ if esearch_result
3496
+ # silently ignore SEARCH results, if any
3497
+ esearch_result
3498
+ elsif search_result
3499
+ # warn EXPECTED_ESEARCH_RESULT if esearch
3500
+ search_result
3501
+ elsif esearch
3502
+ # warn NO_SEARCH_RESPONSE
3503
+ ESearchResult[tag:, uid: cmd.start_with?("UID ")]
3504
+ else
3505
+ # warn NO_SEARCH_RESPONSE
3506
+ SearchResult[]
3507
+ end
3508
+ end
3509
+ end
3510
+
3511
+ def fetch_internal(cmd, set, attr, mod = nil, partial: nil, changedsince: nil)
3512
+ set = SequenceSet[set]
3513
+ if partial
3514
+ mod ||= []
3515
+ mod << "PARTIAL" << PartialRange[partial]
3516
+ end
3144
3517
  if changedsince
3145
3518
  mod ||= []
3146
3519
  mod << "CHANGEDSINCE" << Integer(changedsince)
@@ -3154,15 +3527,9 @@ module Net
3154
3527
  }
3155
3528
  end
3156
3529
 
3157
- synchronize do
3158
- clear_responses("FETCH")
3159
- if mod
3160
- send_command(cmd, SequenceSet.new(set), attr, mod)
3161
- else
3162
- send_command(cmd, SequenceSet.new(set), attr)
3163
- end
3164
- clear_responses("FETCH")
3165
- end
3530
+ args = [cmd, set, attr]
3531
+ args << mod if mod
3532
+ send_command_returning_fetch_results(*args)
3166
3533
  end
3167
3534
 
3168
3535
  def store_internal(cmd, set, attr, flags, unchangedsince: nil)
@@ -3170,10 +3537,17 @@ module Net
3170
3537
  args = [SequenceSet.new(set)]
3171
3538
  args << ["UNCHANGEDSINCE", Integer(unchangedsince)] if unchangedsince
3172
3539
  args << attr << flags
3540
+ send_command_returning_fetch_results(cmd, *args)
3541
+ end
3542
+
3543
+ def send_command_returning_fetch_results(...)
3173
3544
  synchronize do
3174
3545
  clear_responses("FETCH")
3175
- send_command(cmd, *args)
3176
- clear_responses("FETCH")
3546
+ clear_responses("UIDFETCH")
3547
+ send_command(...)
3548
+ fetches = clear_responses("FETCH")
3549
+ uidfetches = clear_responses("UIDFETCH")
3550
+ uidfetches.any? ? uidfetches : fetches
3177
3551
  end
3178
3552
  end
3179
3553
 
@@ -3198,7 +3572,7 @@ module Net
3198
3572
  end
3199
3573
 
3200
3574
  def normalize_searching_criteria(criteria)
3201
- return RawData.new(criteria) if criteria.is_a?(String)
3575
+ return [RawData.new(criteria)] if criteria.is_a?(String)
3202
3576
  criteria.map {|i|
3203
3577
  if coerce_search_arg_to_seqset?(i)
3204
3578
  SequenceSet[i]
@@ -3276,6 +3650,7 @@ require_relative "imap/errors"
3276
3650
  require_relative "imap/config"
3277
3651
  require_relative "imap/command_data"
3278
3652
  require_relative "imap/data_encoding"
3653
+ require_relative "imap/data_lite"
3279
3654
  require_relative "imap/flags"
3280
3655
  require_relative "imap/response_data"
3281
3656
  require_relative "imap/response_parser"