net-imap 0.5.1 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of net-imap might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +7 -3
- data/docs/styles.css +65 -14
- data/lib/net/imap/command_data.rb +48 -46
- data/lib/net/imap/data_lite.rb +225 -0
- data/lib/net/imap/esearch_result.rb +180 -0
- data/lib/net/imap/response_data.rb +2 -0
- data/lib/net/imap/response_parser/parser_utils.rb +5 -0
- data/lib/net/imap/response_parser.rb +137 -2
- data/lib/net/imap/vanished_data.rb +56 -0
- data/lib/net/imap.rb +531 -226
- data/rakelib/rfcs.rake +1 -0
- metadata +8 -5
data/lib/net/imap.rb
CHANGED
@@ -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+
|
@@ -466,6 +466,10 @@ module Net
|
|
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://tools.ietf.org/html/rfc9051].
|
471
|
+
# - Updates #search, #uid_search with +return+ options and ESearchResult.
|
472
|
+
#
|
469
473
|
# ==== RFC4959: +SASL-IR+
|
470
474
|
# Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
|
471
475
|
# - Updates #authenticate with the option to send an initial response.
|
@@ -530,6 +534,11 @@ 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
|
+
#
|
533
542
|
# == References
|
534
543
|
#
|
535
544
|
# [{IMAP4rev1}[https://www.rfc-editor.org/rfc/rfc3501.html]]::
|
@@ -697,6 +706,11 @@ module Net
|
|
697
706
|
# Gondwana, B., Ed., "IMAP Extension for Object Identifiers",
|
698
707
|
# RFC 8474, DOI 10.17487/RFC8474, September 2018,
|
699
708
|
# <https://www.rfc-editor.org/info/rfc8474>.
|
709
|
+
# [PARTIAL[https://www.rfc-editor.org/info/rfc9394]]::
|
710
|
+
# Melnikov, A., Achuthan, A., Nagulakonda, V., and L. Alves,
|
711
|
+
# "IMAP PARTIAL Extension for Paged SEARCH and FETCH", RFC 9394,
|
712
|
+
# DOI 10.17487/RFC9394, June 2023,
|
713
|
+
# <https://www.rfc-editor.org/info/rfc9394>.
|
700
714
|
#
|
701
715
|
# === IANA registries
|
702
716
|
# * {IMAP Capabilities}[http://www.iana.org/assignments/imap4-capabilities]
|
@@ -719,7 +733,7 @@ module Net
|
|
719
733
|
# * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
|
720
734
|
#
|
721
735
|
class IMAP < Protocol
|
722
|
-
VERSION = "0.5.
|
736
|
+
VERSION = "0.5.4"
|
723
737
|
|
724
738
|
# Aliases for supported capabilities, to be used with the #enable command.
|
725
739
|
ENABLE_ALIASES = {
|
@@ -1123,7 +1137,7 @@ module Net
|
|
1123
1137
|
#
|
1124
1138
|
# See [ID[https://tools.ietf.org/html/rfc2971]] for field definitions.
|
1125
1139
|
#
|
1126
|
-
#
|
1140
|
+
# ==== Capabilities
|
1127
1141
|
#
|
1128
1142
|
# The server's capabilities must include +ID+
|
1129
1143
|
# [RFC2971[https://tools.ietf.org/html/rfc2971]].
|
@@ -1205,7 +1219,7 @@ module Net
|
|
1205
1219
|
#
|
1206
1220
|
# Related: Net::IMAP.new, #login, #authenticate
|
1207
1221
|
#
|
1208
|
-
#
|
1222
|
+
# ==== Capability
|
1209
1223
|
# Clients should not call #starttls unless the server advertises the
|
1210
1224
|
# +STARTTLS+ capability.
|
1211
1225
|
#
|
@@ -1352,7 +1366,7 @@ module Net
|
|
1352
1366
|
#
|
1353
1367
|
# Related: #authenticate, #starttls
|
1354
1368
|
#
|
1355
|
-
#
|
1369
|
+
# ==== Capabilities
|
1356
1370
|
#
|
1357
1371
|
# An IMAP client MUST NOT call #login when the server advertises the
|
1358
1372
|
# +LOGINDISABLED+ capability. By default, Net::IMAP will raise a
|
@@ -1393,7 +1407,7 @@ module Net
|
|
1393
1407
|
#
|
1394
1408
|
# Related: #examine
|
1395
1409
|
#
|
1396
|
-
#
|
1410
|
+
# ==== Capabilities
|
1397
1411
|
#
|
1398
1412
|
# If [UIDPLUS[https://www.rfc-editor.org/rfc/rfc4315.html]] is supported,
|
1399
1413
|
# the server may return an untagged "NO" response with a "UIDNOTSTICKY"
|
@@ -1511,7 +1525,7 @@ module Net
|
|
1511
1525
|
#
|
1512
1526
|
# Related: #lsub, MailboxList
|
1513
1527
|
#
|
1514
|
-
#
|
1528
|
+
# ==== For example:
|
1515
1529
|
#
|
1516
1530
|
# imap.create("foo/bar")
|
1517
1531
|
# imap.create("foo/baz")
|
@@ -1562,7 +1576,7 @@ module Net
|
|
1562
1576
|
#
|
1563
1577
|
# Related: #list, Namespaces, Namespace
|
1564
1578
|
#
|
1565
|
-
#
|
1579
|
+
# ==== For example:
|
1566
1580
|
#
|
1567
1581
|
# if capable?("NAMESPACE")
|
1568
1582
|
# namespaces = imap.namespace
|
@@ -1576,7 +1590,7 @@ module Net
|
|
1576
1590
|
# end
|
1577
1591
|
# end
|
1578
1592
|
#
|
1579
|
-
#
|
1593
|
+
# ==== Capabilities
|
1580
1594
|
#
|
1581
1595
|
# The server's capabilities must include +NAMESPACE+
|
1582
1596
|
# [RFC2342[https://tools.ietf.org/html/rfc2342]].
|
@@ -1615,7 +1629,7 @@ module Net
|
|
1615
1629
|
#
|
1616
1630
|
# Related: #list, MailboxList
|
1617
1631
|
#
|
1618
|
-
#
|
1632
|
+
# ==== Capabilities
|
1619
1633
|
#
|
1620
1634
|
# The server's capabilities must include +XLIST+,
|
1621
1635
|
# a deprecated Gmail extension (replaced by +SPECIAL-USE+).
|
@@ -1638,7 +1652,7 @@ module Net
|
|
1638
1652
|
#
|
1639
1653
|
# Related: #getquota, #setquota, MailboxQuotaRoot, MailboxQuota
|
1640
1654
|
#
|
1641
|
-
#
|
1655
|
+
# ==== Capabilities
|
1642
1656
|
#
|
1643
1657
|
# The server's capabilities must include +QUOTA+
|
1644
1658
|
# [RFC2087[https://tools.ietf.org/html/rfc2087]].
|
@@ -1659,7 +1673,7 @@ module Net
|
|
1659
1673
|
#
|
1660
1674
|
# Related: #getquotaroot, #setquota, MailboxQuota
|
1661
1675
|
#
|
1662
|
-
#
|
1676
|
+
# ==== Capabilities
|
1663
1677
|
#
|
1664
1678
|
# The server's capabilities must include +QUOTA+
|
1665
1679
|
# [RFC2087[https://tools.ietf.org/html/rfc2087]].
|
@@ -1677,7 +1691,7 @@ module Net
|
|
1677
1691
|
#
|
1678
1692
|
# Related: #getquota, #getquotaroot
|
1679
1693
|
#
|
1680
|
-
#
|
1694
|
+
# ==== Capabilities
|
1681
1695
|
#
|
1682
1696
|
# The server's capabilities must include +QUOTA+
|
1683
1697
|
# [RFC2087[https://tools.ietf.org/html/rfc2087]].
|
@@ -1697,7 +1711,7 @@ module Net
|
|
1697
1711
|
#
|
1698
1712
|
# Related: #getacl
|
1699
1713
|
#
|
1700
|
-
#
|
1714
|
+
# ==== Capabilities
|
1701
1715
|
#
|
1702
1716
|
# The server's capabilities must include +ACL+
|
1703
1717
|
# [RFC4314[https://tools.ietf.org/html/rfc4314]].
|
@@ -1715,7 +1729,7 @@ module Net
|
|
1715
1729
|
#
|
1716
1730
|
# Related: #setacl, MailboxACLItem
|
1717
1731
|
#
|
1718
|
-
#
|
1732
|
+
# ==== Capabilities
|
1719
1733
|
#
|
1720
1734
|
# The server's capabilities must include +ACL+
|
1721
1735
|
# [RFC4314[https://tools.ietf.org/html/rfc4314]].
|
@@ -1752,7 +1766,7 @@ module Net
|
|
1752
1766
|
# for +mailbox+ cannot be returned; for instance, because it
|
1753
1767
|
# does not exist.
|
1754
1768
|
#
|
1755
|
-
#
|
1769
|
+
# ==== Supported attributes
|
1756
1770
|
#
|
1757
1771
|
# +MESSAGES+:: The number of messages in the mailbox.
|
1758
1772
|
#
|
@@ -1783,12 +1797,12 @@ module Net
|
|
1783
1797
|
# Unsupported attributes may be requested. The attribute value will be
|
1784
1798
|
# either an Integer or an ExtensionData object.
|
1785
1799
|
#
|
1786
|
-
#
|
1800
|
+
# ==== For example:
|
1787
1801
|
#
|
1788
1802
|
# p imap.status("inbox", ["MESSAGES", "RECENT"])
|
1789
1803
|
# #=> {"RECENT"=>0, "MESSAGES"=>44}
|
1790
1804
|
#
|
1791
|
-
#
|
1805
|
+
# ==== Capabilities
|
1792
1806
|
#
|
1793
1807
|
# +SIZE+ requires the server's capabilities to include either +IMAP4rev2+ or
|
1794
1808
|
# <tt>STATUS=SIZE</tt>
|
@@ -1828,7 +1842,7 @@ module Net
|
|
1828
1842
|
# not exist (it is not created automatically), or if the flags,
|
1829
1843
|
# date_time, or message arguments contain errors.
|
1830
1844
|
#
|
1831
|
-
#
|
1845
|
+
# ==== Capabilities
|
1832
1846
|
#
|
1833
1847
|
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
|
1834
1848
|
# supported and the destination supports persistent UIDs, the server's
|
@@ -1877,7 +1891,7 @@ module Net
|
|
1877
1891
|
#
|
1878
1892
|
# Related: #close
|
1879
1893
|
#
|
1880
|
-
#
|
1894
|
+
# ==== Capabilities
|
1881
1895
|
#
|
1882
1896
|
# The server's capabilities must include +UNSELECT+
|
1883
1897
|
# [RFC3691[https://tools.ietf.org/html/rfc3691]].
|
@@ -1885,110 +1899,269 @@ module Net
|
|
1885
1899
|
send_command("UNSELECT")
|
1886
1900
|
end
|
1887
1901
|
|
1902
|
+
# call-seq:
|
1903
|
+
# expunge -> array of message sequence numbers
|
1904
|
+
# expunge -> VanishedData of UIDs
|
1905
|
+
#
|
1888
1906
|
# Sends an {EXPUNGE command [IMAP4rev1 §6.4.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.3]
|
1889
|
-
#
|
1890
|
-
# selected mailbox
|
1907
|
+
# to permanently remove all messages with the +\Deleted+ flag from the
|
1908
|
+
# currently selected mailbox.
|
1909
|
+
#
|
1910
|
+
# Returns either an array of expunged message <em>sequence numbers</em> or
|
1911
|
+
# (when the appropriate capability is enabled) VanishedData of expunged
|
1912
|
+
# UIDs. Previously unhandled +EXPUNGE+ or +VANISHED+ responses are merged
|
1913
|
+
# with the direct response to this command. <tt>VANISHED (EARLIER)</tt>
|
1914
|
+
# responses will _not_ be merged.
|
1915
|
+
#
|
1916
|
+
# When no messages have been expunged, an empty array is returned,
|
1917
|
+
# regardless of which extensions are enabled. In a future release, an empty
|
1918
|
+
# VanishedData may be returned, based on the currently enabled extensions.
|
1891
1919
|
#
|
1892
1920
|
# Related: #uid_expunge
|
1921
|
+
#
|
1922
|
+
# ==== Capabilities
|
1923
|
+
#
|
1924
|
+
# When either QRESYNC[https://tools.ietf.org/html/rfc7162] or
|
1925
|
+
# UIDONLY[https://tools.ietf.org/html/rfc9586] are enabled, #expunge
|
1926
|
+
# returns VanishedData, which contains UIDs---<em>not message sequence
|
1927
|
+
# numbers</em>.
|
1893
1928
|
def expunge
|
1894
|
-
|
1895
|
-
send_command("EXPUNGE")
|
1896
|
-
clear_responses("EXPUNGE")
|
1897
|
-
end
|
1929
|
+
expunge_internal("EXPUNGE")
|
1898
1930
|
end
|
1899
1931
|
|
1932
|
+
# call-seq:
|
1933
|
+
# uid_expunge{uid_set) -> array of message sequence numbers
|
1934
|
+
# uid_expunge{uid_set) -> VanishedData of UIDs
|
1935
|
+
#
|
1900
1936
|
# Sends a {UID EXPUNGE command [RFC4315 §2.1]}[https://www.rfc-editor.org/rfc/rfc4315#section-2.1]
|
1901
1937
|
# {[IMAP4rev2 §6.4.9]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.9]
|
1902
1938
|
# to permanently remove all messages that have both the <tt>\\Deleted</tt>
|
1903
1939
|
# flag set and a UID that is included in +uid_set+.
|
1904
1940
|
#
|
1941
|
+
# Returns the same result type as #expunge.
|
1942
|
+
#
|
1905
1943
|
# By using #uid_expunge instead of #expunge when resynchronizing with
|
1906
1944
|
# the server, the client can ensure that it does not inadvertantly
|
1907
1945
|
# remove any messages that have been marked as <tt>\\Deleted</tt> by other
|
1908
1946
|
# clients between the time that the client was last connected and
|
1909
1947
|
# the time the client resynchronizes.
|
1910
1948
|
#
|
1911
|
-
# *Note:*
|
1912
|
-
# >>>
|
1913
|
-
# Although the command takes a set of UIDs for its argument, the
|
1914
|
-
# server still returns regular EXPUNGE responses, which contain
|
1915
|
-
# a <em>sequence number</em>. These will be deleted from
|
1916
|
-
# #responses and this method returns them as an array of
|
1917
|
-
# <em>sequence number</em> integers.
|
1918
|
-
#
|
1919
1949
|
# Related: #expunge
|
1920
1950
|
#
|
1921
|
-
#
|
1951
|
+
# ==== Capabilities
|
1922
1952
|
#
|
1923
|
-
# The server's capabilities must include +UIDPLUS+
|
1953
|
+
# The server's capabilities must include either +IMAP4rev2+ or +UIDPLUS+
|
1924
1954
|
# [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]].
|
1955
|
+
#
|
1956
|
+
# Otherwise, #uid_expunge is updated by extensions in the same way as
|
1957
|
+
# #expunge.
|
1925
1958
|
def uid_expunge(uid_set)
|
1926
|
-
|
1927
|
-
send_command("UID EXPUNGE", SequenceSet.new(uid_set))
|
1928
|
-
clear_responses("EXPUNGE")
|
1929
|
-
end
|
1959
|
+
expunge_internal("UID EXPUNGE", SequenceSet.new(uid_set))
|
1930
1960
|
end
|
1931
1961
|
|
1932
1962
|
# :call-seq:
|
1933
1963
|
# search(criteria, charset = nil) -> result
|
1964
|
+
# search(criteria, charset: nil, return: nil) -> result
|
1934
1965
|
#
|
1935
1966
|
# Sends a {SEARCH command [IMAP4rev1 §6.4.4]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.4]
|
1936
1967
|
# to search the mailbox for messages that match the given search +criteria+,
|
1937
|
-
# and returns a SearchResult. SearchResult
|
1938
|
-
# backward compatibility) but adds
|
1939
|
-
# capability has been enabled.
|
1968
|
+
# and returns either a SearchResult or an ESearchResult. SearchResult
|
1969
|
+
# inherits from Array (for backward compatibility) but adds
|
1970
|
+
# SearchResult#modseq when the +CONDSTORE+ capability has been enabled.
|
1971
|
+
# ESearchResult also implements {#to_a}[rdoc-ref:ESearchResult#to_a], for
|
1972
|
+
# compatibility with SearchResult.
|
1940
1973
|
#
|
1941
1974
|
# +criteria+ is one or more search keys and their arguments, which may be
|
1942
1975
|
# provided as an array or a string.
|
1943
|
-
# See {"
|
1944
|
-
#
|
1945
|
-
#
|
1946
|
-
#
|
1947
|
-
#
|
1948
|
-
#
|
1949
|
-
#
|
1950
|
-
#
|
1951
|
-
#
|
1952
|
-
#
|
1953
|
-
#
|
1954
|
-
# +Array+ of these same types.
|
1955
|
-
# * Any +String+ is sent verbatim when it is a valid \IMAP atom,
|
1956
|
-
# and encoded as an \IMAP quoted or literal string otherwise.
|
1957
|
-
# * Any other nested +Array+ is encoded as a parenthesized list, to group
|
1958
|
-
# multiple search keys (e.g., for use with +OR+ and +NOT+).
|
1959
|
-
# * Any other +Integer+ (besides <tt>-1</tt>) will be sent as +#to_s+.
|
1960
|
-
# * +Date+ objects will be encoded as an \IMAP date (see ::encode_date).
|
1961
|
-
#
|
1962
|
-
# * When +criteria+ is a string, it will be sent directly to the server
|
1963
|
-
# <em>without any validation or encoding</em>. *WARNING:* This is
|
1964
|
-
# vulnerable to injection attacks when external inputs are used.
|
1976
|
+
# See {"Argument translation"}[rdoc-ref:#search@Argument+translation]
|
1977
|
+
# and {"Search criteria"}[rdoc-ref:#search@Search+criteria], below.
|
1978
|
+
#
|
1979
|
+
# +return+ options control what kind of information is returned about
|
1980
|
+
# messages matching the search +criteria+. Specifying +return+ should force
|
1981
|
+
# the server to return an ESearchResult instead of a SearchResult, but some
|
1982
|
+
# servers disobey this requirement. <em>Requires an extended search
|
1983
|
+
# capability, such as +ESEARCH+ or +IMAP4rev2+.</em>
|
1984
|
+
# See {"Argument translation"}[rdoc-ref:#search@Argument+translation] and
|
1985
|
+
# {"Supported return options"}[rdoc-ref:#search@Supported+return+options],
|
1986
|
+
# below.
|
1965
1987
|
#
|
1966
1988
|
# +charset+ is the name of the {registered character
|
1967
1989
|
# set}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
|
1968
1990
|
# used by strings in the search +criteria+. When +charset+ isn't specified,
|
1969
1991
|
# either <tt>"US-ASCII"</tt> or <tt>"UTF-8"</tt> is assumed, depending on
|
1970
|
-
# the server's capabilities.
|
1971
|
-
#
|
1992
|
+
# the server's capabilities.
|
1993
|
+
#
|
1994
|
+
# _NOTE:_ Return options and charset may be sent as part of +criteria+. Do
|
1995
|
+
# not use the +return+ or +charset+ arguments when either return options or
|
1996
|
+
# charset are embedded in +criteria+.
|
1972
1997
|
#
|
1973
1998
|
# Related: #uid_search
|
1974
1999
|
#
|
1975
|
-
#
|
2000
|
+
# ==== For example:
|
1976
2001
|
#
|
1977
|
-
#
|
2002
|
+
# imap.search(["SUBJECT", "hello", "NOT", "SEEN"])
|
1978
2003
|
# #=> [1, 6, 7, 8]
|
1979
2004
|
#
|
1980
|
-
# The following
|
1981
|
-
#
|
1982
|
-
#
|
1983
|
-
#
|
1984
|
-
#
|
1985
|
-
#
|
1986
|
-
#
|
1987
|
-
#
|
1988
|
-
#
|
1989
|
-
#
|
1990
|
-
#
|
1991
|
-
#
|
2005
|
+
# The following assumes the server supports +ESEARCH+ and +CONDSTORE+:
|
2006
|
+
#
|
2007
|
+
# result = imap.uid_search(["UID", 12345.., "MODSEQ", 620_162_338],
|
2008
|
+
# return: %w(all count min max))
|
2009
|
+
# # => #<data Net::IMAP::ESearchResult tag="RUBY0123", uid=true,
|
2010
|
+
# # data=[["ALL", Net::IMAP::SequenceSet["12346:12349,22222:22230"]],
|
2011
|
+
# # ["COUNT", 13], ["MIN", 12346], ["MAX", 22230],
|
2012
|
+
# # ["MODSEQ", 917162488]]>
|
2013
|
+
# result.to_a # => [12346, 12347, 12348, 12349, 22222, 22223, 22224,
|
2014
|
+
# # 22225, 22226, 22227, 22228, 22229, 22230]
|
2015
|
+
# result.uid? # => true
|
2016
|
+
# result.count # => 13
|
2017
|
+
# result.min # => 12346
|
2018
|
+
# result.max # => 22230
|
2019
|
+
# result.modseq # => 917162488
|
2020
|
+
#
|
2021
|
+
# Using +return+ options to limit the result to only min, max, and count:
|
2022
|
+
#
|
2023
|
+
# result = imap.uid_search(["UID", 12345..,], return: %w(count min max))
|
2024
|
+
# # => #<data Net::IMAP::ESearchResult tag="RUBY0124", uid=true,
|
2025
|
+
# # data=[["COUNT", 13], ["MIN", 12346], ["MAX", 22230]]>
|
2026
|
+
# result.to_a # => []
|
2027
|
+
# result.count # => 13
|
2028
|
+
# result.min # => 12346
|
2029
|
+
# result.max # => 22230
|
2030
|
+
#
|
2031
|
+
# Return options and charset may be sent as keyword args or embedded in the
|
2032
|
+
# +criteria+ arg, but they must be in the correct order: <tt>"RETURN (...)
|
2033
|
+
# CHARSET ... criteria..."</tt>. The following searches
|
2034
|
+
# send the exact same command to the server:
|
2035
|
+
#
|
2036
|
+
# # Return options and charset as keyword arguments (preferred)
|
2037
|
+
# imap.search(%w(OR UNSEEN FLAGGED), return: %w(MIN MAX), charset: "UTF-8")
|
2038
|
+
# # Embedding return and charset in the criteria array
|
2039
|
+
# imap.search(["RETURN", %w(MIN MAX), "CHARSET", "UTF-8", *%w(OR UNSEEN FLAGGED)])
|
2040
|
+
# # Embedding return and charset in the criteria string
|
2041
|
+
# imap.search("RETURN (MIN MAX) CHARSET UTF-8 OR UNSEEN FLAGGED")
|
2042
|
+
#
|
2043
|
+
# Sending charset as the second positional argument is supported for
|
2044
|
+
# backward compatibility. Future versions may print a deprecation warning:
|
2045
|
+
# imap.search(%w(OR UNSEEN FLAGGED), "UTF-8", return: %w(MIN MAX))
|
2046
|
+
#
|
2047
|
+
# ==== Argument translation
|
2048
|
+
#
|
2049
|
+
# [+return+ options]
|
2050
|
+
# Must be an Array. Return option names may be either strings or symbols.
|
2051
|
+
# +Range+ elements which begin and end with negative integers are encoded
|
2052
|
+
# for use with +PARTIAL+--any other ranges are converted to SequenceSet.
|
2053
|
+
# Unlike +criteria+, other return option arguments are not automatically
|
2054
|
+
# converted to SequenceSet.
|
2055
|
+
#
|
2056
|
+
# [When +criteria+ is an Array]
|
2057
|
+
# When the array begins with <tt>"RETURN"</tt> (case insensitive), the
|
2058
|
+
# second array element is translated like the +return+ parameter (as
|
2059
|
+
# described above).
|
2060
|
+
#
|
2061
|
+
# Every other member is a +SEARCH+ command argument:
|
2062
|
+
# [SequenceSet]
|
2063
|
+
# Encoded as an \IMAP +sequence-set+ with SequenceSet#valid_string.
|
2064
|
+
# [Set, Range, <tt>-1</tt>, +:*+, responds to +#to_sequence_set+]
|
2065
|
+
# Converted to SequenceSet for validation and encoding.
|
2066
|
+
# [nested sequence-set +Array+]
|
2067
|
+
# When every element in a nested array is one of the above types, a
|
2068
|
+
# positive +Integer+, a sequence-set formatted +String+, or a deeply
|
2069
|
+
# nested +Array+ of these same types, the array will be converted to
|
2070
|
+
# SequenceSet for validation and encoding.
|
2071
|
+
# [Any other nested +Array+]
|
2072
|
+
# Otherwise, a nested array is encoded as a parenthesized list, to
|
2073
|
+
# combine multiple search keys (e.g., for use with +OR+ and +NOT+).
|
2074
|
+
# [+String+]
|
2075
|
+
# Sent verbatim when it is a valid \IMAP +atom+, and encoded as an \IMAP
|
2076
|
+
# +quoted+ or +literal+ string otherwise. Every standard search key
|
2077
|
+
# name is a valid \IMAP +atom+ and every standard search key string
|
2078
|
+
# argument is an +astring+ which may be encoded as +atom+, +quoted+, or
|
2079
|
+
# +literal+.
|
2080
|
+
#
|
2081
|
+
# *Note:* <tt>*</tt> is not a valid \IMAP +atom+ character. Any string
|
2082
|
+
# containing <tt>*</tt> will be encoded as a +quoted+ string, _not_ a
|
2083
|
+
# +sequence-set+.
|
2084
|
+
# [+Integer+ (except for <tt>-1</tt>)]
|
2085
|
+
# Encoded using +#to_s+.
|
2086
|
+
# [+Date+]
|
2087
|
+
# Encoded as an \IMAP date (see ::encode_date).
|
2088
|
+
#
|
2089
|
+
# [When +criteria+ is a String]
|
2090
|
+
# +criteria+ will be sent directly to the server <em>without any
|
2091
|
+
# validation or encoding</em>.
|
2092
|
+
#
|
2093
|
+
# <em>*WARNING:* This is vulnerable to injection attacks when external
|
2094
|
+
# inputs are used.</em>
|
2095
|
+
#
|
2096
|
+
# ==== Supported return options
|
2097
|
+
#
|
2098
|
+
# For full definitions of the standard return options and return data, see
|
2099
|
+
# the relevant RFCs.
|
2100
|
+
#
|
2101
|
+
# [+ALL+]
|
2102
|
+
# Returns ESearchResult#all with a SequenceSet of all matching sequence
|
2103
|
+
# numbers or UIDs. This is the default, when return options are empty.
|
2104
|
+
#
|
2105
|
+
# For compatibility with SearchResult, ESearchResult#to_a returns an
|
2106
|
+
# Array of message sequence numbers or UIDs.
|
2107
|
+
#
|
2108
|
+
# <em>Requires either the +ESEARCH+ or +IMAP4rev2+ capabability.</em>
|
2109
|
+
# {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731]
|
2110
|
+
# {[RFC9051]}[https://rfc-editor.org/rfc/rfc9051]
|
2111
|
+
#
|
2112
|
+
# [+COUNT+]
|
2113
|
+
# Returns ESearchResult#count with the number of matching messages.
|
2114
|
+
#
|
2115
|
+
# <em>Requires either the +ESEARCH+ or +IMAP4rev2+ capabability.</em>
|
2116
|
+
# {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731]
|
2117
|
+
# {[RFC9051]}[https://rfc-editor.org/rfc/rfc9051]
|
2118
|
+
#
|
2119
|
+
# [+MAX+]
|
2120
|
+
# Returns ESearchResult#max with the highest matching sequence number or
|
2121
|
+
# UID.
|
2122
|
+
#
|
2123
|
+
# <em>Requires either the +ESEARCH+ or +IMAP4rev2+ capabability.</em>
|
2124
|
+
# {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731]
|
2125
|
+
# {[RFC9051]}[https://rfc-editor.org/rfc/rfc9051]
|
2126
|
+
#
|
2127
|
+
# [+MIN+]
|
2128
|
+
# Returns ESearchResult#min with the lowest matching sequence number or
|
2129
|
+
# UID.
|
2130
|
+
#
|
2131
|
+
# <em>Requires either the +ESEARCH+ or +IMAP4rev2+ capabability.</em>
|
2132
|
+
# {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731]
|
2133
|
+
# {[RFC9051]}[https://rfc-editor.org/rfc/rfc9051]
|
2134
|
+
#
|
2135
|
+
# [+PARTIAL+ _range_]
|
2136
|
+
# Returns ESearchResult#partial with a SequenceSet of a subset of
|
2137
|
+
# matching sequence numbers or UIDs, as selected by _range_. As with
|
2138
|
+
# sequence numbers, the first result is +1+: <tt>1..500</tt> selects the
|
2139
|
+
# first 500 search results (in mailbox order), <tt>501..1000</tt> the
|
2140
|
+
# second 500, and so on. _range_ may also be negative: <tt>-500..-1</tt>
|
2141
|
+
# selects the last 500 search results.
|
2142
|
+
#
|
2143
|
+
# <em>Requires either the <tt>CONTEXT=SEARCH</tt> or +PARTIAL+ capabability.</em>
|
2144
|
+
# {[RFC5267]}[https://rfc-editor.org/rfc/rfc5267]
|
2145
|
+
# {[RFC9394]}[https://rfc-editor.org/rfc/rfc9394]
|
2146
|
+
#
|
2147
|
+
# ===== +MODSEQ+ return data
|
2148
|
+
#
|
2149
|
+
# ESearchResult#modseq return data does not have a corresponding return
|
2150
|
+
# option. Instead, it is returned if the +MODSEQ+ search key is used or
|
2151
|
+
# when the +CONDSTORE+ extension is enabled for the selected mailbox.
|
2152
|
+
# See [{RFC4731 §3.2}[https://www.rfc-editor.org/rfc/rfc4731#section-3.2]]
|
2153
|
+
# or [{RFC7162 §2.1.5}[https://www.rfc-editor.org/rfc/rfc7162#section-3.1.5]].
|
2154
|
+
#
|
2155
|
+
# ===== +RFC4466+ compatible extensions
|
2156
|
+
#
|
2157
|
+
# {RFC4466 §2.6}[https://www.rfc-editor.org/rfc/rfc4466.html#section-2.6]
|
2158
|
+
# defines standard syntax for search extensions. Net::IMAP allows sending
|
2159
|
+
# unsupported search return options and will parse unsupported search
|
2160
|
+
# extensions' return values into ExtensionData. Please note that this is an
|
2161
|
+
# intentionally _unstable_ API. Future releases may return different
|
2162
|
+
# (incompatible) objects, <em>without deprecation or warning</em>.
|
2163
|
+
#
|
2164
|
+
# ==== Search keys
|
1992
2165
|
#
|
1993
2166
|
# For full definitions of the standard search +criteria+,
|
1994
2167
|
# see [{IMAP4rev1 §6.4.4}[https://www.rfc-editor.org/rfc/rfc3501.html#section-6.4.4]],
|
@@ -2003,23 +2176,21 @@ module Net
|
|
2003
2176
|
# arguments. The number and type of arguments is specific to each search
|
2004
2177
|
# key.
|
2005
2178
|
#
|
2006
|
-
#
|
2007
|
-
# Matches every message in the mailbox.
|
2179
|
+
# ===== Search keys that match all messages
|
2008
2180
|
#
|
2009
|
-
#
|
2010
|
-
#
|
2011
|
-
# messages which match all contained search keys. Useful for +OR+, +NOT+,
|
2012
|
-
# and other search keys with _search-key_ arguments.
|
2181
|
+
# [+ALL+]
|
2182
|
+
# The default initial key. Matches every message in the mailbox.
|
2013
2183
|
#
|
2014
|
-
#
|
2184
|
+
# [+SAVEDATESUPPORTED+]
|
2185
|
+
# Matches every message in the mailbox when the mailbox supports the save
|
2186
|
+
# date attribute. Otherwise, it matches no messages.
|
2015
2187
|
#
|
2016
|
-
# +
|
2017
|
-
#
|
2188
|
+
# <em>Requires +SAVEDATE+ capability</em>.
|
2189
|
+
# {[RFC8514]}[https://www.rfc-editor.org/rfc/rfc8514.html#section-4.3]
|
2018
2190
|
#
|
2019
|
-
#
|
2020
|
-
# Matches messages which do not match _search-key_.
|
2191
|
+
# ===== Sequence set search keys
|
2021
2192
|
#
|
2022
|
-
# _sequence-set_
|
2193
|
+
# [_sequence-set_]
|
2023
2194
|
# Matches messages with message sequence numbers in _sequence-set_.
|
2024
2195
|
#
|
2025
2196
|
# _Note:_ this search key has no label.
|
@@ -2027,121 +2198,139 @@ module Net
|
|
2027
2198
|
# <em>+UIDONLY+ must *not* be enabled.</em>
|
2028
2199
|
# {[RFC9586]}[https://www.rfc-editor.org/rfc/rfc9586.html]
|
2029
2200
|
#
|
2030
|
-
# +UID+ _sequence-set_
|
2201
|
+
# [+UID+ _sequence-set_]
|
2031
2202
|
# Matches messages with a UID in _sequence-set_.
|
2032
2203
|
#
|
2033
|
-
#
|
2034
|
-
#
|
2204
|
+
# ===== Compound search keys
|
2205
|
+
#
|
2206
|
+
# [(_search-key_ _search-key_...)]
|
2207
|
+
# Combines one or more _search-key_ arguments to match
|
2208
|
+
# messages which match all contained search keys. Useful for +OR+, +NOT+,
|
2209
|
+
# and other search keys with _search-key_ arguments.
|
2210
|
+
#
|
2211
|
+
# _Note:_ this search key has no label.
|
2212
|
+
#
|
2213
|
+
# [+OR+ _search-key_ _search-key_]
|
2214
|
+
# Matches messages which match either _search-key_ argument.
|
2215
|
+
#
|
2216
|
+
# [+NOT+ _search-key_]
|
2217
|
+
# Matches messages which do not match _search-key_.
|
2218
|
+
#
|
2219
|
+
# [+FUZZY+ _search-key_]
|
2220
|
+
# Uses fuzzy matching for the specified search key.
|
2221
|
+
#
|
2222
|
+
# <em>Requires <tt>SEARCH=FUZZY</tt> capability.</em>
|
2223
|
+
# {[RFC6203]}[https://www.rfc-editor.org/rfc/rfc6203.html#section-6].
|
2224
|
+
#
|
2225
|
+
# ===== Flags search keys
|
2226
|
+
#
|
2227
|
+
# [+ANSWERED+, +UNANSWERED+]
|
2035
2228
|
# Matches messages with or without the <tt>\\Answered</tt> flag.
|
2036
|
-
# +DELETED
|
2037
|
-
# +UNDELETED+::
|
2229
|
+
# [+DELETED+, +UNDELETED+]
|
2038
2230
|
# Matches messages with or without the <tt>\\Deleted</tt> flag.
|
2039
|
-
# +DRAFT
|
2040
|
-
# +UNDRAFT+::
|
2231
|
+
# [+DRAFT+, +UNDRAFT+]
|
2041
2232
|
# Matches messages with or without the <tt>\\Draft</tt> flag.
|
2042
|
-
# +FLAGGED
|
2043
|
-
# +UNFLAGGED+::
|
2233
|
+
# [+FLAGGED+, +UNFLAGGED+]
|
2044
2234
|
# Matches messages with or without the <tt>\\Flagged</tt> flag.
|
2045
|
-
# +SEEN
|
2046
|
-
# +UNSEEN+::
|
2235
|
+
# [+SEEN+, +UNSEEN+]
|
2047
2236
|
# Matches messages with or without the <tt>\\Seen</tt> flag.
|
2048
|
-
#
|
2049
|
-
# +KEYWORD+ _keyword_::
|
2050
|
-
# +UNKEYWORD+ _keyword_::
|
2237
|
+
# [+KEYWORD+ _keyword_, +UNKEYWORD+ _keyword_]
|
2051
2238
|
# Matches messages with or without the specified _keyword_.
|
2052
2239
|
#
|
2053
|
-
# +
|
2054
|
-
# Matches
|
2055
|
-
#
|
2056
|
-
#
|
2057
|
-
# +
|
2058
|
-
#
|
2059
|
-
#
|
2060
|
-
#
|
2061
|
-
#
|
2062
|
-
#
|
2063
|
-
#
|
2064
|
-
# +
|
2240
|
+
# [+RECENT+, +UNRECENT+]
|
2241
|
+
# Matches messages with or without the <tt>\\Recent</tt> flag.
|
2242
|
+
#
|
2243
|
+
# *NOTE:* The <tt>\\Recent</tt> flag has been removed from +IMAP4rev2+.
|
2244
|
+
# [+NEW+]
|
2245
|
+
# Equivalent to <tt>(RECENT UNSEEN)</tt>.
|
2246
|
+
#
|
2247
|
+
# *NOTE:* The <tt>\\Recent</tt> flag has been removed from +IMAP4rev2+.
|
2248
|
+
#
|
2249
|
+
# ===== Header field substring search keys
|
2250
|
+
#
|
2251
|
+
# [+BCC+ _substring_]
|
2252
|
+
# Matches when _substring_ is in the envelope's +BCC+ field.
|
2253
|
+
# [+CC+ _substring_]
|
2254
|
+
# Matches when _substring_ is in the envelope's +CC+ field.
|
2255
|
+
# [+FROM+ _substring_]
|
2256
|
+
# Matches when _substring_ is in the envelope's +FROM+ field.
|
2257
|
+
# [+SUBJECT+ _substring_]
|
2258
|
+
# Matches when _substring_ is in the envelope's +SUBJECT+ field.
|
2259
|
+
# [+TO+ _substring_]
|
2260
|
+
# Matches when _substring_ is in the envelope's +TO+ field.
|
2261
|
+
#
|
2262
|
+
# [+HEADER+ _field_ _substring_]
|
2065
2263
|
# Matches when _substring_ is in the specified header _field_.
|
2066
2264
|
#
|
2067
|
-
#
|
2265
|
+
# ===== Body text search keys
|
2266
|
+
# [+BODY+ _string_]
|
2068
2267
|
# Matches when _string_ is in the body of the message.
|
2069
2268
|
# Does not match on header fields.
|
2070
2269
|
#
|
2071
2270
|
# The server _may_ use flexible matching, rather than simple substring
|
2072
2271
|
# matches. For example, this may use stemming or match only full words.
|
2073
2272
|
#
|
2074
|
-
# +TEXT+ _string_
|
2273
|
+
# [+TEXT+ _string_]
|
2075
2274
|
# Matches when _string_ is in the header or body of the message.
|
2076
2275
|
#
|
2077
2276
|
# The server _may_ use flexible matching, rather than simple substring
|
2078
2277
|
# matches. For example, this may use stemming or match only full words.
|
2079
2278
|
#
|
2080
|
-
#
|
2081
|
-
# +ON+ _date_::
|
2082
|
-
# +SINCE+ _date_::
|
2083
|
-
# Matches when the +INTERNALDATE+ is earlier than, on, or later than
|
2084
|
-
# _date_.
|
2279
|
+
# ===== Date/Time search keys
|
2085
2280
|
#
|
2086
|
-
# +SENTBEFORE+ _date_
|
2087
|
-
# +SENTON+ _date_
|
2088
|
-
# +SENTSINCE+ _date_
|
2281
|
+
# [+SENTBEFORE+ _date_]
|
2282
|
+
# [+SENTON+ _date_]
|
2283
|
+
# [+SENTSINCE+ _date_]
|
2089
2284
|
# Matches when the +Date+ header is earlier than, on, or later than _date_.
|
2090
2285
|
#
|
2091
|
-
# +
|
2092
|
-
# +
|
2093
|
-
#
|
2094
|
-
#
|
2095
|
-
#
|
2096
|
-
#
|
2097
|
-
# The <tt>\\Recent</tt> flag has been removed from +IMAP4rev2+. So these
|
2098
|
-
# search keys require the +IMAP4rev1+ capability.
|
2286
|
+
# [+BEFORE+ _date_]
|
2287
|
+
# [+ON+ _date_]
|
2288
|
+
# [+SINCE+ _date_]
|
2289
|
+
# Matches when the +INTERNALDATE+ is earlier than, on, or later than
|
2290
|
+
# _date_.
|
2099
2291
|
#
|
2100
|
-
# +
|
2101
|
-
# +
|
2102
|
-
# Matches
|
2292
|
+
# [+OLDER+ _interval_]
|
2293
|
+
# [+YOUNGER+ _interval_]
|
2294
|
+
# Matches when the +INTERNALDATE+ is more/less than _interval_ seconds ago.
|
2103
2295
|
#
|
2104
|
-
# +
|
2105
|
-
#
|
2296
|
+
# <em>Requires +WITHIN+ capability</em>.
|
2297
|
+
# {[RFC5032]}[https://www.rfc-editor.org/rfc/rfc5032.html]
|
2106
2298
|
#
|
2107
|
-
#
|
2299
|
+
# [+SAVEDBEFORE+ _date_]
|
2300
|
+
# [+SAVEDON+ _date_]
|
2301
|
+
# [+SAVEDSINCE+ _date_]
|
2302
|
+
# Matches when the save date is earlier than, on, or later than _date_.
|
2108
2303
|
#
|
2109
|
-
#
|
2304
|
+
# <em>Requires +SAVEDATE+ capability.</em>
|
2305
|
+
# {[RFC8514]}[https://www.rfc-editor.org/rfc/rfc8514.html#section-4.3]
|
2110
2306
|
#
|
2111
|
-
#
|
2112
|
-
# +YOUNGER+ _interval_::
|
2113
|
-
# Matches when +INTERNALDATE+ is more/less than _interval_ seconds ago.
|
2307
|
+
# ===== Other message attribute search keys
|
2114
2308
|
#
|
2115
|
-
#
|
2116
|
-
#
|
2309
|
+
# [+SMALLER+ _bytes_]
|
2310
|
+
# [+LARGER+ _bytes_]
|
2311
|
+
# Matches when +RFC822.SIZE+ is smaller or larger than _bytes_.
|
2117
2312
|
#
|
2118
|
-
# +ANNOTATION+ _entry_ _attr_ _value_
|
2313
|
+
# [+ANNOTATION+ _entry_ _attr_ _value_]
|
2119
2314
|
# Matches messages that have annotations with entries matching _entry_,
|
2120
2315
|
# attributes matching _attr_, and _value_ in the attribute's values.
|
2121
2316
|
#
|
2122
|
-
# <em>Requires
|
2317
|
+
# <em>Requires +ANNOTATE-EXPERIMENT-1+ capability</em>.
|
2123
2318
|
# {[RFC5257]}[https://www.rfc-editor.org/rfc/rfc5257.html].
|
2124
2319
|
#
|
2125
|
-
# +FILTER+ _filter_
|
2320
|
+
# [+FILTER+ _filter_]
|
2126
2321
|
# References a _filter_ that is stored on the server and matches all
|
2127
2322
|
# messages which would be matched by that filter's search criteria.
|
2128
2323
|
#
|
2129
|
-
# <em>Requires
|
2324
|
+
# <em>Requires +FILTERS+ capability</em>.
|
2130
2325
|
# {[RFC5466]}[https://www.rfc-editor.org/rfc/rfc5466.html#section-3.1]
|
2131
2326
|
#
|
2132
|
-
# +
|
2133
|
-
# Uses fuzzy matching for the specified search key.
|
2134
|
-
#
|
2135
|
-
# <em>Requires the <tt>SEARCH=FUZZY</tt> capability.</em>
|
2136
|
-
# {[RFC6203]}[https://www.rfc-editor.org/rfc/rfc6203.html#section-6].
|
2137
|
-
#
|
2138
|
-
# +MODSEQ+ _modseq_::
|
2327
|
+
# [+MODSEQ+ _modseq_]
|
2139
2328
|
# Matches when +MODSEQ+ is greater than or equal to _modseq_.
|
2140
2329
|
#
|
2141
|
-
# <em>Requires
|
2330
|
+
# <em>Requires +CONDSTORE+ capability</em>.
|
2142
2331
|
# {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html#section-3.1.5].
|
2143
2332
|
#
|
2144
|
-
# +MODSEQ+ _entry_ _entry-type_ _modseq_
|
2333
|
+
# [+MODSEQ+ _entry_ _entry-type_ _modseq_]
|
2145
2334
|
# Matches when a specific metadata _entry_ has been updated since
|
2146
2335
|
# _modseq_.
|
2147
2336
|
#
|
@@ -2150,33 +2339,25 @@ module Net
|
|
2150
2339
|
# <tt>\\</tt> prefix. _entry-type_ can be one of <tt>"shared"</tt>,
|
2151
2340
|
# <tt>"priv"</tt> (private), or <tt>"all"</tt>.
|
2152
2341
|
#
|
2153
|
-
# <em>Requires
|
2342
|
+
# <em>Requires +CONDSTORE+ capability</em>.
|
2154
2343
|
# {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html#section-3.1.5].
|
2155
2344
|
#
|
2156
|
-
# +EMAILID+ _objectid_
|
2157
|
-
# +THREADID+ _objectid_
|
2345
|
+
# [+EMAILID+ _objectid_]
|
2346
|
+
# [+THREADID+ _objectid_]
|
2158
2347
|
# Matches when +EMAILID+/+THREADID+ is equal to _objectid_
|
2159
2348
|
# (substring matches are not supported).
|
2160
2349
|
#
|
2161
|
-
# <em>Requires
|
2350
|
+
# <em>Requires +OBJECTID+ capability</em>.
|
2162
2351
|
# {[RFC8474]}[https://www.rfc-editor.org/rfc/rfc8474.html#section-6]
|
2163
2352
|
#
|
2164
|
-
#
|
2165
|
-
# Matches every message in the mailbox when the mailbox supports the save
|
2166
|
-
# date attribute. Otherwise, it matches no messages.
|
2167
|
-
#
|
2168
|
-
# <em>Requires the +SAVEDATE+ capability</em>.
|
2169
|
-
# {[RFC8514]}[https://www.rfc-editor.org/rfc/rfc8514.html#section-4.3]
|
2170
|
-
#
|
2171
|
-
# +SAVEDBEFORE+ _date_::
|
2172
|
-
# +SAVEDON+ _date_::
|
2173
|
-
# +SAVEDSINCE+ _date_::
|
2174
|
-
# Matches when the save date is earlier than, on, or later than _date_.
|
2353
|
+
# ==== Capabilities
|
2175
2354
|
#
|
2176
|
-
#
|
2177
|
-
#
|
2355
|
+
# Return options should only be specified when the server supports
|
2356
|
+
# +IMAP4rev2+ or an extension that allows them, such as +ESEARCH+
|
2357
|
+
# [RFC4731[https://rfc-editor.org/rfc/rfc4731#section-3.1]].
|
2178
2358
|
#
|
2179
|
-
#
|
2359
|
+
# When +IMAP4rev2+ is enabled, or when the server supports +IMAP4rev2+ but
|
2360
|
+
# not +IMAP4rev1+, ESearchResult is always returned instead of SearchResult.
|
2180
2361
|
#
|
2181
2362
|
# If CONDSTORE[https://www.rfc-editor.org/rfc/rfc7162.html] is supported
|
2182
2363
|
# and enabled for the selected mailbox, a non-empty SearchResult will
|
@@ -2191,6 +2372,7 @@ module Net
|
|
2191
2372
|
|
2192
2373
|
# :call-seq:
|
2193
2374
|
# uid_search(criteria, charset = nil) -> result
|
2375
|
+
# uid_search(criteria, charset: nil, return: nil) -> result
|
2194
2376
|
#
|
2195
2377
|
# Sends a {UID SEARCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
|
2196
2378
|
# to search the mailbox for messages that match the given searching
|
@@ -2211,14 +2393,9 @@ module Net
|
|
2211
2393
|
# Sends a {FETCH command [IMAP4rev1 §6.4.5]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.5]
|
2212
2394
|
# to retrieve data associated with a message in the mailbox.
|
2213
2395
|
#
|
2214
|
-
#
|
2215
|
-
#
|
2216
|
-
#
|
2217
|
-
# being interpreted as '100:*'. Beware that the +exclude_end?+
|
2218
|
-
# property of a Range object is ignored, and the contents of a
|
2219
|
-
# range are independent of the order of the range endpoints as per
|
2220
|
-
# the protocol specification, so 1...5, 5..1 and 5...1 are all
|
2221
|
-
# equivalent to 1..5.
|
2396
|
+
# +set+ is the message sequence numbers to fetch, and may be any valid input
|
2397
|
+
# to {SequenceSet[...]}[rdoc-ref:SequenceSet@Creating+sequence+sets].
|
2398
|
+
# (For UIDs, use #uid_fetch instead.)
|
2222
2399
|
#
|
2223
2400
|
# +attr+ is a list of attributes to fetch; see the documentation
|
2224
2401
|
# for FetchData for a list of valid attributes.
|
@@ -2228,9 +2405,9 @@ module Net
|
|
2228
2405
|
#
|
2229
2406
|
# The return value is an array of FetchData.
|
2230
2407
|
#
|
2231
|
-
# Related: #
|
2408
|
+
# Related: #uid_fetch, FetchData
|
2232
2409
|
#
|
2233
|
-
#
|
2410
|
+
# ==== For example:
|
2234
2411
|
#
|
2235
2412
|
# p imap.fetch(6..8, "UID")
|
2236
2413
|
# #=> [#<Net::IMAP::FetchData seqno=6, attr={"UID"=>98}>, \\
|
@@ -2248,7 +2425,7 @@ module Net
|
|
2248
2425
|
# p data.attr["UID"]
|
2249
2426
|
# #=> 98
|
2250
2427
|
#
|
2251
|
-
#
|
2428
|
+
# ==== Capabilities
|
2252
2429
|
#
|
2253
2430
|
# Many extensions define new message +attr+ names. See FetchData for a list
|
2254
2431
|
# of supported extension fields.
|
@@ -2257,30 +2434,66 @@ module Net
|
|
2257
2434
|
# {[RFC7162]}[https://tools.ietf.org/html/rfc7162] in order to use the
|
2258
2435
|
# +changedsince+ argument. Using +changedsince+ implicitly enables the
|
2259
2436
|
# +CONDSTORE+ extension.
|
2260
|
-
def fetch(
|
2261
|
-
fetch_internal("FETCH",
|
2437
|
+
def fetch(...)
|
2438
|
+
fetch_internal("FETCH", ...)
|
2262
2439
|
end
|
2263
2440
|
|
2264
2441
|
# :call-seq:
|
2265
|
-
# uid_fetch(set, attr, changedsince: nil) -> array of FetchData
|
2442
|
+
# uid_fetch(set, attr, changedsince: nil, partial: nil) -> array of FetchData
|
2266
2443
|
#
|
2267
2444
|
# Sends a {UID FETCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
|
2268
2445
|
# to retrieve data associated with a message in the mailbox.
|
2269
2446
|
#
|
2270
|
-
#
|
2271
|
-
#
|
2447
|
+
# +set+ is the message UIDs to fetch, and may be any valid input to
|
2448
|
+
# {SequenceSet[...]}[rdoc-ref:SequenceSet@Creating+sequence+sets].
|
2449
|
+
# (For message sequence numbers, use #fetch instead.)
|
2272
2450
|
#
|
2451
|
+
# +attr+ behaves the same as with #fetch.
|
2273
2452
|
# >>>
|
2274
2453
|
# *Note:* Servers _MUST_ implicitly include the +UID+ message data item as
|
2275
2454
|
# part of any +FETCH+ response caused by a +UID+ command, regardless of
|
2276
2455
|
# whether a +UID+ was specified as a message data item to the +FETCH+.
|
2277
2456
|
#
|
2457
|
+
# +changedsince+ (optional) behaves the same as with #fetch.
|
2458
|
+
#
|
2459
|
+
# +partial+ is an optional range to limit the number of results returned.
|
2460
|
+
# It's useful when +set+ contains an unknown number of messages.
|
2461
|
+
# <tt>1..500</tt> returns the first 500 messages in +set+ (in mailbox
|
2462
|
+
# order), <tt>501..1000</tt> the second 500, and so on. +partial+ may also
|
2463
|
+
# be negative: <tt>-500..-1</tt> selects the last 500 messages in +set+.
|
2464
|
+
# <em>Requires the +PARTIAL+ capabability.</em>
|
2465
|
+
# {[RFC9394]}[https://rfc-editor.org/rfc/rfc9394]
|
2466
|
+
#
|
2467
|
+
# For example:
|
2468
|
+
#
|
2469
|
+
# # Without partial, the size of the results may be unknown beforehand:
|
2470
|
+
# results = imap.uid_fetch(next_uid_to_fetch.., %w(UID FLAGS))
|
2471
|
+
# # ... maybe wait for a long time ... and allocate a lot of memory ...
|
2472
|
+
# results.size # => 0..2**32-1
|
2473
|
+
# process results # may also take a long time and use a lot of memory...
|
2474
|
+
#
|
2475
|
+
# # Using partial, the results may be paginated:
|
2476
|
+
# loop do
|
2477
|
+
# results = imap.uid_fetch(next_uid_to_fetch.., %w(UID FLAGS),
|
2478
|
+
# partial: 1..500)
|
2479
|
+
# # fetch should return quickly and allocate little memory
|
2480
|
+
# results.size # => 0..500
|
2481
|
+
# break if results.empty?
|
2482
|
+
# next_uid_to_fetch = results.last.uid + 1
|
2483
|
+
# process results
|
2484
|
+
# end
|
2485
|
+
#
|
2278
2486
|
# Related: #fetch, FetchData
|
2279
2487
|
#
|
2280
|
-
#
|
2281
|
-
#
|
2282
|
-
|
2283
|
-
|
2488
|
+
# ==== Capabilities
|
2489
|
+
#
|
2490
|
+
# The server's capabilities must include +PARTIAL+
|
2491
|
+
# {[RFC9394]}[https://rfc-editor.org/rfc/rfc9394] in order to use the
|
2492
|
+
# +partial+ argument.
|
2493
|
+
#
|
2494
|
+
# Otherwise, the same as #fetch.
|
2495
|
+
def uid_fetch(...)
|
2496
|
+
fetch_internal("UID FETCH", ...)
|
2284
2497
|
end
|
2285
2498
|
|
2286
2499
|
# :call-seq:
|
@@ -2311,14 +2524,14 @@ module Net
|
|
2311
2524
|
#
|
2312
2525
|
# Related: #uid_store
|
2313
2526
|
#
|
2314
|
-
#
|
2527
|
+
# ==== For example:
|
2315
2528
|
#
|
2316
2529
|
# p imap.store(6..8, "+FLAGS", [:Deleted])
|
2317
2530
|
# #=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>,
|
2318
2531
|
# #<Net::IMAP::FetchData seqno=7, attr={"FLAGS"=>[:Seen, :Deleted]}>,
|
2319
2532
|
# #<Net::IMAP::FetchData seqno=8, attr={"FLAGS"=>[:Seen, :Deleted]}>]
|
2320
2533
|
#
|
2321
|
-
#
|
2534
|
+
# ==== Capabilities
|
2322
2535
|
#
|
2323
2536
|
# Extensions may define new data items to be used with #store.
|
2324
2537
|
#
|
@@ -2342,7 +2555,7 @@ module Net
|
|
2342
2555
|
#
|
2343
2556
|
# Related: #store
|
2344
2557
|
#
|
2345
|
-
#
|
2558
|
+
# ==== Capabilities
|
2346
2559
|
# Same as #store.
|
2347
2560
|
def uid_store(set, attr, flags, unchangedsince: nil)
|
2348
2561
|
store_internal("UID STORE", set, attr, flags, unchangedsince: unchangedsince)
|
@@ -2355,7 +2568,7 @@ module Net
|
|
2355
2568
|
#
|
2356
2569
|
# Related: #uid_copy
|
2357
2570
|
#
|
2358
|
-
#
|
2571
|
+
# ==== Capabilities
|
2359
2572
|
#
|
2360
2573
|
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
|
2361
2574
|
# supported, the server's response should include a +COPYUID+ response code
|
@@ -2372,7 +2585,7 @@ module Net
|
|
2372
2585
|
#
|
2373
2586
|
# Similar to #copy, but +set+ contains unique identifiers.
|
2374
2587
|
#
|
2375
|
-
#
|
2588
|
+
# ==== Capabilities
|
2376
2589
|
#
|
2377
2590
|
# +UIDPLUS+ affects #uid_copy the same way it affects #copy.
|
2378
2591
|
def uid_copy(set, mailbox)
|
@@ -2387,7 +2600,7 @@ module Net
|
|
2387
2600
|
#
|
2388
2601
|
# Related: #uid_move
|
2389
2602
|
#
|
2390
|
-
#
|
2603
|
+
# ==== Capabilities
|
2391
2604
|
#
|
2392
2605
|
# The server's capabilities must include +MOVE+
|
2393
2606
|
# [RFC6851[https://tools.ietf.org/html/rfc6851]].
|
@@ -2411,7 +2624,7 @@ module Net
|
|
2411
2624
|
#
|
2412
2625
|
# Related: #move
|
2413
2626
|
#
|
2414
|
-
#
|
2627
|
+
# ==== Capabilities
|
2415
2628
|
#
|
2416
2629
|
# Same as #move: The server's capabilities must include +MOVE+
|
2417
2630
|
# [RFC6851[https://tools.ietf.org/html/rfc6851]]. +UIDPLUS+ also affects
|
@@ -2431,14 +2644,14 @@ module Net
|
|
2431
2644
|
#
|
2432
2645
|
# Related: #uid_sort, #search, #uid_search, #thread, #uid_thread
|
2433
2646
|
#
|
2434
|
-
#
|
2647
|
+
# ==== For example:
|
2435
2648
|
#
|
2436
2649
|
# p imap.sort(["FROM"], ["ALL"], "US-ASCII")
|
2437
2650
|
# #=> [1, 2, 3, 5, 6, 7, 8, 4, 9]
|
2438
2651
|
# p imap.sort(["DATE"], ["SUBJECT", "hello"], "US-ASCII")
|
2439
2652
|
# #=> [6, 7, 8, 1]
|
2440
2653
|
#
|
2441
|
-
#
|
2654
|
+
# ==== Capabilities
|
2442
2655
|
#
|
2443
2656
|
# The server's capabilities must include +SORT+
|
2444
2657
|
# [RFC5256[https://tools.ietf.org/html/rfc5256]].
|
@@ -2453,7 +2666,7 @@ module Net
|
|
2453
2666
|
#
|
2454
2667
|
# Related: #sort, #search, #uid_search, #thread, #uid_thread
|
2455
2668
|
#
|
2456
|
-
#
|
2669
|
+
# ==== Capabilities
|
2457
2670
|
#
|
2458
2671
|
# The server's capabilities must include +SORT+
|
2459
2672
|
# [RFC5256[https://tools.ietf.org/html/rfc5256]].
|
@@ -2478,7 +2691,7 @@ module Net
|
|
2478
2691
|
#
|
2479
2692
|
# Related: #uid_thread, #search, #uid_search, #sort, #uid_sort
|
2480
2693
|
#
|
2481
|
-
#
|
2694
|
+
# ==== Capabilities
|
2482
2695
|
#
|
2483
2696
|
# The server's capabilities must include +THREAD+
|
2484
2697
|
# [RFC5256[https://tools.ietf.org/html/rfc5256]].
|
@@ -2492,7 +2705,7 @@ module Net
|
|
2492
2705
|
#
|
2493
2706
|
# Related: #thread, #search, #uid_search, #sort, #uid_sort
|
2494
2707
|
#
|
2495
|
-
#
|
2708
|
+
# ==== Capabilities
|
2496
2709
|
#
|
2497
2710
|
# The server's capabilities must include +THREAD+
|
2498
2711
|
# [RFC5256[https://tools.ietf.org/html/rfc5256]].
|
@@ -2511,7 +2724,7 @@ module Net
|
|
2511
2724
|
#
|
2512
2725
|
# Related: #capable?, #capabilities, #capability
|
2513
2726
|
#
|
2514
|
-
#
|
2727
|
+
# ==== Capabilities
|
2515
2728
|
#
|
2516
2729
|
# The server's capabilities must include
|
2517
2730
|
# +ENABLE+ [RFC5161[https://tools.ietf.org/html/rfc5161]]
|
@@ -2613,7 +2826,7 @@ module Net
|
|
2613
2826
|
#
|
2614
2827
|
# Related: #idle_done, #noop, #check
|
2615
2828
|
#
|
2616
|
-
#
|
2829
|
+
# ==== Capabilities
|
2617
2830
|
#
|
2618
2831
|
# The server's capabilities must include +IDLE+
|
2619
2832
|
# [RFC2177[https://tools.ietf.org/html/rfc2177]].
|
@@ -2730,7 +2943,7 @@ module Net
|
|
2730
2943
|
#
|
2731
2944
|
# Related: #extract_responses, #clear_responses, #response_handlers, #greeting
|
2732
2945
|
#
|
2733
|
-
#
|
2946
|
+
# ==== Thread safety
|
2734
2947
|
# >>>
|
2735
2948
|
# *Note:* Access to the responses hash is synchronized for thread-safety.
|
2736
2949
|
# The receiver thread and response_handlers cannot process new responses
|
@@ -2744,7 +2957,7 @@ module Net
|
|
2744
2957
|
# thread, but will not modify any responses after adding them to the
|
2745
2958
|
# responses hash.
|
2746
2959
|
#
|
2747
|
-
#
|
2960
|
+
# ==== Clearing responses
|
2748
2961
|
#
|
2749
2962
|
# Previously unhandled responses are automatically cleared before entering a
|
2750
2963
|
# mailbox with #select or #examine. Long-lived connections can receive many
|
@@ -2753,7 +2966,7 @@ module Net
|
|
2753
2966
|
# the block, or remove responses with #extract_responses, #clear_responses,
|
2754
2967
|
# or #add_response_handler.
|
2755
2968
|
#
|
2756
|
-
#
|
2969
|
+
# ==== Missing responses
|
2757
2970
|
#
|
2758
2971
|
# Only non-+nil+ data is stored. Many important response codes have no data
|
2759
2972
|
# of their own, but are used as "tags" on the ResponseText object they are
|
@@ -3131,16 +3344,107 @@ module Net
|
|
3131
3344
|
end
|
3132
3345
|
end
|
3133
3346
|
|
3134
|
-
def
|
3135
|
-
keys = normalize_searching_criteria(keys)
|
3136
|
-
args = charset ? ["CHARSET", charset, *keys] : keys
|
3347
|
+
def expunge_internal(...)
|
3137
3348
|
synchronize do
|
3138
|
-
send_command(
|
3139
|
-
clear_responses("
|
3349
|
+
send_command(...)
|
3350
|
+
expunged_array = clear_responses("EXPUNGE")
|
3351
|
+
vanished_array = extract_responses("VANISHED") { !_1.earlier? }
|
3352
|
+
if vanished_array.empty?
|
3353
|
+
expunged_array
|
3354
|
+
elsif vanished_array.length == 1
|
3355
|
+
vanished_array.first
|
3356
|
+
else
|
3357
|
+
merged_uids = SequenceSet[*vanished_array.map(&:uids)]
|
3358
|
+
VanishedData[uids: merged_uids, earlier: false]
|
3359
|
+
end
|
3360
|
+
end
|
3361
|
+
end
|
3362
|
+
|
3363
|
+
RETURN_WHOLE = /\ARETURN\z/i
|
3364
|
+
RETURN_START = /\ARETURN\b/i
|
3365
|
+
private_constant :RETURN_WHOLE, :RETURN_START
|
3366
|
+
|
3367
|
+
def search_args(keys, charset_arg = nil, return: nil, charset: nil)
|
3368
|
+
{return:} => {return: return_kw}
|
3369
|
+
case [return_kw, keys]
|
3370
|
+
in [nil, Array[RETURN_WHOLE, return_opts, *keys]]
|
3371
|
+
return_opts = convert_return_opts(return_opts)
|
3372
|
+
esearch = true
|
3373
|
+
in [nil => return_opts, RETURN_START]
|
3374
|
+
esearch = true
|
3375
|
+
in [nil => return_opts, keys]
|
3376
|
+
esearch = false
|
3377
|
+
in [_, Array[RETURN_WHOLE, _, *] | RETURN_START]
|
3378
|
+
raise ArgumentError, "conflicting return options"
|
3379
|
+
in [_, Array[RETURN_WHOLE, _, *]] # workaround for https://bugs.ruby-lang.org/issues/20956
|
3380
|
+
raise ArgumentError, "conflicting return options"
|
3381
|
+
in [_, RETURN_START] # workaround for https://bugs.ruby-lang.org/issues/20956
|
3382
|
+
raise ArgumentError, "conflicting return options"
|
3383
|
+
in [return_opts, keys]
|
3384
|
+
return_opts = convert_return_opts(return_opts)
|
3385
|
+
esearch = true
|
3140
3386
|
end
|
3387
|
+
if charset && charset_arg
|
3388
|
+
raise ArgumentError, "multiple charset arguments"
|
3389
|
+
end
|
3390
|
+
charset ||= charset_arg
|
3391
|
+
# NOTE: not handling combined RETURN and CHARSET for raw strings
|
3392
|
+
if charset && keys in /\ACHARSET\b/i | Array[/\ACHARSET\z/i, *]
|
3393
|
+
raise ArgumentError, "multiple charset arguments"
|
3394
|
+
end
|
3395
|
+
args = normalize_searching_criteria(keys)
|
3396
|
+
args.prepend("CHARSET", charset) if charset
|
3397
|
+
args.prepend("RETURN", return_opts) if return_opts
|
3398
|
+
return args, esearch
|
3399
|
+
end
|
3400
|
+
|
3401
|
+
def convert_return_opts(unconverted)
|
3402
|
+
return_opts = Array.try_convert(unconverted) or
|
3403
|
+
raise TypeError, "expected return options to be Array, got %s" % [
|
3404
|
+
unconverted.class
|
3405
|
+
]
|
3406
|
+
return_opts.map {|opt|
|
3407
|
+
case opt
|
3408
|
+
when Symbol then opt.to_s
|
3409
|
+
when PartialRange::Negative then PartialRange[opt]
|
3410
|
+
when Range then SequenceSet[opt]
|
3411
|
+
else opt
|
3412
|
+
end
|
3413
|
+
}
|
3141
3414
|
end
|
3142
3415
|
|
3143
|
-
def
|
3416
|
+
def search_internal(cmd, ...)
|
3417
|
+
args, esearch = search_args(...)
|
3418
|
+
synchronize do
|
3419
|
+
tagged = send_command(cmd, *args)
|
3420
|
+
tag = tagged.tag
|
3421
|
+
# Only the last ESEARCH or SEARCH is used. Excess results are ignored.
|
3422
|
+
esearch_result = extract_responses("ESEARCH") {|response|
|
3423
|
+
response in ESearchResult(tag: ^tag)
|
3424
|
+
}.last
|
3425
|
+
search_result = clear_responses("SEARCH").last
|
3426
|
+
if esearch_result
|
3427
|
+
# silently ignore SEARCH results, if any
|
3428
|
+
esearch_result
|
3429
|
+
elsif search_result
|
3430
|
+
# warn EXPECTED_ESEARCH_RESULT if esearch
|
3431
|
+
search_result
|
3432
|
+
elsif esearch
|
3433
|
+
# warn NO_SEARCH_RESPONSE
|
3434
|
+
ESearchResult[tag:, uid: cmd.start_with?("UID ")]
|
3435
|
+
else
|
3436
|
+
# warn NO_SEARCH_RESPONSE
|
3437
|
+
SearchResult[]
|
3438
|
+
end
|
3439
|
+
end
|
3440
|
+
end
|
3441
|
+
|
3442
|
+
def fetch_internal(cmd, set, attr, mod = nil, partial: nil, changedsince: nil)
|
3443
|
+
set = SequenceSet[set]
|
3444
|
+
if partial
|
3445
|
+
mod ||= []
|
3446
|
+
mod << "PARTIAL" << PartialRange[partial]
|
3447
|
+
end
|
3144
3448
|
if changedsince
|
3145
3449
|
mod ||= []
|
3146
3450
|
mod << "CHANGEDSINCE" << Integer(changedsince)
|
@@ -3157,9 +3461,9 @@ module Net
|
|
3157
3461
|
synchronize do
|
3158
3462
|
clear_responses("FETCH")
|
3159
3463
|
if mod
|
3160
|
-
send_command(cmd,
|
3464
|
+
send_command(cmd, set, attr, mod)
|
3161
3465
|
else
|
3162
|
-
send_command(cmd,
|
3466
|
+
send_command(cmd, set, attr)
|
3163
3467
|
end
|
3164
3468
|
clear_responses("FETCH")
|
3165
3469
|
end
|
@@ -3198,7 +3502,7 @@ module Net
|
|
3198
3502
|
end
|
3199
3503
|
|
3200
3504
|
def normalize_searching_criteria(criteria)
|
3201
|
-
return RawData.new(criteria) if criteria.is_a?(String)
|
3505
|
+
return [RawData.new(criteria)] if criteria.is_a?(String)
|
3202
3506
|
criteria.map {|i|
|
3203
3507
|
if coerce_search_arg_to_seqset?(i)
|
3204
3508
|
SequenceSet[i]
|
@@ -3276,6 +3580,7 @@ require_relative "imap/errors"
|
|
3276
3580
|
require_relative "imap/config"
|
3277
3581
|
require_relative "imap/command_data"
|
3278
3582
|
require_relative "imap/data_encoding"
|
3583
|
+
require_relative "imap/data_lite"
|
3279
3584
|
require_relative "imap/flags"
|
3280
3585
|
require_relative "imap/response_data"
|
3281
3586
|
require_relative "imap/response_parser"
|