net-imap 0.4.17 → 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.
- checksums.yaml +4 -4
- data/Gemfile +8 -1
- data/README.md +10 -4
- data/docs/styles.css +75 -14
- data/lib/net/imap/authenticators.rb +2 -2
- data/lib/net/imap/command_data.rb +59 -46
- data/lib/net/imap/config.rb +109 -13
- data/lib/net/imap/data_encoding.rb +3 -3
- data/lib/net/imap/data_lite.rb +226 -0
- data/lib/net/imap/deprecated_client_options.rb +6 -3
- data/lib/net/imap/errors.rb +6 -0
- data/lib/net/imap/esearch_result.rb +180 -0
- data/lib/net/imap/fetch_data.rb +126 -47
- data/lib/net/imap/response_data.rb +124 -237
- data/lib/net/imap/response_parser/parser_utils.rb +5 -0
- data/lib/net/imap/response_parser.rb +183 -34
- data/lib/net/imap/sasl/anonymous_authenticator.rb +3 -3
- data/lib/net/imap/sasl/authentication_exchange.rb +52 -20
- data/lib/net/imap/sasl/authenticators.rb +8 -4
- data/lib/net/imap/sasl/client_adapter.rb +77 -26
- data/lib/net/imap/sasl/cram_md5_authenticator.rb +4 -4
- data/lib/net/imap/sasl/digest_md5_authenticator.rb +218 -56
- 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 +4 -3
- 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/protocol_adapters.rb +60 -4
- data/lib/net/imap/sasl/scram_authenticator.rb +8 -8
- data/lib/net/imap/sasl.rb +7 -4
- data/lib/net/imap/sasl_adapter.rb +0 -1
- data/lib/net/imap/search_result.rb +2 -2
- data/lib/net/imap/sequence_set.rb +211 -81
- 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 +831 -279
- data/net-imap.gemspec +1 -1
- data/rakelib/rfcs.rake +2 -0
- data/rakelib/string_prep_tables_generator.rb +2 -0
- metadata +8 -7
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+.
|
@@ -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, +
|
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://
|
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,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://
|
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://
|
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://
|
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://
|
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://
|
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://
|
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://
|
577
|
-
# 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>
|
578
593
|
#
|
579
|
-
# [CHARSET[https://
|
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://
|
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://
|
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://
|
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://
|
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://
|
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://
|
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://
|
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://
|
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://
|
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://
|
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://
|
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://
|
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://
|
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://
|
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://
|
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://
|
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://
|
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://
|
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://
|
686
|
-
# [UTF8=ONLY[https://
|
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://
|
691
|
-
# [QRESYNC[https://
|
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://
|
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
|
-
#
|
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.
|
747
|
+
VERSION = "0.5.6"
|
723
748
|
|
724
749
|
# Aliases for supported capabilities, to be used with the #enable command.
|
725
750
|
ENABLE_ALIASES = {
|
@@ -946,9 +971,6 @@ module Net
|
|
946
971
|
@sock = tcp_socket(@host, @port)
|
947
972
|
start_tls_session if ssl_ctx
|
948
973
|
start_imap_connection
|
949
|
-
|
950
|
-
# DEPRECATED: to remove in next version
|
951
|
-
@client_thread = Thread.current
|
952
974
|
end
|
953
975
|
|
954
976
|
# Returns true after the TLS negotiation has completed and the remote
|
@@ -956,11 +978,6 @@ module Net
|
|
956
978
|
# but peer verification was disabled.
|
957
979
|
def tls_verified?; @tls_verified end
|
958
980
|
|
959
|
-
def client_thread # :nodoc:
|
960
|
-
warn "Net::IMAP#client_thread is deprecated and will be removed soon."
|
961
|
-
@client_thread
|
962
|
-
end
|
963
|
-
|
964
981
|
# Disconnects from the server.
|
965
982
|
#
|
966
983
|
# Related: #logout, #logout!
|
@@ -1129,12 +1146,12 @@ module Net
|
|
1129
1146
|
# )
|
1130
1147
|
# end
|
1131
1148
|
#
|
1132
|
-
# See [ID[https://
|
1149
|
+
# See [ID[https://www.rfc-editor.org/rfc/rfc2971]] for field definitions.
|
1133
1150
|
#
|
1134
|
-
#
|
1151
|
+
# ==== Capabilities
|
1135
1152
|
#
|
1136
1153
|
# The server's capabilities must include +ID+
|
1137
|
-
# [RFC2971[https://
|
1154
|
+
# [RFC2971[https://www.rfc-editor.org/rfc/rfc2971]].
|
1138
1155
|
def id(client_id=nil)
|
1139
1156
|
synchronize do
|
1140
1157
|
send_command("ID", ClientID.new(client_id))
|
@@ -1213,7 +1230,7 @@ module Net
|
|
1213
1230
|
#
|
1214
1231
|
# Related: Net::IMAP.new, #login, #authenticate
|
1215
1232
|
#
|
1216
|
-
#
|
1233
|
+
# ==== Capability
|
1217
1234
|
# Clients should not call #starttls unless the server advertises the
|
1218
1235
|
# +STARTTLS+ capability.
|
1219
1236
|
#
|
@@ -1222,13 +1239,21 @@ module Net
|
|
1222
1239
|
#
|
1223
1240
|
def starttls(**options)
|
1224
1241
|
@ssl_ctx_params, @ssl_ctx = build_ssl_ctx(options)
|
1225
|
-
|
1242
|
+
error = nil
|
1243
|
+
ok = send_command("STARTTLS") do |resp|
|
1226
1244
|
if resp.kind_of?(TaggedResponse) && resp.name == "OK"
|
1227
1245
|
clear_cached_capabilities
|
1228
1246
|
clear_responses
|
1229
1247
|
start_tls_session
|
1230
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
|
1231
1255
|
end
|
1256
|
+
ok
|
1232
1257
|
end
|
1233
1258
|
|
1234
1259
|
# :call-seq:
|
@@ -1244,6 +1269,9 @@ module Net
|
|
1244
1269
|
# +SASL-IR+ capability, below). Defaults to the #config value for
|
1245
1270
|
# {sasl_ir}[rdoc-ref:Config#sasl_ir], which defaults to +true+.
|
1246
1271
|
#
|
1272
|
+
# The +registry+ kwarg can be used to select the mechanism implementation
|
1273
|
+
# from a custom registry. See SASL.authenticator and SASL::Authenticators.
|
1274
|
+
#
|
1247
1275
|
# All other arguments are forwarded to the registered SASL authenticator for
|
1248
1276
|
# the requested mechanism. <em>The documentation for each individual
|
1249
1277
|
# mechanism must be consulted for its specific parameters.</em>
|
@@ -1338,29 +1366,9 @@ module Net
|
|
1338
1366
|
# Previously cached #capabilities will be cleared when this method
|
1339
1367
|
# completes. If the TaggedResponse to #authenticate includes updated
|
1340
1368
|
# capabilities, they will be cached.
|
1341
|
-
def authenticate(
|
1342
|
-
|
1343
|
-
|
1344
|
-
mechanism = mechanism.to_s.tr("_", "-").upcase
|
1345
|
-
authenticator = SASL.authenticator(mechanism, *creds, **props, &callback)
|
1346
|
-
cmdargs = ["AUTHENTICATE", mechanism]
|
1347
|
-
if sasl_ir && capable?("SASL-IR") && auth_capable?(mechanism) &&
|
1348
|
-
authenticator.respond_to?(:initial_response?) &&
|
1349
|
-
authenticator.initial_response?
|
1350
|
-
response = authenticator.process(nil)
|
1351
|
-
cmdargs << (response.empty? ? "=" : [response].pack("m0"))
|
1352
|
-
end
|
1353
|
-
result = send_command_with_continuations(*cmdargs) {|data|
|
1354
|
-
challenge = data.unpack1("m")
|
1355
|
-
response = authenticator.process challenge
|
1356
|
-
[response].pack("m0")
|
1357
|
-
}
|
1358
|
-
if authenticator.respond_to?(:done?) && !authenticator.done?
|
1359
|
-
logout!
|
1360
|
-
raise SASL::AuthenticationIncomplete, result
|
1361
|
-
end
|
1362
|
-
@capabilities = capabilities_from_resp_code result
|
1363
|
-
result
|
1369
|
+
def authenticate(*args, sasl_ir: config.sasl_ir, **props, &callback)
|
1370
|
+
sasl_adapter.authenticate(*args, sasl_ir: sasl_ir, **props, &callback)
|
1371
|
+
.tap { @capabilities = capabilities_from_resp_code _1 }
|
1364
1372
|
end
|
1365
1373
|
|
1366
1374
|
# Sends a {LOGIN command [IMAP4rev1 §6.2.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.2.3]
|
@@ -1377,16 +1385,12 @@ module Net
|
|
1377
1385
|
#
|
1378
1386
|
# Related: #authenticate, #starttls
|
1379
1387
|
#
|
1380
|
-
#
|
1388
|
+
# ==== Capabilities
|
1381
1389
|
#
|
1382
1390
|
# An IMAP client MUST NOT call #login when the server advertises the
|
1383
|
-
# +LOGINDISABLED+ capability.
|
1384
|
-
#
|
1385
|
-
#
|
1386
|
-
# raise "Remote server has disabled the login command"
|
1387
|
-
# else
|
1388
|
-
# imap.login username, password
|
1389
|
-
# end
|
1391
|
+
# +LOGINDISABLED+ capability. By default, Net::IMAP will raise a
|
1392
|
+
# LoginDisabledError when that capability is present. See
|
1393
|
+
# Config#enforce_logindisabled.
|
1390
1394
|
#
|
1391
1395
|
# Server capabilities may change after #starttls, #login, and #authenticate.
|
1392
1396
|
# Cached capabilities _must_ be invalidated after this method completes.
|
@@ -1394,6 +1398,9 @@ module Net
|
|
1394
1398
|
# ResponseCode.
|
1395
1399
|
#
|
1396
1400
|
def login(user, password)
|
1401
|
+
if enforce_logindisabled? && capability?("LOGINDISABLED")
|
1402
|
+
raise LoginDisabledError
|
1403
|
+
end
|
1397
1404
|
send_command("LOGIN", user, password)
|
1398
1405
|
.tap { @capabilities = capabilities_from_resp_code _1 }
|
1399
1406
|
end
|
@@ -1419,7 +1426,7 @@ module Net
|
|
1419
1426
|
#
|
1420
1427
|
# Related: #examine
|
1421
1428
|
#
|
1422
|
-
#
|
1429
|
+
# ==== Capabilities
|
1423
1430
|
#
|
1424
1431
|
# If [UIDPLUS[https://www.rfc-editor.org/rfc/rfc4315.html]] is supported,
|
1425
1432
|
# the server may return an untagged "NO" response with a "UIDNOTSTICKY"
|
@@ -1537,7 +1544,7 @@ module Net
|
|
1537
1544
|
#
|
1538
1545
|
# Related: #lsub, MailboxList
|
1539
1546
|
#
|
1540
|
-
#
|
1547
|
+
# ==== For example:
|
1541
1548
|
#
|
1542
1549
|
# imap.create("foo/bar")
|
1543
1550
|
# imap.create("foo/baz")
|
@@ -1575,7 +1582,7 @@ module Net
|
|
1575
1582
|
# servers, then folder creation (and listing, moving, etc) can lead to
|
1576
1583
|
# errors.
|
1577
1584
|
#
|
1578
|
-
# From RFC2342[https://
|
1585
|
+
# From RFC2342[https://www.rfc-editor.org/rfc/rfc2342]:
|
1579
1586
|
# >>>
|
1580
1587
|
# <em>Although typically a server will support only a single Personal
|
1581
1588
|
# Namespace, and a single Other User's Namespace, circumstances exist
|
@@ -1588,7 +1595,7 @@ module Net
|
|
1588
1595
|
#
|
1589
1596
|
# Related: #list, Namespaces, Namespace
|
1590
1597
|
#
|
1591
|
-
#
|
1598
|
+
# ==== For example:
|
1592
1599
|
#
|
1593
1600
|
# if capable?("NAMESPACE")
|
1594
1601
|
# namespaces = imap.namespace
|
@@ -1602,10 +1609,10 @@ module Net
|
|
1602
1609
|
# end
|
1603
1610
|
# end
|
1604
1611
|
#
|
1605
|
-
#
|
1612
|
+
# ==== Capabilities
|
1606
1613
|
#
|
1607
|
-
# The server's capabilities must include +NAMESPACE+
|
1608
|
-
# [RFC2342[https://
|
1614
|
+
# The server's capabilities must include either +IMAP4rev2+ or +NAMESPACE+
|
1615
|
+
# [RFC2342[https://www.rfc-editor.org/rfc/rfc2342]].
|
1609
1616
|
def namespace
|
1610
1617
|
synchronize do
|
1611
1618
|
send_command("NAMESPACE")
|
@@ -1641,7 +1648,7 @@ module Net
|
|
1641
1648
|
#
|
1642
1649
|
# Related: #list, MailboxList
|
1643
1650
|
#
|
1644
|
-
#
|
1651
|
+
# ==== Capabilities
|
1645
1652
|
#
|
1646
1653
|
# The server's capabilities must include +XLIST+,
|
1647
1654
|
# a deprecated Gmail extension (replaced by +SPECIAL-USE+).
|
@@ -1664,10 +1671,10 @@ module Net
|
|
1664
1671
|
#
|
1665
1672
|
# Related: #getquota, #setquota, MailboxQuotaRoot, MailboxQuota
|
1666
1673
|
#
|
1667
|
-
#
|
1674
|
+
# ==== Capabilities
|
1668
1675
|
#
|
1669
1676
|
# The server's capabilities must include +QUOTA+
|
1670
|
-
# [RFC2087[https://
|
1677
|
+
# [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]].
|
1671
1678
|
def getquotaroot(mailbox)
|
1672
1679
|
synchronize do
|
1673
1680
|
send_command("GETQUOTAROOT", mailbox)
|
@@ -1685,10 +1692,10 @@ module Net
|
|
1685
1692
|
#
|
1686
1693
|
# Related: #getquotaroot, #setquota, MailboxQuota
|
1687
1694
|
#
|
1688
|
-
#
|
1695
|
+
# ==== Capabilities
|
1689
1696
|
#
|
1690
1697
|
# The server's capabilities must include +QUOTA+
|
1691
|
-
# [RFC2087[https://
|
1698
|
+
# [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]].
|
1692
1699
|
def getquota(mailbox)
|
1693
1700
|
synchronize do
|
1694
1701
|
send_command("GETQUOTA", mailbox)
|
@@ -1703,10 +1710,10 @@ module Net
|
|
1703
1710
|
#
|
1704
1711
|
# Related: #getquota, #getquotaroot
|
1705
1712
|
#
|
1706
|
-
#
|
1713
|
+
# ==== Capabilities
|
1707
1714
|
#
|
1708
1715
|
# The server's capabilities must include +QUOTA+
|
1709
|
-
# [RFC2087[https://
|
1716
|
+
# [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]].
|
1710
1717
|
def setquota(mailbox, quota)
|
1711
1718
|
if quota.nil?
|
1712
1719
|
data = '()'
|
@@ -1723,10 +1730,10 @@ module Net
|
|
1723
1730
|
#
|
1724
1731
|
# Related: #getacl
|
1725
1732
|
#
|
1726
|
-
#
|
1733
|
+
# ==== Capabilities
|
1727
1734
|
#
|
1728
1735
|
# The server's capabilities must include +ACL+
|
1729
|
-
# [RFC4314[https://
|
1736
|
+
# [RFC4314[https://www.rfc-editor.org/rfc/rfc4314]].
|
1730
1737
|
def setacl(mailbox, user, rights)
|
1731
1738
|
if rights.nil?
|
1732
1739
|
send_command("SETACL", mailbox, user, "")
|
@@ -1741,10 +1748,10 @@ module Net
|
|
1741
1748
|
#
|
1742
1749
|
# Related: #setacl, MailboxACLItem
|
1743
1750
|
#
|
1744
|
-
#
|
1751
|
+
# ==== Capabilities
|
1745
1752
|
#
|
1746
1753
|
# The server's capabilities must include +ACL+
|
1747
|
-
# [RFC4314[https://
|
1754
|
+
# [RFC4314[https://www.rfc-editor.org/rfc/rfc4314]].
|
1748
1755
|
def getacl(mailbox)
|
1749
1756
|
synchronize do
|
1750
1757
|
send_command("GETACL", mailbox)
|
@@ -1778,7 +1785,7 @@ module Net
|
|
1778
1785
|
# for +mailbox+ cannot be returned; for instance, because it
|
1779
1786
|
# does not exist.
|
1780
1787
|
#
|
1781
|
-
#
|
1788
|
+
# ==== Supported attributes
|
1782
1789
|
#
|
1783
1790
|
# +MESSAGES+:: The number of messages in the mailbox.
|
1784
1791
|
#
|
@@ -1809,12 +1816,12 @@ module Net
|
|
1809
1816
|
# Unsupported attributes may be requested. The attribute value will be
|
1810
1817
|
# either an Integer or an ExtensionData object.
|
1811
1818
|
#
|
1812
|
-
#
|
1819
|
+
# ==== For example:
|
1813
1820
|
#
|
1814
1821
|
# p imap.status("inbox", ["MESSAGES", "RECENT"])
|
1815
1822
|
# #=> {"RECENT"=>0, "MESSAGES"=>44}
|
1816
1823
|
#
|
1817
|
-
#
|
1824
|
+
# ==== Capabilities
|
1818
1825
|
#
|
1819
1826
|
# +SIZE+ requires the server's capabilities to include either +IMAP4rev2+ or
|
1820
1827
|
# <tt>STATUS=SIZE</tt>
|
@@ -1854,7 +1861,7 @@ module Net
|
|
1854
1861
|
# not exist (it is not created automatically), or if the flags,
|
1855
1862
|
# date_time, or message arguments contain errors.
|
1856
1863
|
#
|
1857
|
-
#
|
1864
|
+
# ==== Capabilities
|
1858
1865
|
#
|
1859
1866
|
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
|
1860
1867
|
# supported and the destination supports persistent UIDs, the server's
|
@@ -1903,129 +1910,492 @@ module Net
|
|
1903
1910
|
#
|
1904
1911
|
# Related: #close
|
1905
1912
|
#
|
1906
|
-
#
|
1913
|
+
# ==== Capabilities
|
1907
1914
|
#
|
1908
|
-
# The server's capabilities must include +UNSELECT+
|
1909
|
-
# [RFC3691[https://
|
1915
|
+
# The server's capabilities must include either +IMAP4rev2+ or +UNSELECT+
|
1916
|
+
# [RFC3691[https://www.rfc-editor.org/rfc/rfc3691]].
|
1910
1917
|
def unselect
|
1911
1918
|
send_command("UNSELECT")
|
1912
1919
|
end
|
1913
1920
|
|
1921
|
+
# call-seq:
|
1922
|
+
# expunge -> array of message sequence numbers
|
1923
|
+
# expunge -> VanishedData of UIDs
|
1924
|
+
#
|
1914
1925
|
# Sends an {EXPUNGE command [IMAP4rev1 §6.4.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.3]
|
1915
|
-
#
|
1916
|
-
# 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.
|
1917
1938
|
#
|
1918
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>.
|
1919
1947
|
def expunge
|
1920
|
-
|
1921
|
-
send_command("EXPUNGE")
|
1922
|
-
clear_responses("EXPUNGE")
|
1923
|
-
end
|
1948
|
+
expunge_internal("EXPUNGE")
|
1924
1949
|
end
|
1925
1950
|
|
1951
|
+
# call-seq:
|
1952
|
+
# uid_expunge{uid_set) -> array of message sequence numbers
|
1953
|
+
# uid_expunge{uid_set) -> VanishedData of UIDs
|
1954
|
+
#
|
1926
1955
|
# Sends a {UID EXPUNGE command [RFC4315 §2.1]}[https://www.rfc-editor.org/rfc/rfc4315#section-2.1]
|
1927
1956
|
# {[IMAP4rev2 §6.4.9]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.9]
|
1928
1957
|
# to permanently remove all messages that have both the <tt>\\Deleted</tt>
|
1929
1958
|
# flag set and a UID that is included in +uid_set+.
|
1930
1959
|
#
|
1960
|
+
# Returns the same result type as #expunge.
|
1961
|
+
#
|
1931
1962
|
# By using #uid_expunge instead of #expunge when resynchronizing with
|
1932
1963
|
# the server, the client can ensure that it does not inadvertantly
|
1933
1964
|
# remove any messages that have been marked as <tt>\\Deleted</tt> by other
|
1934
1965
|
# clients between the time that the client was last connected and
|
1935
1966
|
# the time the client resynchronizes.
|
1936
1967
|
#
|
1937
|
-
# *Note:*
|
1938
|
-
# >>>
|
1939
|
-
# Although the command takes a set of UIDs for its argument, the
|
1940
|
-
# server still returns regular EXPUNGE responses, which contain
|
1941
|
-
# a <em>sequence number</em>. These will be deleted from
|
1942
|
-
# #responses and this method returns them as an array of
|
1943
|
-
# <em>sequence number</em> integers.
|
1944
|
-
#
|
1945
1968
|
# Related: #expunge
|
1946
1969
|
#
|
1947
|
-
#
|
1970
|
+
# ==== Capabilities
|
1948
1971
|
#
|
1949
|
-
# The server's capabilities must include +UIDPLUS+
|
1972
|
+
# The server's capabilities must include either +IMAP4rev2+ or +UIDPLUS+
|
1950
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.
|
1951
1977
|
def uid_expunge(uid_set)
|
1952
|
-
|
1953
|
-
send_command("UID EXPUNGE", MessageSet.new(uid_set))
|
1954
|
-
clear_responses("EXPUNGE")
|
1955
|
-
end
|
1978
|
+
expunge_internal("UID EXPUNGE", SequenceSet.new(uid_set))
|
1956
1979
|
end
|
1957
1980
|
|
1958
|
-
#
|
1959
|
-
#
|
1960
|
-
#
|
1961
|
-
# string holding the entire search string, or a single-dimension array of
|
1962
|
-
# search keywords and arguments.
|
1981
|
+
# :call-seq:
|
1982
|
+
# search(criteria, charset = nil) -> result
|
1983
|
+
# search(criteria, charset: nil, return: nil) -> result
|
1963
1984
|
#
|
1964
|
-
#
|
1965
|
-
#
|
1966
|
-
#
|
1985
|
+
# Sends a {SEARCH command [IMAP4rev1 §6.4.4]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.4]
|
1986
|
+
# to search the mailbox for messages that match the given search +criteria+,
|
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.
|
1992
|
+
#
|
1993
|
+
# +criteria+ is one or more search keys and their arguments, which may be
|
1994
|
+
# provided as an array or a string.
|
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.
|
2006
|
+
#
|
2007
|
+
# +charset+ is the name of the {registered character
|
2008
|
+
# set}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
|
2009
|
+
# used by strings in the search +criteria+. When +charset+ isn't specified,
|
2010
|
+
# either <tt>"US-ASCII"</tt> or <tt>"UTF-8"</tt> is assumed, depending on
|
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+.
|
1967
2016
|
#
|
1968
2017
|
# Related: #uid_search
|
1969
2018
|
#
|
1970
|
-
#
|
2019
|
+
# ==== For example:
|
1971
2020
|
#
|
1972
|
-
#
|
2021
|
+
# imap.search(["SUBJECT", "hello", "NOT", "SEEN"])
|
2022
|
+
# #=> [1, 6, 7, 8]
|
2023
|
+
#
|
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
|
2184
|
+
#
|
2185
|
+
# For full definitions of the standard search +criteria+,
|
1973
2186
|
# see [{IMAP4rev1 §6.4.4}[https://www.rfc-editor.org/rfc/rfc3501.html#section-6.4.4]],
|
1974
2187
|
# or [{IMAP4rev2 §6.4.4}[https://www.rfc-editor.org/rfc/rfc9051.html#section-6.4.4]],
|
1975
2188
|
# in addition to documentation for
|
1976
|
-
# any
|
1977
|
-
# reported by #capabilities which may define additional search filters, e.g:
|
2189
|
+
# any #capabilities which may define additional search filters, such as
|
1978
2190
|
# +CONDSTORE+, +WITHIN+, +FILTERS+, <tt>SEARCH=FUZZY</tt>, +OBJECTID+, or
|
1979
|
-
# +SAVEDATE+.
|
2191
|
+
# +SAVEDATE+.
|
1980
2192
|
#
|
1981
|
-
#
|
1982
|
-
#
|
1983
|
-
#
|
2193
|
+
# With the exception of <em>sequence-set</em> and <em>parenthesized
|
2194
|
+
# list</em>, all search keys are composed of prefix label with zero or more
|
2195
|
+
# arguments. The number and type of arguments is specific to each search
|
2196
|
+
# key.
|
1984
2197
|
#
|
1985
|
-
#
|
1986
|
-
# <b><date></b>. The date argument has a format similar
|
1987
|
-
# to <tt>8-Aug-2002</tt>, and can be formatted using
|
1988
|
-
# Net::IMAP.format_date.
|
2198
|
+
# ===== Search keys that match all messages
|
1989
2199
|
#
|
1990
|
-
#
|
2200
|
+
# [+ALL+]
|
2201
|
+
# The default initial key. Matches every message in the mailbox.
|
1991
2202
|
#
|
1992
|
-
#
|
2203
|
+
# [+SAVEDATESUPPORTED+]
|
2204
|
+
# Matches every message in the mailbox when the mailbox supports the save
|
2205
|
+
# date attribute. Otherwise, it matches no messages.
|
1993
2206
|
#
|
1994
|
-
#
|
2207
|
+
# <em>Requires +SAVEDATE+ capability</em>.
|
2208
|
+
# {[RFC8514]}[https://www.rfc-editor.org/rfc/rfc8514.html#section-4.3]
|
1995
2209
|
#
|
1996
|
-
#
|
2210
|
+
# ===== Sequence set search keys
|
1997
2211
|
#
|
1998
|
-
#
|
2212
|
+
# [_sequence-set_]
|
2213
|
+
# Matches messages with message sequence numbers in _sequence-set_.
|
1999
2214
|
#
|
2000
|
-
#
|
2215
|
+
# _Note:_ this search key has no label.
|
2001
2216
|
#
|
2002
|
-
#
|
2003
|
-
#
|
2217
|
+
# <em>+UIDONLY+ must *not* be enabled.</em>
|
2218
|
+
# {[RFC9586]}[https://www.rfc-editor.org/rfc/rfc9586.html]
|
2004
2219
|
#
|
2005
|
-
#
|
2220
|
+
# [+UID+ _sequence-set_]
|
2221
|
+
# Matches messages with a UID in _sequence-set_.
|
2006
2222
|
#
|
2007
|
-
#
|
2223
|
+
# ===== Compound search keys
|
2008
2224
|
#
|
2009
|
-
#
|
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.
|
2010
2229
|
#
|
2011
|
-
#
|
2230
|
+
# _Note:_ this search key has no label.
|
2012
2231
|
#
|
2013
|
-
#
|
2014
|
-
#
|
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+]
|
2247
|
+
# Matches messages with or without the <tt>\\Answered</tt> flag.
|
2248
|
+
# [+DELETED+, +UNDELETED+]
|
2249
|
+
# Matches messages with or without the <tt>\\Deleted</tt> flag.
|
2250
|
+
# [+DRAFT+, +UNDRAFT+]
|
2251
|
+
# Matches messages with or without the <tt>\\Draft</tt> flag.
|
2252
|
+
# [+FLAGGED+, +UNFLAGGED+]
|
2253
|
+
# Matches messages with or without the <tt>\\Flagged</tt> flag.
|
2254
|
+
# [+SEEN+, +UNSEEN+]
|
2255
|
+
# Matches messages with or without the <tt>\\Seen</tt> flag.
|
2256
|
+
# [+KEYWORD+ _keyword_, +UNKEYWORD+ _keyword_]
|
2257
|
+
# Matches messages with or without the specified _keyword_.
|
2258
|
+
#
|
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_]
|
2282
|
+
# Matches when _substring_ is in the specified header _field_.
|
2283
|
+
#
|
2284
|
+
# ===== Body text search keys
|
2285
|
+
# [+BODY+ _string_]
|
2286
|
+
# Matches when _string_ is in the body of the message.
|
2287
|
+
# Does not match on header fields.
|
2288
|
+
#
|
2289
|
+
# The server _may_ use flexible matching, rather than simple substring
|
2290
|
+
# matches. For example, this may use stemming or match only full words.
|
2291
|
+
#
|
2292
|
+
# [+TEXT+ _string_]
|
2293
|
+
# Matches when _string_ is in the header or body of the message.
|
2294
|
+
#
|
2295
|
+
# The server _may_ use flexible matching, rather than simple substring
|
2296
|
+
# matches. For example, this may use stemming or match only full words.
|
2297
|
+
#
|
2298
|
+
# ===== Date/Time search keys
|
2299
|
+
#
|
2300
|
+
# [+SENTBEFORE+ _date_]
|
2301
|
+
# [+SENTON+ _date_]
|
2302
|
+
# [+SENTSINCE+ _date_]
|
2303
|
+
# Matches when the +Date+ header is earlier than, on, or later than _date_.
|
2304
|
+
#
|
2305
|
+
# [+BEFORE+ _date_]
|
2306
|
+
# [+ON+ _date_]
|
2307
|
+
# [+SINCE+ _date_]
|
2308
|
+
# Matches when the +INTERNALDATE+ is earlier than, on, or later than
|
2309
|
+
# _date_.
|
2310
|
+
#
|
2311
|
+
# [+OLDER+ _interval_]
|
2312
|
+
# [+YOUNGER+ _interval_]
|
2313
|
+
# Matches when the +INTERNALDATE+ is more/less than _interval_ seconds ago.
|
2314
|
+
#
|
2315
|
+
# <em>Requires +WITHIN+ capability</em>.
|
2316
|
+
# {[RFC5032]}[https://www.rfc-editor.org/rfc/rfc5032.html]
|
2317
|
+
#
|
2318
|
+
# [+SAVEDBEFORE+ _date_]
|
2319
|
+
# [+SAVEDON+ _date_]
|
2320
|
+
# [+SAVEDSINCE+ _date_]
|
2321
|
+
# Matches when the save date is earlier than, on, or later than _date_.
|
2322
|
+
#
|
2323
|
+
# <em>Requires +SAVEDATE+ capability.</em>
|
2324
|
+
# {[RFC8514]}[https://www.rfc-editor.org/rfc/rfc8514.html#section-4.3]
|
2325
|
+
#
|
2326
|
+
# ===== Other message attribute search keys
|
2327
|
+
#
|
2328
|
+
# [+SMALLER+ _bytes_]
|
2329
|
+
# [+LARGER+ _bytes_]
|
2330
|
+
# Matches when +RFC822.SIZE+ is smaller or larger than _bytes_.
|
2331
|
+
#
|
2332
|
+
# [+ANNOTATION+ _entry_ _attr_ _value_]
|
2333
|
+
# Matches messages that have annotations with entries matching _entry_,
|
2334
|
+
# attributes matching _attr_, and _value_ in the attribute's values.
|
2335
|
+
#
|
2336
|
+
# <em>Requires +ANNOTATE-EXPERIMENT-1+ capability</em>.
|
2337
|
+
# {[RFC5257]}[https://www.rfc-editor.org/rfc/rfc5257.html].
|
2338
|
+
#
|
2339
|
+
# [+FILTER+ _filter_]
|
2340
|
+
# References a _filter_ that is stored on the server and matches all
|
2341
|
+
# messages which would be matched by that filter's search criteria.
|
2342
|
+
#
|
2343
|
+
# <em>Requires +FILTERS+ capability</em>.
|
2344
|
+
# {[RFC5466]}[https://www.rfc-editor.org/rfc/rfc5466.html#section-3.1]
|
2345
|
+
#
|
2346
|
+
# [+MODSEQ+ _modseq_]
|
2347
|
+
# Matches when +MODSEQ+ is greater than or equal to _modseq_.
|
2348
|
+
#
|
2349
|
+
# <em>Requires +CONDSTORE+ capability</em>.
|
2350
|
+
# {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html#section-3.1.5].
|
2015
2351
|
#
|
2016
|
-
#
|
2352
|
+
# [+MODSEQ+ _entry_ _entry-type_ _modseq_]
|
2353
|
+
# Matches when a specific metadata _entry_ has been updated since
|
2354
|
+
# _modseq_.
|
2017
2355
|
#
|
2018
|
-
#
|
2356
|
+
# For flags, the corresponding _entry_ name is
|
2357
|
+
# <tt>"/flags/#{flag_name}"</tt>, where _flag_name_ includes the
|
2358
|
+
# <tt>\\</tt> prefix. _entry-type_ can be one of <tt>"shared"</tt>,
|
2359
|
+
# <tt>"priv"</tt> (private), or <tt>"all"</tt>.
|
2360
|
+
#
|
2361
|
+
# <em>Requires +CONDSTORE+ capability</em>.
|
2362
|
+
# {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html#section-3.1.5].
|
2363
|
+
#
|
2364
|
+
# [+EMAILID+ _objectid_]
|
2365
|
+
# [+THREADID+ _objectid_]
|
2366
|
+
# Matches when +EMAILID+/+THREADID+ is equal to _objectid_
|
2367
|
+
# (substring matches are not supported).
|
2368
|
+
#
|
2369
|
+
# <em>Requires +OBJECTID+ capability</em>.
|
2370
|
+
# {[RFC8474]}[https://www.rfc-editor.org/rfc/rfc8474.html#section-6]
|
2371
|
+
#
|
2372
|
+
# ==== Capabilities
|
2373
|
+
#
|
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]].
|
2377
|
+
#
|
2378
|
+
# When +IMAP4rev2+ is enabled, or when the server supports +IMAP4rev2+ but
|
2379
|
+
# not +IMAP4rev1+, ESearchResult is always returned instead of SearchResult.
|
2380
|
+
#
|
2381
|
+
# If CONDSTORE[https://www.rfc-editor.org/rfc/rfc7162.html] is supported
|
2019
2382
|
# and enabled for the selected mailbox, a non-empty SearchResult will
|
2020
2383
|
# include a +MODSEQ+ value.
|
2021
2384
|
# imap.select("mbox", condstore: true)
|
2022
|
-
# result = imap.search(["SUBJECT", "hi there", "not", "new")
|
2385
|
+
# result = imap.search(["SUBJECT", "hi there", "not", "new"])
|
2023
2386
|
# #=> Net::IMAP::SearchResult[1, 6, 7, 8, modseq: 5594]
|
2024
2387
|
# result.modseq # => 5594
|
2025
|
-
|
2026
|
-
|
2388
|
+
#
|
2389
|
+
# When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled,
|
2390
|
+
# the +SEARCH+ command is prohibited. Use #uid_search instead.
|
2391
|
+
def search(...)
|
2392
|
+
search_internal("SEARCH", ...)
|
2027
2393
|
end
|
2028
2394
|
|
2395
|
+
# :call-seq:
|
2396
|
+
# uid_search(criteria, charset = nil) -> result
|
2397
|
+
# uid_search(criteria, charset: nil, return: nil) -> result
|
2398
|
+
#
|
2029
2399
|
# Sends a {UID SEARCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
|
2030
2400
|
# to search the mailbox for messages that match the given searching
|
2031
2401
|
# criteria, and returns unique identifiers (<tt>UID</tt>s).
|
@@ -2034,9 +2404,19 @@ module Net
|
|
2034
2404
|
# backward compatibility) but adds SearchResult#modseq when the +CONDSTORE+
|
2035
2405
|
# capability has been enabled.
|
2036
2406
|
#
|
2037
|
-
# See #search for documentation of
|
2038
|
-
|
2039
|
-
|
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.
|
2418
|
+
def uid_search(...)
|
2419
|
+
search_internal("UID SEARCH", ...)
|
2040
2420
|
end
|
2041
2421
|
|
2042
2422
|
# :call-seq:
|
@@ -2045,26 +2425,21 @@ module Net
|
|
2045
2425
|
# Sends a {FETCH command [IMAP4rev1 §6.4.5]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.5]
|
2046
2426
|
# to retrieve data associated with a message in the mailbox.
|
2047
2427
|
#
|
2048
|
-
#
|
2049
|
-
#
|
2050
|
-
#
|
2051
|
-
# being interpreted as '100:*'. Beware that the +exclude_end?+
|
2052
|
-
# property of a Range object is ignored, and the contents of a
|
2053
|
-
# range are independent of the order of the range endpoints as per
|
2054
|
-
# the protocol specification, so 1...5, 5..1 and 5...1 are all
|
2055
|
-
# 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.)
|
2056
2431
|
#
|
2057
|
-
# +attr+ is a list of attributes to fetch; see
|
2058
|
-
#
|
2432
|
+
# +attr+ is a list of attributes to fetch; see FetchStruct documentation for
|
2433
|
+
# a list of supported attributes.
|
2059
2434
|
#
|
2060
2435
|
# +changedsince+ is an optional integer mod-sequence. It limits results to
|
2061
2436
|
# messages with a mod-sequence greater than +changedsince+.
|
2062
2437
|
#
|
2063
2438
|
# The return value is an array of FetchData.
|
2064
2439
|
#
|
2065
|
-
# Related: #
|
2440
|
+
# Related: #uid_fetch, FetchData
|
2066
2441
|
#
|
2067
|
-
#
|
2442
|
+
# ==== For example:
|
2068
2443
|
#
|
2069
2444
|
# p imap.fetch(6..8, "UID")
|
2070
2445
|
# #=> [#<Net::IMAP::FetchData seqno=6, attr={"UID"=>98}>, \\
|
@@ -2082,39 +2457,82 @@ module Net
|
|
2082
2457
|
# p data.attr["UID"]
|
2083
2458
|
# #=> 98
|
2084
2459
|
#
|
2085
|
-
#
|
2460
|
+
# ==== Capabilities
|
2086
2461
|
#
|
2087
|
-
# Many extensions define new message +attr+ names. See
|
2088
|
-
# of supported extension fields.
|
2462
|
+
# Many extensions define new message +attr+ names. See FetchStruct for a
|
2463
|
+
# list of supported extension fields.
|
2089
2464
|
#
|
2090
2465
|
# The server's capabilities must include +CONDSTORE+
|
2091
|
-
# {[RFC7162]}[https://
|
2466
|
+
# {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162] in order to use the
|
2092
2467
|
# +changedsince+ argument. Using +changedsince+ implicitly enables the
|
2093
2468
|
# +CONDSTORE+ extension.
|
2094
|
-
|
2095
|
-
|
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", ...)
|
2096
2474
|
end
|
2097
2475
|
|
2098
2476
|
# :call-seq:
|
2099
|
-
# uid_fetch(set, attr, changedsince: nil) -> array of FetchData
|
2477
|
+
# uid_fetch(set, attr, changedsince: nil, partial: nil) -> array of FetchData (or UIDFetchData)
|
2100
2478
|
#
|
2101
2479
|
# Sends a {UID FETCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
|
2102
2480
|
# to retrieve data associated with a message in the mailbox.
|
2103
2481
|
#
|
2104
|
-
#
|
2105
|
-
#
|
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.)
|
2106
2485
|
#
|
2486
|
+
# +attr+ behaves the same as with #fetch.
|
2107
2487
|
# >>>
|
2108
2488
|
# *Note:* Servers _MUST_ implicitly include the +UID+ message data item as
|
2109
2489
|
# part of any +FETCH+ response caused by a +UID+ command, regardless of
|
2110
2490
|
# whether a +UID+ was specified as a message data item to the +FETCH+.
|
2111
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
|
+
#
|
2112
2521
|
# Related: #fetch, FetchData
|
2113
2522
|
#
|
2114
|
-
#
|
2115
|
-
#
|
2116
|
-
|
2117
|
-
|
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", ...)
|
2118
2536
|
end
|
2119
2537
|
|
2120
2538
|
# :call-seq:
|
@@ -2145,27 +2563,30 @@ module Net
|
|
2145
2563
|
#
|
2146
2564
|
# Related: #uid_store
|
2147
2565
|
#
|
2148
|
-
#
|
2566
|
+
# ==== For example:
|
2149
2567
|
#
|
2150
2568
|
# p imap.store(6..8, "+FLAGS", [:Deleted])
|
2151
2569
|
# #=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>,
|
2152
2570
|
# #<Net::IMAP::FetchData seqno=7, attr={"FLAGS"=>[:Seen, :Deleted]}>,
|
2153
2571
|
# #<Net::IMAP::FetchData seqno=8, attr={"FLAGS"=>[:Seen, :Deleted]}>]
|
2154
2572
|
#
|
2155
|
-
#
|
2573
|
+
# ==== Capabilities
|
2156
2574
|
#
|
2157
2575
|
# Extensions may define new data items to be used with #store.
|
2158
2576
|
#
|
2159
2577
|
# The server's capabilities must include +CONDSTORE+
|
2160
|
-
# {[RFC7162]}[https://
|
2578
|
+
# {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162] in order to use the
|
2161
2579
|
# +unchangedsince+ argument. Using +unchangedsince+ implicitly enables the
|
2162
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.
|
2163
2584
|
def store(set, attr, flags, unchangedsince: nil)
|
2164
2585
|
store_internal("STORE", set, attr, flags, unchangedsince: unchangedsince)
|
2165
2586
|
end
|
2166
2587
|
|
2167
2588
|
# :call-seq:
|
2168
|
-
# uid_store(set, attr, value, unchangedsince: nil) -> array of FetchData
|
2589
|
+
# uid_store(set, attr, value, unchangedsince: nil) -> array of FetchData (or UIDFetchData)
|
2169
2590
|
#
|
2170
2591
|
# Sends a {UID STORE command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
|
2171
2592
|
# to alter data associated with messages in the mailbox, in particular their
|
@@ -2176,8 +2597,13 @@ module Net
|
|
2176
2597
|
#
|
2177
2598
|
# Related: #store
|
2178
2599
|
#
|
2179
|
-
#
|
2180
|
-
#
|
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.
|
2181
2607
|
def uid_store(set, attr, flags, unchangedsince: nil)
|
2182
2608
|
store_internal("UID STORE", set, attr, flags, unchangedsince: unchangedsince)
|
2183
2609
|
end
|
@@ -2189,13 +2615,16 @@ module Net
|
|
2189
2615
|
#
|
2190
2616
|
# Related: #uid_copy
|
2191
2617
|
#
|
2192
|
-
#
|
2618
|
+
# ==== Capabilities
|
2193
2619
|
#
|
2194
2620
|
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
|
2195
2621
|
# supported, the server's response should include a +COPYUID+ response code
|
2196
2622
|
# with UIDPlusData. This will report the UIDVALIDITY of the destination
|
2197
2623
|
# mailbox, the UID set of the source messages, and the assigned UID set of
|
2198
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.
|
2199
2628
|
def copy(set, mailbox)
|
2200
2629
|
copy_internal("COPY", set, mailbox)
|
2201
2630
|
end
|
@@ -2206,9 +2635,12 @@ module Net
|
|
2206
2635
|
#
|
2207
2636
|
# Similar to #copy, but +set+ contains unique identifiers.
|
2208
2637
|
#
|
2209
|
-
#
|
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.
|
2210
2642
|
#
|
2211
|
-
#
|
2643
|
+
# Otherwise, #uid_copy is updated by extensions in the same way as #copy.
|
2212
2644
|
def uid_copy(set, mailbox)
|
2213
2645
|
copy_internal("UID COPY", set, mailbox)
|
2214
2646
|
end
|
@@ -2221,10 +2653,10 @@ module Net
|
|
2221
2653
|
#
|
2222
2654
|
# Related: #uid_move
|
2223
2655
|
#
|
2224
|
-
#
|
2656
|
+
# ==== Capabilities
|
2225
2657
|
#
|
2226
|
-
# The server's capabilities must include +MOVE+
|
2227
|
-
# [RFC6851[https://
|
2658
|
+
# The server's capabilities must include either +IMAP4rev2+ or +MOVE+
|
2659
|
+
# [RFC6851[https://www.rfc-editor.org/rfc/rfc6851]].
|
2228
2660
|
#
|
2229
2661
|
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
|
2230
2662
|
# supported, the server's response should include a +COPYUID+ response code
|
@@ -2232,6 +2664,8 @@ module Net
|
|
2232
2664
|
# mailbox, the UID set of the source messages, and the assigned UID set of
|
2233
2665
|
# the moved messages.
|
2234
2666
|
#
|
2667
|
+
# When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled, the
|
2668
|
+
# +MOVE+ command is prohibited. Use #uid_move instead.
|
2235
2669
|
def move(set, mailbox)
|
2236
2670
|
copy_internal("MOVE", set, mailbox)
|
2237
2671
|
end
|
@@ -2245,11 +2679,15 @@ module Net
|
|
2245
2679
|
#
|
2246
2680
|
# Related: #move
|
2247
2681
|
#
|
2248
|
-
#
|
2682
|
+
# ==== Capabilities
|
2683
|
+
#
|
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.
|
2249
2689
|
#
|
2250
|
-
#
|
2251
|
-
# [RFC6851[https://tools.ietf.org/html/rfc6851]]. +UIDPLUS+ also affects
|
2252
|
-
# #uid_move the same way it affects #move.
|
2690
|
+
# Otherwise, #uid_move is updated by extensions in the same way as #move.
|
2253
2691
|
def uid_move(set, mailbox)
|
2254
2692
|
copy_internal("UID MOVE", set, mailbox)
|
2255
2693
|
end
|
@@ -2265,17 +2703,17 @@ module Net
|
|
2265
2703
|
#
|
2266
2704
|
# Related: #uid_sort, #search, #uid_search, #thread, #uid_thread
|
2267
2705
|
#
|
2268
|
-
#
|
2706
|
+
# ==== For example:
|
2269
2707
|
#
|
2270
2708
|
# p imap.sort(["FROM"], ["ALL"], "US-ASCII")
|
2271
2709
|
# #=> [1, 2, 3, 5, 6, 7, 8, 4, 9]
|
2272
2710
|
# p imap.sort(["DATE"], ["SUBJECT", "hello"], "US-ASCII")
|
2273
2711
|
# #=> [6, 7, 8, 1]
|
2274
2712
|
#
|
2275
|
-
#
|
2713
|
+
# ==== Capabilities
|
2276
2714
|
#
|
2277
2715
|
# The server's capabilities must include +SORT+
|
2278
|
-
# [RFC5256[https://
|
2716
|
+
# [RFC5256[https://www.rfc-editor.org/rfc/rfc5256]].
|
2279
2717
|
def sort(sort_keys, search_keys, charset)
|
2280
2718
|
return sort_internal("SORT", sort_keys, search_keys, charset)
|
2281
2719
|
end
|
@@ -2287,10 +2725,10 @@ module Net
|
|
2287
2725
|
#
|
2288
2726
|
# Related: #sort, #search, #uid_search, #thread, #uid_thread
|
2289
2727
|
#
|
2290
|
-
#
|
2728
|
+
# ==== Capabilities
|
2291
2729
|
#
|
2292
2730
|
# The server's capabilities must include +SORT+
|
2293
|
-
# [RFC5256[https://
|
2731
|
+
# [RFC5256[https://www.rfc-editor.org/rfc/rfc5256]].
|
2294
2732
|
def uid_sort(sort_keys, search_keys, charset)
|
2295
2733
|
return sort_internal("UID SORT", sort_keys, search_keys, charset)
|
2296
2734
|
end
|
@@ -2312,10 +2750,10 @@ module Net
|
|
2312
2750
|
#
|
2313
2751
|
# Related: #uid_thread, #search, #uid_search, #sort, #uid_sort
|
2314
2752
|
#
|
2315
|
-
#
|
2753
|
+
# ==== Capabilities
|
2316
2754
|
#
|
2317
2755
|
# The server's capabilities must include +THREAD+
|
2318
|
-
# [RFC5256[https://
|
2756
|
+
# [RFC5256[https://www.rfc-editor.org/rfc/rfc5256]].
|
2319
2757
|
def thread(algorithm, search_keys, charset)
|
2320
2758
|
return thread_internal("THREAD", algorithm, search_keys, charset)
|
2321
2759
|
end
|
@@ -2326,10 +2764,10 @@ module Net
|
|
2326
2764
|
#
|
2327
2765
|
# Related: #thread, #search, #uid_search, #sort, #uid_sort
|
2328
2766
|
#
|
2329
|
-
#
|
2767
|
+
# ==== Capabilities
|
2330
2768
|
#
|
2331
2769
|
# The server's capabilities must include +THREAD+
|
2332
|
-
# [RFC5256[https://
|
2770
|
+
# [RFC5256[https://www.rfc-editor.org/rfc/rfc5256]].
|
2333
2771
|
def uid_thread(algorithm, search_keys, charset)
|
2334
2772
|
return thread_internal("UID THREAD", algorithm, search_keys, charset)
|
2335
2773
|
end
|
@@ -2345,11 +2783,11 @@ module Net
|
|
2345
2783
|
#
|
2346
2784
|
# Related: #capable?, #capabilities, #capability
|
2347
2785
|
#
|
2348
|
-
#
|
2786
|
+
# ==== Capabilities
|
2349
2787
|
#
|
2350
2788
|
# The server's capabilities must include
|
2351
|
-
# +ENABLE+ [RFC5161[https://
|
2352
|
-
# 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]].
|
2353
2791
|
#
|
2354
2792
|
# Additionally, the server capabilities must include a capability matching
|
2355
2793
|
# each enabled extension (usually the same name as the enabled extension).
|
@@ -2368,7 +2806,7 @@ module Net
|
|
2368
2806
|
# <tt>"UTF8=ACCEPT"</tt> or <tt>"IMAP4rev2"</tt>, depending on server
|
2369
2807
|
# capabilities.
|
2370
2808
|
#
|
2371
|
-
# [<tt>"UTF8=ACCEPT"</tt> [RFC6855[https://
|
2809
|
+
# [<tt>"UTF8=ACCEPT"</tt> [RFC6855[https://www.rfc-editor.org/rfc/rfc6855]]]
|
2372
2810
|
#
|
2373
2811
|
# The server's capabilities must include <tt>UTF8=ACCEPT</tt> _or_
|
2374
2812
|
# <tt>UTF8=ONLY</tt>.
|
@@ -2387,13 +2825,23 @@ module Net
|
|
2387
2825
|
# encoding, even if they generally contain UTF-8 data, if they are
|
2388
2826
|
# text at all.
|
2389
2827
|
#
|
2390
|
-
# [<tt>"UTF8=ONLY"</tt> [RFC6855[https://
|
2828
|
+
# [<tt>"UTF8=ONLY"</tt> [RFC6855[https://www.rfc-editor.org/rfc/rfc6855]]]
|
2391
2829
|
#
|
2392
2830
|
# A server that reports the <tt>UTF8=ONLY</tt> capability _requires_ that
|
2393
2831
|
# the client <tt>enable("UTF8=ACCEPT")</tt> before any mailboxes may be
|
2394
2832
|
# selected. For convenience, <tt>enable("UTF8=ONLY")</tt> is aliased to
|
2395
2833
|
# <tt>enable("UTF8=ACCEPT")</tt>.
|
2396
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
|
+
#
|
2397
2845
|
# ===== Unsupported capabilities
|
2398
2846
|
#
|
2399
2847
|
# *Note:* Some extensions that use ENABLE permit the server to send syntax
|
@@ -2447,10 +2895,10 @@ module Net
|
|
2447
2895
|
#
|
2448
2896
|
# Related: #idle_done, #noop, #check
|
2449
2897
|
#
|
2450
|
-
#
|
2898
|
+
# ==== Capabilities
|
2451
2899
|
#
|
2452
|
-
# The server's capabilities must include +IDLE+
|
2453
|
-
# [RFC2177[https://
|
2900
|
+
# The server's capabilities must include either +IMAP4rev2+ or +IDLE+
|
2901
|
+
# [RFC2177[https://www.rfc-editor.org/rfc/rfc2177]].
|
2454
2902
|
def idle(timeout = nil, &response_handler)
|
2455
2903
|
raise LocalJumpError, "no block given" unless response_handler
|
2456
2904
|
|
@@ -2564,7 +3012,7 @@ module Net
|
|
2564
3012
|
#
|
2565
3013
|
# Related: #extract_responses, #clear_responses, #response_handlers, #greeting
|
2566
3014
|
#
|
2567
|
-
#
|
3015
|
+
# ==== Thread safety
|
2568
3016
|
# >>>
|
2569
3017
|
# *Note:* Access to the responses hash is synchronized for thread-safety.
|
2570
3018
|
# The receiver thread and response_handlers cannot process new responses
|
@@ -2578,7 +3026,7 @@ module Net
|
|
2578
3026
|
# thread, but will not modify any responses after adding them to the
|
2579
3027
|
# responses hash.
|
2580
3028
|
#
|
2581
|
-
#
|
3029
|
+
# ==== Clearing responses
|
2582
3030
|
#
|
2583
3031
|
# Previously unhandled responses are automatically cleared before entering a
|
2584
3032
|
# mailbox with #select or #examine. Long-lived connections can receive many
|
@@ -2587,7 +3035,7 @@ module Net
|
|
2587
3035
|
# the block, or remove responses with #extract_responses, #clear_responses,
|
2588
3036
|
# or #add_response_handler.
|
2589
3037
|
#
|
2590
|
-
#
|
3038
|
+
# ==== Missing responses
|
2591
3039
|
#
|
2592
3040
|
# Only non-+nil+ data is stored. Many important response codes have no data
|
2593
3041
|
# of their own, but are used as "tags" on the ResponseText object they are
|
@@ -2608,7 +3056,7 @@ module Net
|
|
2608
3056
|
when :raise
|
2609
3057
|
raise ArgumentError, RESPONSES_DEPRECATION_MSG
|
2610
3058
|
when :warn
|
2611
|
-
warn(RESPONSES_DEPRECATION_MSG, uplevel: 1)
|
3059
|
+
warn(RESPONSES_DEPRECATION_MSG, uplevel: 1, category: :deprecated)
|
2612
3060
|
when :frozen_dup
|
2613
3061
|
synchronize {
|
2614
3062
|
responses = @responses.transform_values(&:freeze)
|
@@ -2957,23 +3405,115 @@ module Net
|
|
2957
3405
|
end
|
2958
3406
|
end
|
2959
3407
|
|
2960
|
-
def
|
2961
|
-
if
|
2962
|
-
|
3408
|
+
def enforce_logindisabled?
|
3409
|
+
if config.enforce_logindisabled == :when_capabilities_cached
|
3410
|
+
capabilities_cached?
|
2963
3411
|
else
|
2964
|
-
|
3412
|
+
config.enforce_logindisabled
|
3413
|
+
end
|
3414
|
+
end
|
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
|
+
|
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"
|
2965
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(...)
|
2966
3487
|
synchronize do
|
2967
|
-
|
2968
|
-
|
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 ")]
|
2969
3504
|
else
|
2970
|
-
|
3505
|
+
# warn NO_SEARCH_RESPONSE
|
3506
|
+
SearchResult[]
|
2971
3507
|
end
|
2972
|
-
clear_responses("SEARCH").last || []
|
2973
3508
|
end
|
2974
3509
|
end
|
2975
3510
|
|
2976
|
-
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
|
2977
3517
|
if changedsince
|
2978
3518
|
mod ||= []
|
2979
3519
|
mod << "CHANGEDSINCE" << Integer(changedsince)
|
@@ -2987,39 +3527,36 @@ module Net
|
|
2987
3527
|
}
|
2988
3528
|
end
|
2989
3529
|
|
2990
|
-
|
2991
|
-
|
2992
|
-
|
2993
|
-
send_command(cmd, MessageSet.new(set), attr, mod)
|
2994
|
-
else
|
2995
|
-
send_command(cmd, MessageSet.new(set), attr)
|
2996
|
-
end
|
2997
|
-
clear_responses("FETCH")
|
2998
|
-
end
|
3530
|
+
args = [cmd, set, attr]
|
3531
|
+
args << mod if mod
|
3532
|
+
send_command_returning_fetch_results(*args)
|
2999
3533
|
end
|
3000
3534
|
|
3001
3535
|
def store_internal(cmd, set, attr, flags, unchangedsince: nil)
|
3002
3536
|
attr = RawData.new(attr) if attr.instance_of?(String)
|
3003
|
-
args = [
|
3537
|
+
args = [SequenceSet.new(set)]
|
3004
3538
|
args << ["UNCHANGEDSINCE", Integer(unchangedsince)] if unchangedsince
|
3005
3539
|
args << attr << flags
|
3540
|
+
send_command_returning_fetch_results(cmd, *args)
|
3541
|
+
end
|
3542
|
+
|
3543
|
+
def send_command_returning_fetch_results(...)
|
3006
3544
|
synchronize do
|
3007
3545
|
clear_responses("FETCH")
|
3008
|
-
|
3009
|
-
|
3546
|
+
clear_responses("UIDFETCH")
|
3547
|
+
send_command(...)
|
3548
|
+
fetches = clear_responses("FETCH")
|
3549
|
+
uidfetches = clear_responses("UIDFETCH")
|
3550
|
+
uidfetches.any? ? uidfetches : fetches
|
3010
3551
|
end
|
3011
3552
|
end
|
3012
3553
|
|
3013
3554
|
def copy_internal(cmd, set, mailbox)
|
3014
|
-
send_command(cmd,
|
3555
|
+
send_command(cmd, SequenceSet.new(set), mailbox)
|
3015
3556
|
end
|
3016
3557
|
|
3017
3558
|
def sort_internal(cmd, sort_keys, search_keys, charset)
|
3018
|
-
|
3019
|
-
search_keys = [RawData.new(search_keys)]
|
3020
|
-
else
|
3021
|
-
normalize_searching_criteria(search_keys)
|
3022
|
-
end
|
3559
|
+
search_keys = normalize_searching_criteria(search_keys)
|
3023
3560
|
synchronize do
|
3024
3561
|
send_command(cmd, sort_keys, charset, *search_keys)
|
3025
3562
|
clear_responses("SORT").last || []
|
@@ -3027,25 +3564,39 @@ module Net
|
|
3027
3564
|
end
|
3028
3565
|
|
3029
3566
|
def thread_internal(cmd, algorithm, search_keys, charset)
|
3030
|
-
|
3031
|
-
search_keys = [RawData.new(search_keys)]
|
3032
|
-
else
|
3033
|
-
normalize_searching_criteria(search_keys)
|
3034
|
-
end
|
3567
|
+
search_keys = normalize_searching_criteria(search_keys)
|
3035
3568
|
synchronize do
|
3036
3569
|
send_command(cmd, algorithm, charset, *search_keys)
|
3037
3570
|
clear_responses("THREAD").last || []
|
3038
3571
|
end
|
3039
3572
|
end
|
3040
3573
|
|
3041
|
-
def normalize_searching_criteria(
|
3042
|
-
|
3043
|
-
|
3044
|
-
|
3045
|
-
|
3574
|
+
def normalize_searching_criteria(criteria)
|
3575
|
+
return [RawData.new(criteria)] if criteria.is_a?(String)
|
3576
|
+
criteria.map {|i|
|
3577
|
+
if coerce_search_arg_to_seqset?(i)
|
3578
|
+
SequenceSet[i]
|
3046
3579
|
else
|
3047
3580
|
i
|
3048
3581
|
end
|
3582
|
+
}
|
3583
|
+
end
|
3584
|
+
|
3585
|
+
def coerce_search_arg_to_seqset?(obj)
|
3586
|
+
case obj
|
3587
|
+
when Set, -1, :* then true
|
3588
|
+
when Range then true
|
3589
|
+
when Array then obj.all? { coerce_search_array_arg_to_seqset? _1 }
|
3590
|
+
else obj.respond_to?(:to_sequence_set)
|
3591
|
+
end
|
3592
|
+
end
|
3593
|
+
|
3594
|
+
def coerce_search_array_arg_to_seqset?(obj)
|
3595
|
+
case obj
|
3596
|
+
when Integer then obj.positive? || obj == -1
|
3597
|
+
when String then ResponseParser::Patterns::SEQUENCE_SET_STR.match?(obj.b)
|
3598
|
+
else
|
3599
|
+
coerce_search_arg_to_seqset?(obj)
|
3049
3600
|
end
|
3050
3601
|
end
|
3051
3602
|
|
@@ -3099,6 +3650,7 @@ require_relative "imap/errors"
|
|
3099
3650
|
require_relative "imap/config"
|
3100
3651
|
require_relative "imap/command_data"
|
3101
3652
|
require_relative "imap/data_encoding"
|
3653
|
+
require_relative "imap/data_lite"
|
3102
3654
|
require_relative "imap/flags"
|
3103
3655
|
require_relative "imap/response_data"
|
3104
3656
|
require_relative "imap/response_parser"
|