net-imap 0.5.2 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of net-imap might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +3 -1
- data/docs/styles.css +12 -7
- data/lib/net/imap/command_data.rb +32 -0
- data/lib/net/imap/config.rb +73 -3
- data/lib/net/imap/data_lite.rb +11 -10
- data/lib/net/imap/esearch_result.rb +44 -4
- data/lib/net/imap/fetch_data.rb +126 -47
- data/lib/net/imap/response_data.rb +117 -144
- data/lib/net/imap/response_parser.rb +106 -16
- data/lib/net/imap/sasl/anonymous_authenticator.rb +3 -3
- data/lib/net/imap/sasl/cram_md5_authenticator.rb +3 -3
- data/lib/net/imap/sasl/digest_md5_authenticator.rb +8 -8
- data/lib/net/imap/sasl/external_authenticator.rb +2 -2
- data/lib/net/imap/sasl/gs2_header.rb +7 -7
- data/lib/net/imap/sasl/login_authenticator.rb +2 -2
- data/lib/net/imap/sasl/oauthbearer_authenticator.rb +6 -6
- data/lib/net/imap/sasl/plain_authenticator.rb +7 -7
- data/lib/net/imap/sasl/scram_authenticator.rb +8 -8
- data/lib/net/imap/sasl.rb +1 -1
- data/lib/net/imap/search_result.rb +2 -2
- data/lib/net/imap/sequence_set.rb +193 -58
- data/lib/net/imap/stringprep/nameprep.rb +1 -1
- data/lib/net/imap/stringprep/trace.rb +4 -4
- data/lib/net/imap/uidplus_data.rb +244 -0
- data/lib/net/imap/vanished_data.rb +56 -0
- data/lib/net/imap.rb +325 -161
- data/rakelib/rfcs.rake +2 -0
- metadata +5 -6
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://
|
29
|
-
# and {IMAP4rev2 [RFC9051]}[https://
|
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://
|
302
|
+
# the [IMAP4rev1[https://www.rfc-editor.org/rfc/rfc3501]] base specification, or
|
303
303
|
# by one of the following extensions:
|
304
|
-
# [IDLE[https://
|
305
|
-
# [NAMESPACE[https://
|
306
|
-
# [UNSELECT[https://
|
307
|
-
# [ENABLE[https://
|
308
|
-
# [MOVE[https://
|
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://
|
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://
|
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+.
|
@@ -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://
|
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://
|
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://
|
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://
|
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,7 +459,7 @@ module Net
|
|
459
459
|
# *NOTE:* +DELETEACL+, +LISTRIGHTS+, and +MYRIGHTS+ are not supported yet.
|
460
460
|
#
|
461
461
|
# ==== RFC4315: +UIDPLUS+
|
462
|
-
# Folded into IMAP4rev2[https://
|
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
|
@@ -467,15 +467,15 @@ module Net
|
|
467
467
|
# - Updates #copy, #move with the +COPYUID+ ResponseCode
|
468
468
|
#
|
469
469
|
# ==== RFC4731: +ESEARCH+
|
470
|
-
# Folded into IMAP4rev2[https://
|
470
|
+
# Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051].
|
471
471
|
# - Updates #search, #uid_search with +return+ options and ESearchResult.
|
472
472
|
#
|
473
473
|
# ==== RFC4959: +SASL-IR+
|
474
|
-
# Folded into IMAP4rev2[https://
|
474
|
+
# Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051].
|
475
475
|
# - Updates #authenticate with the option to send an initial response.
|
476
476
|
#
|
477
477
|
# ==== RFC5161: +ENABLE+
|
478
|
-
# Folded into IMAP4rev2[https://
|
478
|
+
# Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] and also included
|
479
479
|
# above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
|
480
480
|
# - #enable: Enables backwards incompatible server extensions.
|
481
481
|
#
|
@@ -499,7 +499,7 @@ module Net
|
|
499
499
|
# +X-GM-THRID+, but Gmail does not support it (as of 2023-11-10).
|
500
500
|
#
|
501
501
|
# ==== RFC6851: +MOVE+
|
502
|
-
# Folded into IMAP4rev2[https://
|
502
|
+
# Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] and also included
|
503
503
|
# above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
|
504
504
|
# - #move, #uid_move: Moves the specified messages to the end of the
|
505
505
|
# specified destination mailbox, expunging them from the current mailbox.
|
@@ -534,6 +534,17 @@ module Net
|
|
534
534
|
# See FetchData#emailid and FetchData#emailid.
|
535
535
|
# - Updates #status with support for the +MAILBOXID+ status attribute.
|
536
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
|
+
#
|
537
548
|
# == References
|
538
549
|
#
|
539
550
|
# [{IMAP4rev1}[https://www.rfc-editor.org/rfc/rfc3501.html]]::
|
@@ -564,57 +575,57 @@ module Net
|
|
564
575
|
# Gahrns, M., "IMAP4 Multi-Accessed Mailbox Practice", RFC 2180, DOI
|
565
576
|
# 10.17487/RFC2180, July 1997, <https://www.rfc-editor.org/info/rfc2180>.
|
566
577
|
#
|
567
|
-
# [UTF7[https://
|
578
|
+
# [UTF7[https://www.rfc-editor.org/rfc/rfc2152]]::
|
568
579
|
# Goldsmith, D. and M. Davis, "UTF-7 A Mail-Safe Transformation Format of
|
569
580
|
# Unicode", RFC 2152, DOI 10.17487/RFC2152, May 1997,
|
570
581
|
# <https://www.rfc-editor.org/info/rfc2152>.
|
571
582
|
#
|
572
583
|
# === Message envelope and body structure
|
573
584
|
#
|
574
|
-
# [RFC5322[https://
|
585
|
+
# [RFC5322[https://www.rfc-editor.org/rfc/rfc5322]]::
|
575
586
|
# Resnick, P., Ed., "Internet Message Format",
|
576
587
|
# RFC 5322, DOI 10.17487/RFC5322, October 2008,
|
577
588
|
# <https://www.rfc-editor.org/info/rfc5322>.
|
578
589
|
#
|
579
590
|
# <em>Note: obsoletes</em>
|
580
|
-
# RFC-2822[https://
|
581
|
-
# RFC-822[https://
|
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>
|
582
593
|
#
|
583
|
-
# [CHARSET[https://
|
594
|
+
# [CHARSET[https://www.rfc-editor.org/rfc/rfc2978]]::
|
584
595
|
# Freed, N. and J. Postel, "IANA Charset Registration Procedures", BCP 19,
|
585
596
|
# RFC 2978, DOI 10.17487/RFC2978, October 2000,
|
586
597
|
# <https://www.rfc-editor.org/info/rfc2978>.
|
587
598
|
#
|
588
|
-
# [DISPOSITION[https://
|
599
|
+
# [DISPOSITION[https://www.rfc-editor.org/rfc/rfc2183]]::
|
589
600
|
# Troost, R., Dorner, S., and K. Moore, Ed., "Communicating Presentation
|
590
601
|
# Information in Internet Messages: The Content-Disposition Header
|
591
602
|
# Field", RFC 2183, DOI 10.17487/RFC2183, August 1997,
|
592
603
|
# <https://www.rfc-editor.org/info/rfc2183>.
|
593
604
|
#
|
594
|
-
# [MIME-IMB[https://
|
605
|
+
# [MIME-IMB[https://www.rfc-editor.org/rfc/rfc2045]]::
|
595
606
|
# Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions
|
596
607
|
# (MIME) Part One: Format of Internet Message Bodies",
|
597
608
|
# RFC 2045, DOI 10.17487/RFC2045, November 1996,
|
598
609
|
# <https://www.rfc-editor.org/info/rfc2045>.
|
599
610
|
#
|
600
|
-
# [MIME-IMT[https://
|
611
|
+
# [MIME-IMT[https://www.rfc-editor.org/rfc/rfc2046]]::
|
601
612
|
# Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions
|
602
613
|
# (MIME) Part Two: Media Types", RFC 2046, DOI 10.17487/RFC2046,
|
603
614
|
# November 1996, <https://www.rfc-editor.org/info/rfc2046>.
|
604
615
|
#
|
605
|
-
# [MIME-HDRS[https://
|
616
|
+
# [MIME-HDRS[https://www.rfc-editor.org/rfc/rfc2047]]::
|
606
617
|
# Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part Three:
|
607
618
|
# Message Header Extensions for Non-ASCII Text",
|
608
619
|
# RFC 2047, DOI 10.17487/RFC2047, November 1996,
|
609
620
|
# <https://www.rfc-editor.org/info/rfc2047>.
|
610
621
|
#
|
611
|
-
# [RFC2231[https://
|
622
|
+
# [RFC2231[https://www.rfc-editor.org/rfc/rfc2231]]::
|
612
623
|
# Freed, N. and K. Moore, "MIME Parameter Value and Encoded Word
|
613
624
|
# Extensions: Character Sets, Languages, and Continuations",
|
614
625
|
# RFC 2231, DOI 10.17487/RFC2231, November 1997,
|
615
626
|
# <https://www.rfc-editor.org/info/rfc2231>.
|
616
627
|
#
|
617
|
-
# [I18n-HDRS[https://
|
628
|
+
# [I18n-HDRS[https://www.rfc-editor.org/rfc/rfc6532]]::
|
618
629
|
# Yang, A., Steele, S., and N. Freed, "Internationalized Email Headers",
|
619
630
|
# RFC 6532, DOI 10.17487/RFC6532, February 2012,
|
620
631
|
# <https://www.rfc-editor.org/info/rfc6532>.
|
@@ -630,12 +641,12 @@ module Net
|
|
630
641
|
# RFC 2557, DOI 10.17487/RFC2557, March 1999,
|
631
642
|
# <https://www.rfc-editor.org/info/rfc2557>.
|
632
643
|
#
|
633
|
-
# [MD5[https://
|
644
|
+
# [MD5[https://www.rfc-editor.org/rfc/rfc1864]]::
|
634
645
|
# Myers, J. and M. Rose, "The Content-MD5 Header Field",
|
635
646
|
# RFC 1864, DOI 10.17487/RFC1864, October 1995,
|
636
647
|
# <https://www.rfc-editor.org/info/rfc1864>.
|
637
648
|
#
|
638
|
-
# [RFC3503[https://
|
649
|
+
# [RFC3503[https://www.rfc-editor.org/rfc/rfc3503]]::
|
639
650
|
# Melnikov, A., "Message Disposition Notification (MDN)
|
640
651
|
# profile for Internet Message Access Protocol (IMAP)",
|
641
652
|
# RFC 3503, DOI 10.17487/RFC3503, March 2003,
|
@@ -643,27 +654,27 @@ module Net
|
|
643
654
|
#
|
644
655
|
# === \IMAP Extensions
|
645
656
|
#
|
646
|
-
# [QUOTA[https://
|
657
|
+
# [QUOTA[https://www.rfc-editor.org/rfc/rfc9208]]::
|
647
658
|
# Melnikov, A., "IMAP QUOTA Extension", RFC 9208, DOI 10.17487/RFC9208,
|
648
659
|
# March 2022, <https://www.rfc-editor.org/info/rfc9208>.
|
649
660
|
#
|
650
661
|
# <em>Note: obsoletes</em>
|
651
|
-
# RFC-2087[https://
|
662
|
+
# RFC-2087[https://www.rfc-editor.org/rfc/rfc2087]<em> (January 1997)</em>.
|
652
663
|
# <em>Net::IMAP does not fully support the RFC9208 updates yet.</em>
|
653
|
-
# [IDLE[https://
|
664
|
+
# [IDLE[https://www.rfc-editor.org/rfc/rfc2177]]::
|
654
665
|
# Leiba, B., "IMAP4 IDLE command", RFC 2177, DOI 10.17487/RFC2177,
|
655
666
|
# June 1997, <https://www.rfc-editor.org/info/rfc2177>.
|
656
|
-
# [NAMESPACE[https://
|
667
|
+
# [NAMESPACE[https://www.rfc-editor.org/rfc/rfc2342]]::
|
657
668
|
# Gahrns, M. and C. Newman, "IMAP4 Namespace", RFC 2342,
|
658
669
|
# DOI 10.17487/RFC2342, May 1998, <https://www.rfc-editor.org/info/rfc2342>.
|
659
|
-
# [ID[https://
|
670
|
+
# [ID[https://www.rfc-editor.org/rfc/rfc2971]]::
|
660
671
|
# Showalter, T., "IMAP4 ID extension", RFC 2971, DOI 10.17487/RFC2971,
|
661
672
|
# October 2000, <https://www.rfc-editor.org/info/rfc2971>.
|
662
|
-
# [BINARY[https://
|
673
|
+
# [BINARY[https://www.rfc-editor.org/rfc/rfc3516]]::
|
663
674
|
# Nerenberg, L., "IMAP4 Binary Content Extension", RFC 3516,
|
664
675
|
# DOI 10.17487/RFC3516, April 2003,
|
665
676
|
# <https://www.rfc-editor.org/info/rfc3516>.
|
666
|
-
# [ACL[https://
|
677
|
+
# [ACL[https://www.rfc-editor.org/rfc/rfc4314]]::
|
667
678
|
# Melnikov, A., "IMAP4 Access Control List (ACL) Extension", RFC 4314,
|
668
679
|
# DOI 10.17487/RFC4314, December 2005,
|
669
680
|
# <https://www.rfc-editor.org/info/rfc4314>.
|
@@ -671,36 +682,46 @@ module Net
|
|
671
682
|
# Crispin, M., "Internet Message Access Protocol (\IMAP) - UIDPLUS
|
672
683
|
# extension", RFC 4315, DOI 10.17487/RFC4315, December 2005,
|
673
684
|
# <https://www.rfc-editor.org/info/rfc4315>.
|
674
|
-
# [SORT[https://
|
685
|
+
# [SORT[https://www.rfc-editor.org/rfc/rfc5256]]::
|
675
686
|
# Crispin, M. and K. Murchison, "Internet Message Access Protocol - SORT and
|
676
687
|
# THREAD Extensions", RFC 5256, DOI 10.17487/RFC5256, June 2008,
|
677
688
|
# <https://www.rfc-editor.org/info/rfc5256>.
|
678
|
-
# [THREAD[https://
|
689
|
+
# [THREAD[https://www.rfc-editor.org/rfc/rfc5256]]::
|
679
690
|
# Crispin, M. and K. Murchison, "Internet Message Access Protocol - SORT and
|
680
691
|
# THREAD Extensions", RFC 5256, DOI 10.17487/RFC5256, June 2008,
|
681
692
|
# <https://www.rfc-editor.org/info/rfc5256>.
|
682
693
|
# [RFC5530[https://www.rfc-editor.org/rfc/rfc5530.html]]::
|
683
694
|
# Gulbrandsen, A., "IMAP Response Codes", RFC 5530, DOI 10.17487/RFC5530,
|
684
695
|
# May 2009, <https://www.rfc-editor.org/info/rfc5530>.
|
685
|
-
# [MOVE[https://
|
696
|
+
# [MOVE[https://www.rfc-editor.org/rfc/rfc6851]]::
|
686
697
|
# Gulbrandsen, A. and N. Freed, Ed., "Internet Message Access Protocol
|
687
698
|
# (\IMAP) - MOVE Extension", RFC 6851, DOI 10.17487/RFC6851, January 2013,
|
688
699
|
# <https://www.rfc-editor.org/info/rfc6851>.
|
689
|
-
# [UTF8=ACCEPT[https://
|
690
|
-
# [UTF8=ONLY[https://
|
700
|
+
# [UTF8=ACCEPT[https://www.rfc-editor.org/rfc/rfc6855]]::
|
701
|
+
# [UTF8=ONLY[https://www.rfc-editor.org/rfc/rfc6855]]::
|
691
702
|
# Resnick, P., Ed., Newman, C., Ed., and S. Shen, Ed.,
|
692
703
|
# "IMAP Support for UTF-8", RFC 6855, DOI 10.17487/RFC6855, March 2013,
|
693
704
|
# <https://www.rfc-editor.org/info/rfc6855>.
|
694
|
-
# [CONDSTORE[https://
|
695
|
-
# [QRESYNC[https://
|
705
|
+
# [CONDSTORE[https://www.rfc-editor.org/rfc/rfc7162]]::
|
706
|
+
# [QRESYNC[https://www.rfc-editor.org/rfc/rfc7162]]::
|
696
707
|
# Melnikov, A. and D. Cridland, "IMAP Extensions: Quick Flag Changes
|
697
708
|
# Resynchronization (CONDSTORE) and Quick Mailbox Resynchronization
|
698
709
|
# (QRESYNC)", RFC 7162, DOI 10.17487/RFC7162, May 2014,
|
699
710
|
# <https://www.rfc-editor.org/info/rfc7162>.
|
700
|
-
# [OBJECTID[https://
|
711
|
+
# [OBJECTID[https://www.rfc-editor.org/rfc/rfc8474]]::
|
701
712
|
# Gondwana, B., Ed., "IMAP Extension for Object Identifiers",
|
702
713
|
# RFC 8474, DOI 10.17487/RFC8474, September 2018,
|
703
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>.
|
704
725
|
#
|
705
726
|
# === IANA registries
|
706
727
|
# * {IMAP Capabilities}[http://www.iana.org/assignments/imap4-capabilities]
|
@@ -714,7 +735,7 @@ module Net
|
|
714
735
|
# * {GSSAPI/Kerberos/SASL Service Names}[https://www.iana.org/assignments/gssapi-service-names/gssapi-service-names.xhtml]:
|
715
736
|
# +imap+
|
716
737
|
# * {Character sets}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
|
717
|
-
#
|
738
|
+
# ==== For currently unsupported features:
|
718
739
|
# * {IMAP Quota Resource Types}[http://www.iana.org/assignments/imap4-capabilities#imap-capabilities-2]
|
719
740
|
# * {LIST-EXTENDED options and responses}[https://www.iana.org/assignments/imap-list-extended/imap-list-extended.xhtml]
|
720
741
|
# * {IMAP METADATA Server Entry and Mailbox Entry Registries}[https://www.iana.org/assignments/imap-metadata/imap-metadata.xhtml]
|
@@ -723,7 +744,7 @@ module Net
|
|
723
744
|
# * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
|
724
745
|
#
|
725
746
|
class IMAP < Protocol
|
726
|
-
VERSION = "0.5.
|
747
|
+
VERSION = "0.5.6"
|
727
748
|
|
728
749
|
# Aliases for supported capabilities, to be used with the #enable command.
|
729
750
|
ENABLE_ALIASES = {
|
@@ -1125,12 +1146,12 @@ module Net
|
|
1125
1146
|
# )
|
1126
1147
|
# end
|
1127
1148
|
#
|
1128
|
-
# See [ID[https://
|
1149
|
+
# See [ID[https://www.rfc-editor.org/rfc/rfc2971]] for field definitions.
|
1129
1150
|
#
|
1130
1151
|
# ==== Capabilities
|
1131
1152
|
#
|
1132
1153
|
# The server's capabilities must include +ID+
|
1133
|
-
# [RFC2971[https://
|
1154
|
+
# [RFC2971[https://www.rfc-editor.org/rfc/rfc2971]].
|
1134
1155
|
def id(client_id=nil)
|
1135
1156
|
synchronize do
|
1136
1157
|
send_command("ID", ClientID.new(client_id))
|
@@ -1218,13 +1239,21 @@ module Net
|
|
1218
1239
|
#
|
1219
1240
|
def starttls(**options)
|
1220
1241
|
@ssl_ctx_params, @ssl_ctx = build_ssl_ctx(options)
|
1221
|
-
|
1242
|
+
error = nil
|
1243
|
+
ok = send_command("STARTTLS") do |resp|
|
1222
1244
|
if resp.kind_of?(TaggedResponse) && resp.name == "OK"
|
1223
1245
|
clear_cached_capabilities
|
1224
1246
|
clear_responses
|
1225
1247
|
start_tls_session
|
1226
1248
|
end
|
1249
|
+
rescue Exception => error
|
1250
|
+
raise # note that the error backtrace is in the receiver_thread
|
1227
1251
|
end
|
1252
|
+
if error
|
1253
|
+
disconnect
|
1254
|
+
raise error
|
1255
|
+
end
|
1256
|
+
ok
|
1228
1257
|
end
|
1229
1258
|
|
1230
1259
|
# :call-seq:
|
@@ -1553,7 +1582,7 @@ module Net
|
|
1553
1582
|
# servers, then folder creation (and listing, moving, etc) can lead to
|
1554
1583
|
# errors.
|
1555
1584
|
#
|
1556
|
-
# From RFC2342[https://
|
1585
|
+
# From RFC2342[https://www.rfc-editor.org/rfc/rfc2342]:
|
1557
1586
|
# >>>
|
1558
1587
|
# <em>Although typically a server will support only a single Personal
|
1559
1588
|
# Namespace, and a single Other User's Namespace, circumstances exist
|
@@ -1582,8 +1611,8 @@ module Net
|
|
1582
1611
|
#
|
1583
1612
|
# ==== Capabilities
|
1584
1613
|
#
|
1585
|
-
# The server's capabilities must include +NAMESPACE+
|
1586
|
-
# [RFC2342[https://
|
1614
|
+
# The server's capabilities must include either +IMAP4rev2+ or +NAMESPACE+
|
1615
|
+
# [RFC2342[https://www.rfc-editor.org/rfc/rfc2342]].
|
1587
1616
|
def namespace
|
1588
1617
|
synchronize do
|
1589
1618
|
send_command("NAMESPACE")
|
@@ -1645,7 +1674,7 @@ module Net
|
|
1645
1674
|
# ==== Capabilities
|
1646
1675
|
#
|
1647
1676
|
# The server's capabilities must include +QUOTA+
|
1648
|
-
# [RFC2087[https://
|
1677
|
+
# [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]].
|
1649
1678
|
def getquotaroot(mailbox)
|
1650
1679
|
synchronize do
|
1651
1680
|
send_command("GETQUOTAROOT", mailbox)
|
@@ -1666,7 +1695,7 @@ module Net
|
|
1666
1695
|
# ==== Capabilities
|
1667
1696
|
#
|
1668
1697
|
# The server's capabilities must include +QUOTA+
|
1669
|
-
# [RFC2087[https://
|
1698
|
+
# [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]].
|
1670
1699
|
def getquota(mailbox)
|
1671
1700
|
synchronize do
|
1672
1701
|
send_command("GETQUOTA", mailbox)
|
@@ -1684,7 +1713,7 @@ module Net
|
|
1684
1713
|
# ==== Capabilities
|
1685
1714
|
#
|
1686
1715
|
# The server's capabilities must include +QUOTA+
|
1687
|
-
# [RFC2087[https://
|
1716
|
+
# [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]].
|
1688
1717
|
def setquota(mailbox, quota)
|
1689
1718
|
if quota.nil?
|
1690
1719
|
data = '()'
|
@@ -1704,7 +1733,7 @@ module Net
|
|
1704
1733
|
# ==== Capabilities
|
1705
1734
|
#
|
1706
1735
|
# The server's capabilities must include +ACL+
|
1707
|
-
# [RFC4314[https://
|
1736
|
+
# [RFC4314[https://www.rfc-editor.org/rfc/rfc4314]].
|
1708
1737
|
def setacl(mailbox, user, rights)
|
1709
1738
|
if rights.nil?
|
1710
1739
|
send_command("SETACL", mailbox, user, "")
|
@@ -1722,7 +1751,7 @@ module Net
|
|
1722
1751
|
# ==== Capabilities
|
1723
1752
|
#
|
1724
1753
|
# The server's capabilities must include +ACL+
|
1725
|
-
# [RFC4314[https://
|
1754
|
+
# [RFC4314[https://www.rfc-editor.org/rfc/rfc4314]].
|
1726
1755
|
def getacl(mailbox)
|
1727
1756
|
synchronize do
|
1728
1757
|
send_command("GETACL", mailbox)
|
@@ -1883,54 +1912,70 @@ module Net
|
|
1883
1912
|
#
|
1884
1913
|
# ==== Capabilities
|
1885
1914
|
#
|
1886
|
-
# The server's capabilities must include +UNSELECT+
|
1887
|
-
# [RFC3691[https://
|
1915
|
+
# The server's capabilities must include either +IMAP4rev2+ or +UNSELECT+
|
1916
|
+
# [RFC3691[https://www.rfc-editor.org/rfc/rfc3691]].
|
1888
1917
|
def unselect
|
1889
1918
|
send_command("UNSELECT")
|
1890
1919
|
end
|
1891
1920
|
|
1921
|
+
# call-seq:
|
1922
|
+
# expunge -> array of message sequence numbers
|
1923
|
+
# expunge -> VanishedData of UIDs
|
1924
|
+
#
|
1892
1925
|
# Sends an {EXPUNGE command [IMAP4rev1 §6.4.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.3]
|
1893
|
-
#
|
1894
|
-
# selected mailbox
|
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.
|
1895
1938
|
#
|
1896
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>.
|
1897
1947
|
def expunge
|
1898
|
-
|
1899
|
-
send_command("EXPUNGE")
|
1900
|
-
clear_responses("EXPUNGE")
|
1901
|
-
end
|
1948
|
+
expunge_internal("EXPUNGE")
|
1902
1949
|
end
|
1903
1950
|
|
1951
|
+
# call-seq:
|
1952
|
+
# uid_expunge{uid_set) -> array of message sequence numbers
|
1953
|
+
# uid_expunge{uid_set) -> VanishedData of UIDs
|
1954
|
+
#
|
1904
1955
|
# Sends a {UID EXPUNGE command [RFC4315 §2.1]}[https://www.rfc-editor.org/rfc/rfc4315#section-2.1]
|
1905
1956
|
# {[IMAP4rev2 §6.4.9]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.9]
|
1906
1957
|
# to permanently remove all messages that have both the <tt>\\Deleted</tt>
|
1907
1958
|
# flag set and a UID that is included in +uid_set+.
|
1908
1959
|
#
|
1960
|
+
# Returns the same result type as #expunge.
|
1961
|
+
#
|
1909
1962
|
# By using #uid_expunge instead of #expunge when resynchronizing with
|
1910
1963
|
# the server, the client can ensure that it does not inadvertantly
|
1911
1964
|
# remove any messages that have been marked as <tt>\\Deleted</tt> by other
|
1912
1965
|
# clients between the time that the client was last connected and
|
1913
1966
|
# the time the client resynchronizes.
|
1914
1967
|
#
|
1915
|
-
# *Note:*
|
1916
|
-
# >>>
|
1917
|
-
# Although the command takes a set of UIDs for its argument, the
|
1918
|
-
# server still returns regular EXPUNGE responses, which contain
|
1919
|
-
# a <em>sequence number</em>. These will be deleted from
|
1920
|
-
# #responses and this method returns them as an array of
|
1921
|
-
# <em>sequence number</em> integers.
|
1922
|
-
#
|
1923
1968
|
# Related: #expunge
|
1924
1969
|
#
|
1925
1970
|
# ==== Capabilities
|
1926
1971
|
#
|
1927
|
-
# The server's capabilities must include +UIDPLUS+
|
1972
|
+
# The server's capabilities must include either +IMAP4rev2+ or +UIDPLUS+
|
1928
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.
|
1929
1977
|
def uid_expunge(uid_set)
|
1930
|
-
|
1931
|
-
send_command("UID EXPUNGE", SequenceSet.new(uid_set))
|
1932
|
-
clear_responses("EXPUNGE")
|
1933
|
-
end
|
1978
|
+
expunge_internal("UID EXPUNGE", SequenceSet.new(uid_set))
|
1934
1979
|
end
|
1935
1980
|
|
1936
1981
|
# :call-seq:
|
@@ -1942,7 +1987,7 @@ module Net
|
|
1942
1987
|
# and returns either a SearchResult or an ESearchResult. SearchResult
|
1943
1988
|
# inherits from Array (for backward compatibility) but adds
|
1944
1989
|
# SearchResult#modseq when the +CONDSTORE+ capability has been enabled.
|
1945
|
-
# ESearchResult also implements to_a
|
1990
|
+
# ESearchResult also implements {#to_a}[rdoc-ref:ESearchResult#to_a], for
|
1946
1991
|
# compatibility with SearchResult.
|
1947
1992
|
#
|
1948
1993
|
# +criteria+ is one or more search keys and their arguments, which may be
|
@@ -1955,8 +2000,9 @@ module Net
|
|
1955
2000
|
# the server to return an ESearchResult instead of a SearchResult, but some
|
1956
2001
|
# servers disobey this requirement. <em>Requires an extended search
|
1957
2002
|
# capability, such as +ESEARCH+ or +IMAP4rev2+.</em>
|
1958
|
-
# See {"Argument translation"}[rdoc-ref:#search@Argument+translation]
|
1959
|
-
#
|
2003
|
+
# See {"Argument translation"}[rdoc-ref:#search@Argument+translation] and
|
2004
|
+
# {"Supported return options"}[rdoc-ref:#search@Supported+return+options],
|
2005
|
+
# below.
|
1960
2006
|
#
|
1961
2007
|
# +charset+ is the name of the {registered character
|
1962
2008
|
# set}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
|
@@ -2066,33 +2112,58 @@ module Net
|
|
2066
2112
|
# <em>*WARNING:* This is vulnerable to injection attacks when external
|
2067
2113
|
# inputs are used.</em>
|
2068
2114
|
#
|
2069
|
-
# ====
|
2115
|
+
# ==== Supported return options
|
2070
2116
|
#
|
2071
2117
|
# For full definitions of the standard return options and return data, see
|
2072
2118
|
# the relevant RFCs.
|
2073
2119
|
#
|
2074
|
-
# ===== +ESEARCH+ or +IMAP4rev2+
|
2075
|
-
#
|
2076
|
-
# The following return options require either +ESEARCH+ or +IMAP4rev2+.
|
2077
|
-
# See [{RFC4731 §3.1}[https://rfc-editor.org/rfc/rfc4731#section-3.1]] or
|
2078
|
-
# [{IMAP4rev2 §6.4.4}[https://www.rfc-editor.org/rfc/rfc9051.html#section-6.4.4]].
|
2079
|
-
#
|
2080
2120
|
# [+ALL+]
|
2081
2121
|
# Returns ESearchResult#all with a SequenceSet of all matching sequence
|
2082
2122
|
# numbers or UIDs. This is the default, when return options are empty.
|
2083
2123
|
#
|
2084
2124
|
# For compatibility with SearchResult, ESearchResult#to_a returns an
|
2085
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
|
+
#
|
2086
2131
|
# [+COUNT+]
|
2087
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
|
+
#
|
2088
2138
|
# [+MAX+]
|
2089
2139
|
# Returns ESearchResult#max with the highest matching sequence number or
|
2090
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
|
+
#
|
2091
2146
|
# [+MIN+]
|
2092
2147
|
# Returns ESearchResult#min with the lowest matching sequence number or
|
2093
2148
|
# UID.
|
2094
2149
|
#
|
2095
|
-
#
|
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
|
2096
2167
|
#
|
2097
2168
|
# ESearchResult#modseq return data does not have a corresponding return
|
2098
2169
|
# option. Instead, it is returned if the +MODSEQ+ search key is used or
|
@@ -2104,8 +2175,8 @@ module Net
|
|
2104
2175
|
#
|
2105
2176
|
# {RFC4466 §2.6}[https://www.rfc-editor.org/rfc/rfc4466.html#section-2.6]
|
2106
2177
|
# defines standard syntax for search extensions. Net::IMAP allows sending
|
2107
|
-
#
|
2108
|
-
# return values into ExtensionData. Please note that this is an
|
2178
|
+
# unsupported search return options and will parse unsupported search
|
2179
|
+
# extensions' return values into ExtensionData. Please note that this is an
|
2109
2180
|
# intentionally _unstable_ API. Future releases may return different
|
2110
2181
|
# (incompatible) objects, <em>without deprecation or warning</em>.
|
2111
2182
|
#
|
@@ -2314,6 +2385,9 @@ module Net
|
|
2314
2385
|
# result = imap.search(["SUBJECT", "hi there", "not", "new"])
|
2315
2386
|
# #=> Net::IMAP::SearchResult[1, 6, 7, 8, modseq: 5594]
|
2316
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.
|
2317
2391
|
def search(...)
|
2318
2392
|
search_internal("SEARCH", ...)
|
2319
2393
|
end
|
@@ -2331,6 +2405,16 @@ module Net
|
|
2331
2405
|
# capability has been enabled.
|
2332
2406
|
#
|
2333
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.
|
2334
2418
|
def uid_search(...)
|
2335
2419
|
search_internal("UID SEARCH", ...)
|
2336
2420
|
end
|
@@ -2341,24 +2425,19 @@ module Net
|
|
2341
2425
|
# Sends a {FETCH command [IMAP4rev1 §6.4.5]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.5]
|
2342
2426
|
# to retrieve data associated with a message in the mailbox.
|
2343
2427
|
#
|
2344
|
-
#
|
2345
|
-
#
|
2346
|
-
#
|
2347
|
-
# being interpreted as '100:*'. Beware that the +exclude_end?+
|
2348
|
-
# property of a Range object is ignored, and the contents of a
|
2349
|
-
# range are independent of the order of the range endpoints as per
|
2350
|
-
# the protocol specification, so 1...5, 5..1 and 5...1 are all
|
2351
|
-
# 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.)
|
2352
2431
|
#
|
2353
|
-
# +attr+ is a list of attributes to fetch; see
|
2354
|
-
#
|
2432
|
+
# +attr+ is a list of attributes to fetch; see FetchStruct documentation for
|
2433
|
+
# a list of supported attributes.
|
2355
2434
|
#
|
2356
2435
|
# +changedsince+ is an optional integer mod-sequence. It limits results to
|
2357
2436
|
# messages with a mod-sequence greater than +changedsince+.
|
2358
2437
|
#
|
2359
2438
|
# The return value is an array of FetchData.
|
2360
2439
|
#
|
2361
|
-
# Related: #
|
2440
|
+
# Related: #uid_fetch, FetchData
|
2362
2441
|
#
|
2363
2442
|
# ==== For example:
|
2364
2443
|
#
|
@@ -2380,37 +2459,80 @@ module Net
|
|
2380
2459
|
#
|
2381
2460
|
# ==== Capabilities
|
2382
2461
|
#
|
2383
|
-
# Many extensions define new message +attr+ names. See
|
2384
|
-
# of supported extension fields.
|
2462
|
+
# Many extensions define new message +attr+ names. See FetchStruct for a
|
2463
|
+
# list of supported extension fields.
|
2385
2464
|
#
|
2386
2465
|
# The server's capabilities must include +CONDSTORE+
|
2387
|
-
# {[RFC7162]}[https://
|
2466
|
+
# {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162] in order to use the
|
2388
2467
|
# +changedsince+ argument. Using +changedsince+ implicitly enables the
|
2389
2468
|
# +CONDSTORE+ extension.
|
2390
|
-
|
2391
|
-
|
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", ...)
|
2392
2474
|
end
|
2393
2475
|
|
2394
2476
|
# :call-seq:
|
2395
|
-
# uid_fetch(set, attr, changedsince: nil) -> array of FetchData
|
2477
|
+
# uid_fetch(set, attr, changedsince: nil, partial: nil) -> array of FetchData (or UIDFetchData)
|
2396
2478
|
#
|
2397
2479
|
# Sends a {UID FETCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
|
2398
2480
|
# to retrieve data associated with a message in the mailbox.
|
2399
2481
|
#
|
2400
|
-
#
|
2401
|
-
#
|
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.)
|
2402
2485
|
#
|
2486
|
+
# +attr+ behaves the same as with #fetch.
|
2403
2487
|
# >>>
|
2404
2488
|
# *Note:* Servers _MUST_ implicitly include the +UID+ message data item as
|
2405
2489
|
# part of any +FETCH+ response caused by a +UID+ command, regardless of
|
2406
2490
|
# whether a +UID+ was specified as a message data item to the +FETCH+.
|
2407
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
|
+
#
|
2408
2521
|
# Related: #fetch, FetchData
|
2409
2522
|
#
|
2410
2523
|
# ==== Capabilities
|
2411
|
-
#
|
2412
|
-
|
2413
|
-
|
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", ...)
|
2414
2536
|
end
|
2415
2537
|
|
2416
2538
|
# :call-seq:
|
@@ -2453,15 +2575,18 @@ module Net
|
|
2453
2575
|
# Extensions may define new data items to be used with #store.
|
2454
2576
|
#
|
2455
2577
|
# The server's capabilities must include +CONDSTORE+
|
2456
|
-
# {[RFC7162]}[https://
|
2578
|
+
# {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162] in order to use the
|
2457
2579
|
# +unchangedsince+ argument. Using +unchangedsince+ implicitly enables the
|
2458
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.
|
2459
2584
|
def store(set, attr, flags, unchangedsince: nil)
|
2460
2585
|
store_internal("STORE", set, attr, flags, unchangedsince: unchangedsince)
|
2461
2586
|
end
|
2462
2587
|
|
2463
2588
|
# :call-seq:
|
2464
|
-
# uid_store(set, attr, value, unchangedsince: nil) -> array of FetchData
|
2589
|
+
# uid_store(set, attr, value, unchangedsince: nil) -> array of FetchData (or UIDFetchData)
|
2465
2590
|
#
|
2466
2591
|
# Sends a {UID STORE command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
|
2467
2592
|
# to alter data associated with messages in the mailbox, in particular their
|
@@ -2473,7 +2598,12 @@ module Net
|
|
2473
2598
|
# Related: #store
|
2474
2599
|
#
|
2475
2600
|
# ==== Capabilities
|
2476
|
-
#
|
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.
|
2477
2607
|
def uid_store(set, attr, flags, unchangedsince: nil)
|
2478
2608
|
store_internal("UID STORE", set, attr, flags, unchangedsince: unchangedsince)
|
2479
2609
|
end
|
@@ -2492,6 +2622,9 @@ module Net
|
|
2492
2622
|
# with UIDPlusData. This will report the UIDVALIDITY of the destination
|
2493
2623
|
# mailbox, the UID set of the source messages, and the assigned UID set of
|
2494
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.
|
2495
2628
|
def copy(set, mailbox)
|
2496
2629
|
copy_internal("COPY", set, mailbox)
|
2497
2630
|
end
|
@@ -2504,7 +2637,10 @@ module Net
|
|
2504
2637
|
#
|
2505
2638
|
# ==== Capabilities
|
2506
2639
|
#
|
2507
|
-
#
|
2640
|
+
# When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] in enabled,
|
2641
|
+
# #uid_copy must be used instead of #copy.
|
2642
|
+
#
|
2643
|
+
# Otherwise, #uid_copy is updated by extensions in the same way as #copy.
|
2508
2644
|
def uid_copy(set, mailbox)
|
2509
2645
|
copy_internal("UID COPY", set, mailbox)
|
2510
2646
|
end
|
@@ -2519,8 +2655,8 @@ module Net
|
|
2519
2655
|
#
|
2520
2656
|
# ==== Capabilities
|
2521
2657
|
#
|
2522
|
-
# The server's capabilities must include +MOVE+
|
2523
|
-
# [RFC6851[https://
|
2658
|
+
# The server's capabilities must include either +IMAP4rev2+ or +MOVE+
|
2659
|
+
# [RFC6851[https://www.rfc-editor.org/rfc/rfc6851]].
|
2524
2660
|
#
|
2525
2661
|
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
|
2526
2662
|
# supported, the server's response should include a +COPYUID+ response code
|
@@ -2528,6 +2664,8 @@ module Net
|
|
2528
2664
|
# mailbox, the UID set of the source messages, and the assigned UID set of
|
2529
2665
|
# the moved messages.
|
2530
2666
|
#
|
2667
|
+
# When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled, the
|
2668
|
+
# +MOVE+ command is prohibited. Use #uid_move instead.
|
2531
2669
|
def move(set, mailbox)
|
2532
2670
|
copy_internal("MOVE", set, mailbox)
|
2533
2671
|
end
|
@@ -2543,9 +2681,13 @@ module Net
|
|
2543
2681
|
#
|
2544
2682
|
# ==== Capabilities
|
2545
2683
|
#
|
2546
|
-
#
|
2547
|
-
# [RFC6851[https://
|
2548
|
-
#
|
2684
|
+
# The server's capabilities must include either +IMAP4rev2+ or +MOVE+
|
2685
|
+
# [RFC6851[https://www.rfc-editor.org/rfc/rfc6851]].
|
2686
|
+
#
|
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.
|
2549
2691
|
def uid_move(set, mailbox)
|
2550
2692
|
copy_internal("UID MOVE", set, mailbox)
|
2551
2693
|
end
|
@@ -2571,7 +2713,7 @@ module Net
|
|
2571
2713
|
# ==== Capabilities
|
2572
2714
|
#
|
2573
2715
|
# The server's capabilities must include +SORT+
|
2574
|
-
# [RFC5256[https://
|
2716
|
+
# [RFC5256[https://www.rfc-editor.org/rfc/rfc5256]].
|
2575
2717
|
def sort(sort_keys, search_keys, charset)
|
2576
2718
|
return sort_internal("SORT", sort_keys, search_keys, charset)
|
2577
2719
|
end
|
@@ -2586,7 +2728,7 @@ module Net
|
|
2586
2728
|
# ==== Capabilities
|
2587
2729
|
#
|
2588
2730
|
# The server's capabilities must include +SORT+
|
2589
|
-
# [RFC5256[https://
|
2731
|
+
# [RFC5256[https://www.rfc-editor.org/rfc/rfc5256]].
|
2590
2732
|
def uid_sort(sort_keys, search_keys, charset)
|
2591
2733
|
return sort_internal("UID SORT", sort_keys, search_keys, charset)
|
2592
2734
|
end
|
@@ -2611,7 +2753,7 @@ module Net
|
|
2611
2753
|
# ==== Capabilities
|
2612
2754
|
#
|
2613
2755
|
# The server's capabilities must include +THREAD+
|
2614
|
-
# [RFC5256[https://
|
2756
|
+
# [RFC5256[https://www.rfc-editor.org/rfc/rfc5256]].
|
2615
2757
|
def thread(algorithm, search_keys, charset)
|
2616
2758
|
return thread_internal("THREAD", algorithm, search_keys, charset)
|
2617
2759
|
end
|
@@ -2625,7 +2767,7 @@ module Net
|
|
2625
2767
|
# ==== Capabilities
|
2626
2768
|
#
|
2627
2769
|
# The server's capabilities must include +THREAD+
|
2628
|
-
# [RFC5256[https://
|
2770
|
+
# [RFC5256[https://www.rfc-editor.org/rfc/rfc5256]].
|
2629
2771
|
def uid_thread(algorithm, search_keys, charset)
|
2630
2772
|
return thread_internal("UID THREAD", algorithm, search_keys, charset)
|
2631
2773
|
end
|
@@ -2644,8 +2786,8 @@ module Net
|
|
2644
2786
|
# ==== Capabilities
|
2645
2787
|
#
|
2646
2788
|
# The server's capabilities must include
|
2647
|
-
# +ENABLE+ [RFC5161[https://
|
2648
|
-
# or +IMAP4REV2+ [RFC9051[https://
|
2789
|
+
# +ENABLE+ [RFC5161[https://www.rfc-editor.org/rfc/rfc5161]]
|
2790
|
+
# or +IMAP4REV2+ [RFC9051[https://www.rfc-editor.org/rfc/rfc9051]].
|
2649
2791
|
#
|
2650
2792
|
# Additionally, the server capabilities must include a capability matching
|
2651
2793
|
# each enabled extension (usually the same name as the enabled extension).
|
@@ -2664,7 +2806,7 @@ module Net
|
|
2664
2806
|
# <tt>"UTF8=ACCEPT"</tt> or <tt>"IMAP4rev2"</tt>, depending on server
|
2665
2807
|
# capabilities.
|
2666
2808
|
#
|
2667
|
-
# [<tt>"UTF8=ACCEPT"</tt> [RFC6855[https://
|
2809
|
+
# [<tt>"UTF8=ACCEPT"</tt> [RFC6855[https://www.rfc-editor.org/rfc/rfc6855]]]
|
2668
2810
|
#
|
2669
2811
|
# The server's capabilities must include <tt>UTF8=ACCEPT</tt> _or_
|
2670
2812
|
# <tt>UTF8=ONLY</tt>.
|
@@ -2683,13 +2825,23 @@ module Net
|
|
2683
2825
|
# encoding, even if they generally contain UTF-8 data, if they are
|
2684
2826
|
# text at all.
|
2685
2827
|
#
|
2686
|
-
# [<tt>"UTF8=ONLY"</tt> [RFC6855[https://
|
2828
|
+
# [<tt>"UTF8=ONLY"</tt> [RFC6855[https://www.rfc-editor.org/rfc/rfc6855]]]
|
2687
2829
|
#
|
2688
2830
|
# A server that reports the <tt>UTF8=ONLY</tt> capability _requires_ that
|
2689
2831
|
# the client <tt>enable("UTF8=ACCEPT")</tt> before any mailboxes may be
|
2690
2832
|
# selected. For convenience, <tt>enable("UTF8=ONLY")</tt> is aliased to
|
2691
2833
|
# <tt>enable("UTF8=ACCEPT")</tt>.
|
2692
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
|
+
#
|
2693
2845
|
# ===== Unsupported capabilities
|
2694
2846
|
#
|
2695
2847
|
# *Note:* Some extensions that use ENABLE permit the server to send syntax
|
@@ -2745,8 +2897,8 @@ module Net
|
|
2745
2897
|
#
|
2746
2898
|
# ==== Capabilities
|
2747
2899
|
#
|
2748
|
-
# The server's capabilities must include +IDLE+
|
2749
|
-
# [RFC2177[https://
|
2900
|
+
# The server's capabilities must include either +IMAP4rev2+ or +IDLE+
|
2901
|
+
# [RFC2177[https://www.rfc-editor.org/rfc/rfc2177]].
|
2750
2902
|
def idle(timeout = nil, &response_handler)
|
2751
2903
|
raise LocalJumpError, "no block given" unless response_handler
|
2752
2904
|
|
@@ -3261,6 +3413,22 @@ module Net
|
|
3261
3413
|
end
|
3262
3414
|
end
|
3263
3415
|
|
3416
|
+
def expunge_internal(...)
|
3417
|
+
synchronize do
|
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
|
3429
|
+
end
|
3430
|
+
end
|
3431
|
+
|
3264
3432
|
RETURN_WHOLE = /\ARETURN\z/i
|
3265
3433
|
RETURN_START = /\ARETURN\b/i
|
3266
3434
|
private_constant :RETURN_WHOLE, :RETURN_START
|
@@ -3306,24 +3474,14 @@ module Net
|
|
3306
3474
|
]
|
3307
3475
|
return_opts.map {|opt|
|
3308
3476
|
case opt
|
3309
|
-
when Symbol
|
3310
|
-
when
|
3311
|
-
|
3477
|
+
when Symbol then opt.to_s
|
3478
|
+
when PartialRange::Negative then PartialRange[opt]
|
3479
|
+
when Range then SequenceSet[opt]
|
3480
|
+
else opt
|
3312
3481
|
end
|
3313
3482
|
}
|
3314
3483
|
end
|
3315
3484
|
|
3316
|
-
def partial_range_last_or_seqset(range)
|
3317
|
-
case [range.begin, range.end]
|
3318
|
-
in [Integer => first, Integer => last] if first.negative? && last.negative?
|
3319
|
-
# partial-range-last [RFC9394]
|
3320
|
-
first <= last or raise DataFormatError, "empty range: %p" % [range]
|
3321
|
-
"#{first}:#{last}"
|
3322
|
-
else
|
3323
|
-
SequenceSet[range]
|
3324
|
-
end
|
3325
|
-
end
|
3326
|
-
|
3327
3485
|
def search_internal(cmd, ...)
|
3328
3486
|
args, esearch = search_args(...)
|
3329
3487
|
synchronize do
|
@@ -3350,7 +3508,12 @@ module Net
|
|
3350
3508
|
end
|
3351
3509
|
end
|
3352
3510
|
|
3353
|
-
def fetch_internal(cmd, set, attr, mod = nil, changedsince: nil)
|
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
|
3354
3517
|
if changedsince
|
3355
3518
|
mod ||= []
|
3356
3519
|
mod << "CHANGEDSINCE" << Integer(changedsince)
|
@@ -3364,15 +3527,9 @@ module Net
|
|
3364
3527
|
}
|
3365
3528
|
end
|
3366
3529
|
|
3367
|
-
|
3368
|
-
|
3369
|
-
|
3370
|
-
send_command(cmd, SequenceSet.new(set), attr, mod)
|
3371
|
-
else
|
3372
|
-
send_command(cmd, SequenceSet.new(set), attr)
|
3373
|
-
end
|
3374
|
-
clear_responses("FETCH")
|
3375
|
-
end
|
3530
|
+
args = [cmd, set, attr]
|
3531
|
+
args << mod if mod
|
3532
|
+
send_command_returning_fetch_results(*args)
|
3376
3533
|
end
|
3377
3534
|
|
3378
3535
|
def store_internal(cmd, set, attr, flags, unchangedsince: nil)
|
@@ -3380,10 +3537,17 @@ module Net
|
|
3380
3537
|
args = [SequenceSet.new(set)]
|
3381
3538
|
args << ["UNCHANGEDSINCE", Integer(unchangedsince)] if unchangedsince
|
3382
3539
|
args << attr << flags
|
3540
|
+
send_command_returning_fetch_results(cmd, *args)
|
3541
|
+
end
|
3542
|
+
|
3543
|
+
def send_command_returning_fetch_results(...)
|
3383
3544
|
synchronize do
|
3384
3545
|
clear_responses("FETCH")
|
3385
|
-
|
3386
|
-
|
3546
|
+
clear_responses("UIDFETCH")
|
3547
|
+
send_command(...)
|
3548
|
+
fetches = clear_responses("FETCH")
|
3549
|
+
uidfetches = clear_responses("UIDFETCH")
|
3550
|
+
uidfetches.any? ? uidfetches : fetches
|
3387
3551
|
end
|
3388
3552
|
end
|
3389
3553
|
|