@@ -1935,7 +1935,7 @@ def uid_expunge(uid_set)
1935
1935
1936
1936
# :call-seq:
1937
1937
# search(criteria, charset = nil) -> result
1938
- # search(criteria, charset: nil) -> result
1938
+ # search(criteria, charset: nil, return: nil ) -> result
1939
1939
#
1940
1940
# Sends a {SEARCH command [IMAP4rev1 §6.4.4]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.4]
1941
1941
# to search the mailbox for messages that match the given search +criteria+,
@@ -1950,44 +1950,86 @@ def uid_expunge(uid_set)
1950
1950
# See {"Argument translation"}[rdoc-ref:#search@Argument+translation]
1951
1951
# and {"Search criteria"}[rdoc-ref:#search@Search+criteria], below.
1952
1952
#
1953
+ # +return+ options control what kind of information is returned about
1954
+ # messages matching the search +criteria+. Specifying +return+ should force
1955
+ # the server to return an ESearchResult instead of a SearchResult, but some
1956
+ # servers disobey this requirement. <em>Requires an extended search
1957
+ # capability, such as +ESEARCH+ or +IMAP4rev2+.</em>
1958
+ # See {"Argument translation"}[rdoc-ref:#search@Argument+translation]
1959
+ # and {"Return options"}[rdoc-ref:#search@Return+options], below.
1960
+ #
1953
1961
# +charset+ is the name of the {registered character
1954
1962
# set}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
1955
1963
# used by strings in the search +criteria+. When +charset+ isn't specified,
1956
1964
# either <tt>"US-ASCII"</tt> or <tt>"UTF-8"</tt> is assumed, depending on
1957
1965
# the server's capabilities.
1958
1966
#
1959
1967
# _NOTE:_ Return options and charset may be sent as part of +criteria+. Do
1960
- # not use the +charset+ argument when either return options or charset are
1961
- # embedded in +criteria+.
1968
+ # not use the +return+ or + charset+ arguments when either return options or
1969
+ # charset are embedded in +criteria+.
1962
1970
#
1963
1971
# Related: #uid_search
1964
1972
#
1965
1973
# ==== For example:
1966
1974
#
1967
- # p imap.search(["SUBJECT", "hello", "NOT", "SEEN"])
1975
+ # imap.search(["SUBJECT", "hello", "NOT", "SEEN"])
1968
1976
# #=> [1, 6, 7, 8]
1969
1977
#
1970
- # The following searches send the exact same command to the server:
1971
- #
1972
- # # criteria array, charset arg
1973
- # imap.search(["OR", "UNSEEN", %w(FLAGGED SUBJECT foo)], "UTF-8")
1974
- # # criteria string, charset arg
1975
- # imap.search("OR UNSEEN (FLAGGED SUBJECT foo)", "UTF-8")
1976
- # # criteria array contains charset arg
1977
- # imap.search([*%w[CHARSET UTF-8], "OR", "UNSEEN", %w(FLAGGED SUBJECT foo)])
1978
- # # criteria string contains charset arg
1979
- # imap.search("CHARSET UTF-8 OR UNSEEN (FLAGGED SUBJECT foo)")
1980
- #
1981
- # Sending return options and charset embedded in the +criteria+ arg:
1982
- # imap.search("RETURN (MIN MAX) CHARSET UTF-8 (OR UNSEEN FLAGGED)")
1983
- # imap.search(["RETURN", %w(MIN MAX),
1984
- # "CHARSET", "UTF-8",
1985
- # %w(OR UNSEEN FLAGGED)])
1978
+ # The following assumes the server supports +ESEARCH+ and +CONDSTORE+:
1979
+ #
1980
+ # result = imap.uid_search(["UID", 12345.., "MODSEQ", 620_162_338],
1981
+ # return: %w(all count min max))
1982
+ # # => #<data Net::IMAP::ESearchResult tag="RUBY0123", uid=true,
1983
+ # # data=[["ALL", Net::IMAP::SequenceSet["12346:12349,22222:22230"]],
1984
+ # # ["COUNT", 13], ["MIN", 12346], ["MAX", 22230],
1985
+ # # ["MODSEQ", 917162488]]>
1986
+ # result.to_a # => [12346, 12347, 12348, 12349, 22222, 22223, 22224,
1987
+ # # 22225, 22226, 22227, 22228, 22229, 22230]
1988
+ # result.uid? # => true
1989
+ # result.count # => 13
1990
+ # result.min # => 12346
1991
+ # result.max # => 22230
1992
+ # result.modseq # => 917162488
1993
+ #
1994
+ # Using +return+ options to limit the result to only min, max, and count:
1995
+ #
1996
+ # result = imap.uid_search(["UID", 12345..,], return: %w(count min max))
1997
+ # # => #<data Net::IMAP::ESearchResult tag="RUBY0124", uid=true,
1998
+ # # data=[["COUNT", 13], ["MIN", 12346], ["MAX", 22230]]>
1999
+ # result.to_a # => []
2000
+ # result.count # => 13
2001
+ # result.min # => 12346
2002
+ # result.max # => 22230
2003
+ #
2004
+ # Return options and charset may be sent as keyword args or embedded in the
2005
+ # +criteria+ arg, but they must be in the correct order: <tt>"RETURN (...)
2006
+ # CHARSET ... criteria..."</tt>. The following searches
2007
+ # send the exact same command to the server:
2008
+ #
2009
+ # # Return options and charset as keyword arguments (preferred)
2010
+ # imap.search(%w(OR UNSEEN FLAGGED), return: %w(MIN MAX), charset: "UTF-8")
2011
+ # # Embedding return and charset in the criteria array
2012
+ # imap.search(["RETURN", %w(MIN MAX), "CHARSET", "UTF-8", *%w(OR UNSEEN FLAGGED)])
2013
+ # # Embedding return and charset in the criteria string
2014
+ # imap.search("RETURN (MIN MAX) CHARSET UTF-8 OR UNSEEN FLAGGED")
2015
+ #
2016
+ # Sending charset as the second positional argument is supported for
2017
+ # backward compatibility. Future versions may print a deprecation warning:
2018
+ # imap.search(%w(OR UNSEEN FLAGGED), "UTF-8", return: %w(MIN MAX))
1986
2019
#
1987
2020
# ==== Argument translation
1988
2021
#
2022
+ # [+return+ options]
2023
+ # Must be an Array. Return option names are strings.
2024
+ # Unlike +criteria+, other return option arguments are not automatically
2025
+ # converted to SequenceSet.
2026
+ #
1989
2027
# [When +criteria+ is an Array]
1990
- # Each member is a +SEARCH+ command argument:
2028
+ # When the array begins with <tt>"RETURN"</tt> (case insensitive), the
2029
+ # second array element is translated like the +return+ parameter (as
2030
+ # described above).
2031
+ #
2032
+ # Every other member is a +SEARCH+ command argument:
1991
2033
# [SequenceSet]
1992
2034
# Encoded as an \IMAP +sequence-set+ with SequenceSet#valid_string.
1993
2035
# [Set, Range, <tt>-1</tt>, +:*+, responds to +#to_sequence_set+]
@@ -2276,7 +2318,7 @@ def search(...)
2276
2318
2277
2319
# :call-seq:
2278
2320
# uid_search(criteria, charset = nil) -> result
2279
- # uid_search(criteria, charset: nil) -> result
2321
+ # uid_search(criteria, charset: nil, return: nil ) -> result
2280
2322
#
2281
2323
# Sends a {UID SEARCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
2282
2324
# to search the mailbox for messages that match the given searching
@@ -3217,8 +3259,26 @@ def enforce_logindisabled?
3217
3259
end
3218
3260
end
3219
3261
3220
- def search_args ( keys , charset_arg = nil , charset : nil )
3221
- esearch = ( keys in /\A RETURN\b /i | Array [ /\A RETURN\z /i , *] )
3262
+ RETURN_WHOLE = /\A RETURN\z /i
3263
+ RETURN_START = /\A RETURN\b /i
3264
+ private_constant :RETURN_WHOLE , :RETURN_START
3265
+
3266
+ def search_args ( keys , charset_arg = nil , return : nil , charset : nil )
3267
+ { return :} => { return : return_kw }
3268
+ case [ return_kw , keys ]
3269
+ in [ nil , Array [ RETURN_WHOLE , return_opts , *keys ] ]
3270
+ return_opts = convert_return_opts ( return_opts )
3271
+ esearch = true
3272
+ in [ nil => return_opts , RETURN_START ]
3273
+ esearch = true
3274
+ in [ nil => return_opts , keys ]
3275
+ esearch = false
3276
+ in [ _ , Array [ RETURN_WHOLE , _ , *] | RETURN_START ]
3277
+ raise ArgumentError , "conflicting return options"
3278
+ in [ return_opts , keys ]
3279
+ return_opts = convert_return_opts ( return_opts )
3280
+ esearch = true
3281
+ end
3222
3282
if charset && charset_arg
3223
3283
raise ArgumentError , "multiple charset arguments"
3224
3284
end
@@ -3229,9 +3289,17 @@ def search_args(keys, charset_arg = nil, charset: nil)
3229
3289
end
3230
3290
args = normalize_searching_criteria ( keys )
3231
3291
args . prepend ( "CHARSET" , charset ) if charset
3292
+ args . prepend ( "RETURN" , return_opts ) if return_opts
3232
3293
return args , esearch
3233
3294
end
3234
3295
3296
+ def convert_return_opts ( unconverted )
3297
+ Array . try_convert ( unconverted ) or
3298
+ raise TypeError , "expected return options to be Array, got %s" % [
3299
+ unconverted . class
3300
+ ]
3301
+ end
3302
+
3235
3303
def search_internal ( cmd , ...)
3236
3304
args , esearch = search_args ( ...)
3237
3305
synchronize do
0 commit comments