net-imap 0.4.7 → 0.4.8

Sign up to get free protection for your applications and to get access to all the features.
data/lib/net/imap.rb CHANGED
@@ -404,8 +404,8 @@ module Net
404
404
  #
405
405
  # Although IMAP4rev2[https://tools.ietf.org/html/rfc9051] is not supported
406
406
  # yet, Net::IMAP supports several extensions that have been folded into it:
407
- # +ENABLE+, +IDLE+, +MOVE+, +NAMESPACE+, +SASL-IR+, +UIDPLUS+, +UNSELECT+, and
408
- # the fetch side of +BINARY+.
407
+ # +ENABLE+, +IDLE+, +MOVE+, +NAMESPACE+, +SASL-IR+, +UIDPLUS+, +UNSELECT+,
408
+ # <tt>STATUS=SIZE</tt>, and the fetch side of +BINARY+.
409
409
  # Commands for these extensions are listed with the {Core IMAP
410
410
  # commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands], above.
411
411
  #
@@ -413,9 +413,7 @@ module Net
413
413
  # <em>The following are folded into +IMAP4rev2+ but are currently
414
414
  # unsupported or incompletely supported by</em> Net::IMAP<em>: RFC4466
415
415
  # extensions, +ESEARCH+, +SEARCHRES+, +LIST-EXTENDED+, +LIST-STATUS+,
416
- # +LITERAL-+, and +SPECIAL-USE+. The following extensions are implicitly
417
- # supported, but will be updated with more direct support: RFC5530 response
418
- # codes, <tt>STATUS=SIZE</tt>, and <tt>STATUS=DELETED</tt>.</em>
416
+ # +LITERAL-+, and +SPECIAL-USE+.</em>
419
417
  #
420
418
  # ==== RFC2087: +QUOTA+
421
419
  # - #getquota: returns the resource usage and limits for a quota root
@@ -504,6 +502,25 @@ module Net
504
502
  #
505
503
  # - See #enable for information about support for UTF-8 string encoding.
506
504
  #
505
+ # ==== RFC7162: +CONDSTORE+
506
+ #
507
+ # - Updates #enable with +CONDSTORE+ parameter. +CONDSTORE+ will also be
508
+ # enabled by using any of the extension's command parameters, listed below.
509
+ # - Updates #status with the +HIGHESTMODSEQ+ status attribute.
510
+ # - Updates #select and #examine with the +condstore+ modifier, and adds
511
+ # either a +HIGHESTMODSEQ+ or +NOMODSEQ+ ResponseCode to the responses.
512
+ # - Updates #search, #uid_search, #sort, and #uid_sort with the +MODSEQ+
513
+ # search criterion, and adds SearchResult#modseq to the search response.
514
+ # - Updates #thread and #uid_thread with the +MODSEQ+ search criterion
515
+ # <em>(but thread responses are unchanged)</em>.
516
+ # - Updates #fetch and #uid_fetch with the +changedsince+ modifier and
517
+ # +MODSEQ+ FetchData attribute.
518
+ # - Updates #store and #uid_store with the +unchangedsince+ modifier and adds
519
+ # the +MODIFIED+ ResponseCode to the tagged response.
520
+ #
521
+ # ==== RFC8438: <tt>STATUS=SIZE</tt>
522
+ # - Updates #status with the +SIZE+ status attribute.
523
+ #
507
524
  # ==== RFC8474: +OBJECTID+
508
525
  # - Adds +MAILBOXID+ ResponseCode to #create tagged response.
509
526
  # - Adds +MAILBOXID+ ResponseCode to #select and #examine untagged response.
@@ -668,6 +685,16 @@ module Net
668
685
  # Resnick, P., Ed., Newman, C., Ed., and S. Shen, Ed.,
669
686
  # "IMAP Support for UTF-8", RFC 6855, DOI 10.17487/RFC6855, March 2013,
670
687
  # <https://www.rfc-editor.org/info/rfc6855>.
688
+ # [CONDSTORE[https://tools.ietf.org/html/rfc7162]]::
689
+ # [QRESYNC[https://tools.ietf.org/html/rfc7162]]::
690
+ # Melnikov, A. and D. Cridland, "IMAP Extensions: Quick Flag Changes
691
+ # Resynchronization (CONDSTORE) and Quick Mailbox Resynchronization
692
+ # (QRESYNC)", RFC 7162, DOI 10.17487/RFC7162, May 2014,
693
+ # <https://www.rfc-editor.org/info/rfc7162>.
694
+ # [OBJECTID[https://tools.ietf.org/html/rfc8474]]::
695
+ # Gondwana, B., Ed., "IMAP Extension for Object Identifiers",
696
+ # RFC 8474, DOI 10.17487/RFC8474, September 2018,
697
+ # <https://www.rfc-editor.org/info/rfc8474>.
671
698
  #
672
699
  # === IANA registries
673
700
  # * {IMAP Capabilities}[http://www.iana.org/assignments/imap4-capabilities]
@@ -690,7 +717,7 @@ module Net
690
717
  # * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
691
718
  #
692
719
  class IMAP < Protocol
693
- VERSION = "0.4.7"
720
+ VERSION = "0.4.8"
694
721
 
695
722
  # Aliases for supported capabilities, to be used with the #enable command.
696
723
  ENABLE_ALIASES = {
@@ -1344,6 +1371,12 @@ module Net
1344
1371
  # or when existing messages are expunged; see #add_response_handler for a
1345
1372
  # way to detect these events.
1346
1373
  #
1374
+ # When the +condstore+ keyword argument is true, the server is told to
1375
+ # enable the extension. If +mailbox+ supports persistence of mod-sequences,
1376
+ # the +HIGHESTMODSEQ+ ResponseCode will be sent as an untagged response to
1377
+ # #select and all `FETCH` responses will include FetchData#modseq.
1378
+ # Otherwise, the +NOMODSEQ+ ResponseCode will be sent.
1379
+ #
1347
1380
  # A Net::IMAP::NoResponseError is raised if the mailbox does not
1348
1381
  # exist or is for some reason non-selectable.
1349
1382
  #
@@ -1356,10 +1389,17 @@ module Net
1356
1389
  # response code indicating that the mailstore does not support persistent
1357
1390
  # UIDs:
1358
1391
  # imap.responses("NO", &:last)&.code&.name == "UIDNOTSTICKY"
1359
- def select(mailbox)
1392
+ #
1393
+ # If [CONDSTORE[https://www.rfc-editor.org/rfc/rfc7162.html]] is supported,
1394
+ # the +condstore+ keyword parameter may be used.
1395
+ # imap.select("mbox", condstore: true)
1396
+ # modseq = imap.responses("HIGHESTMODSEQ", &:last)
1397
+ def select(mailbox, condstore: false)
1398
+ args = ["SELECT", mailbox]
1399
+ args << ["CONDSTORE"] if condstore
1360
1400
  synchronize do
1361
1401
  @responses.clear
1362
- send_command("SELECT", mailbox)
1402
+ send_command(*args)
1363
1403
  end
1364
1404
  end
1365
1405
 
@@ -1372,10 +1412,12 @@ module Net
1372
1412
  # exist or is for some reason non-examinable.
1373
1413
  #
1374
1414
  # Related: #select
1375
- def examine(mailbox)
1415
+ def examine(mailbox, condstore: false)
1416
+ args = ["EXAMINE", mailbox]
1417
+ args << ["CONDSTORE"] if condstore
1376
1418
  synchronize do
1377
1419
  @responses.clear
1378
- send_command("EXAMINE", mailbox)
1420
+ send_command(*args)
1379
1421
  end
1380
1422
  end
1381
1423
 
@@ -1688,7 +1730,7 @@ module Net
1688
1730
  end
1689
1731
  end
1690
1732
 
1691
- # Sends a {STATUS commands [IMAP4rev1 §6.3.10]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.10]
1733
+ # Sends a {STATUS command [IMAP4rev1 §6.3.10]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.10]
1692
1734
  # and returns the status of the indicated +mailbox+. +attr+ is a list of one
1693
1735
  # or more attributes whose statuses are to be requested.
1694
1736
  #
@@ -1715,10 +1757,13 @@ module Net
1715
1757
  # The approximate size of the mailbox---must be greater than or equal to
1716
1758
  # the sum of all messages' +RFC822.SIZE+ fetch item values.
1717
1759
  #
1760
+ # +HIGHESTMODSEQ+::
1761
+ # The highest mod-sequence value of all messages in the mailbox. See
1762
+ # +CONDSTORE+ {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html].
1763
+ #
1718
1764
  # +MAILBOXID+::
1719
- # A server-allocated unique _string_ identifier for the mailbox.
1720
- # See +OBJECTID+
1721
- # {[RFC8474]}[https://www.rfc-editor.org/rfc/rfc8474.html#section-4].
1765
+ # A server-allocated unique _string_ identifier for the mailbox. See
1766
+ # +OBJECTID+ {[RFC8474]}[https://www.rfc-editor.org/rfc/rfc8474.html].
1722
1767
  #
1723
1768
  # +RECENT+::
1724
1769
  # The number of messages with the <tt>\Recent</tt> flag.
@@ -1740,6 +1785,9 @@ module Net
1740
1785
  #
1741
1786
  # +DELETED+ requires the server's capabilities to include +IMAP4rev2+.
1742
1787
  #
1788
+ # +HIGHESTMODSEQ+ requires the server's capabilities to include +CONDSTORE+
1789
+ # {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html].
1790
+ #
1743
1791
  # +MAILBOXID+ requires the server's capabilities to include +OBJECTID+
1744
1792
  # {[RFC8474]}[https://www.rfc-editor.org/rfc/rfc8474.html].
1745
1793
  def status(mailbox, attr)
@@ -1876,6 +1924,10 @@ module Net
1876
1924
  # string holding the entire search string, or a single-dimension array of
1877
1925
  # search keywords and arguments.
1878
1926
  #
1927
+ # Returns a SearchResult object. SearchResult inherits from Array (for
1928
+ # backward compatibility) but adds SearchResult#modseq when the +CONDSTORE+
1929
+ # capability has been enabled.
1930
+ #
1879
1931
  # Related: #uid_search
1880
1932
  #
1881
1933
  # ===== Search criteria
@@ -1924,6 +1976,15 @@ module Net
1924
1976
  # p imap.search(["SUBJECT", "hello", "NOT", "NEW"])
1925
1977
  # #=> [1, 6, 7, 8]
1926
1978
  #
1979
+ # ===== Capabilities
1980
+ #
1981
+ # If [CONDSTORE[https://www.rfc-editor.org/rfc/rfc7162.html]] is supported
1982
+ # and enabled for the selected mailbox, a non-empty SearchResult will
1983
+ # include a +MODSEQ+ value.
1984
+ # imap.select("mbox", condstore: true)
1985
+ # result = imap.search(["SUBJECT", "hi there", "not", "new")
1986
+ # #=> Net::IMAP::SearchResult[1, 6, 7, 8, modseq: 5594]
1987
+ # result.modseq # => 5594
1927
1988
  def search(keys, charset = nil)
1928
1989
  return search_internal("SEARCH", keys, charset)
1929
1990
  end
@@ -1932,11 +1993,18 @@ module Net
1932
1993
  # to search the mailbox for messages that match the given searching
1933
1994
  # criteria, and returns unique identifiers (<tt>UID</tt>s).
1934
1995
  #
1996
+ # Returns a SearchResult object. SearchResult inherits from Array (for
1997
+ # backward compatibility) but adds SearchResult#modseq when the +CONDSTORE+
1998
+ # capability has been enabled.
1999
+ #
1935
2000
  # See #search for documentation of search criteria.
1936
2001
  def uid_search(keys, charset = nil)
1937
2002
  return search_internal("UID SEARCH", keys, charset)
1938
2003
  end
1939
2004
 
2005
+ # :call-seq:
2006
+ # fetch(set, attr, changedsince: nil) -> array of FetchData
2007
+ #
1940
2008
  # Sends a {FETCH command [IMAP4rev1 §6.4.5]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.5]
1941
2009
  # to retrieve data associated with a message in the mailbox.
1942
2010
  #
@@ -1952,6 +2020,9 @@ module Net
1952
2020
  # +attr+ is a list of attributes to fetch; see the documentation
1953
2021
  # for FetchData for a list of valid attributes.
1954
2022
  #
2023
+ # +changedsince+ is an optional integer mod-sequence. It limits results to
2024
+ # messages with a mod-sequence greater than +changedsince+.
2025
+ #
1955
2026
  # The return value is an array of FetchData.
1956
2027
  #
1957
2028
  # Related: #uid_search, FetchData
@@ -1973,10 +2044,23 @@ module Net
1973
2044
  # #=> "12-Oct-2000 22:40:59 +0900"
1974
2045
  # p data.attr["UID"]
1975
2046
  # #=> 98
1976
- def fetch(set, attr, mod = nil)
1977
- return fetch_internal("FETCH", set, attr, mod)
2047
+ #
2048
+ # ===== Capabilities
2049
+ #
2050
+ # Many extensions define new message +attr+ names. See FetchData for a list
2051
+ # of supported extension fields.
2052
+ #
2053
+ # The server's capabilities must include +CONDSTORE+
2054
+ # {[RFC7162]}[https://tools.ietf.org/html/rfc7162] in order to use the
2055
+ # +changedsince+ argument. Using +changedsince+ implicitly enables the
2056
+ # +CONDSTORE+ extension.
2057
+ def fetch(set, attr, mod = nil, changedsince: nil)
2058
+ fetch_internal("FETCH", set, attr, mod, changedsince: changedsince)
1978
2059
  end
1979
2060
 
2061
+ # :call-seq:
2062
+ # uid_fetch(set, attr, changedsince: nil) -> array of FetchData
2063
+ #
1980
2064
  # Sends a {UID FETCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
1981
2065
  # to retrieve data associated with a message in the mailbox.
1982
2066
  #
@@ -1989,17 +2073,36 @@ module Net
1989
2073
  # whether a +UID+ was specified as a message data item to the +FETCH+.
1990
2074
  #
1991
2075
  # Related: #fetch, FetchData
1992
- def uid_fetch(set, attr, mod = nil)
1993
- return fetch_internal("UID FETCH", set, attr, mod)
2076
+ #
2077
+ # ===== Capabilities
2078
+ # Same as #fetch.
2079
+ def uid_fetch(set, attr, mod = nil, changedsince: nil)
2080
+ fetch_internal("UID FETCH", set, attr, mod, changedsince: changedsince)
1994
2081
  end
1995
2082
 
2083
+ # :call-seq:
2084
+ # store(set, attr, value, unchangedsince: nil) -> array of FetchData
2085
+ #
1996
2086
  # Sends a {STORE command [IMAP4rev1 §6.4.6]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.6]
1997
2087
  # to alter data associated with messages in the mailbox, in particular their
1998
- # flags. The +set+ parameter is a number, an array of numbers, or a Range
1999
- # object. Each number is a message sequence number. +attr+ is the name of a
2000
- # data item to store: <tt>"FLAGS"</tt> will replace the message's flag list
2001
- # with the provided one, <tt>"+FLAGS"</tt> will add the provided flags, and
2002
- # <tt>"-FLAGS"</tt> will remove them. +flags+ is a list of flags.
2088
+ # flags.
2089
+ #
2090
+ # +set+ is a number, an array of numbers, or a Range object. Each number is
2091
+ # a message sequence number.
2092
+ #
2093
+ # +attr+ is the name of a data item to store. The semantics of +value+
2094
+ # varies based on +attr+:
2095
+ # * When +attr+ is <tt>"FLAGS"</tt>, the flags in +value+ replace the
2096
+ # message's flag list.
2097
+ # * When +attr+ is <tt>"+FLAGS"</tt>, the flags in +value+ are added to
2098
+ # the flags for the message.
2099
+ # * When +attr+ is <tt>"-FLAGS"</tt>, the flags in +value+ are removed
2100
+ # from the message.
2101
+ #
2102
+ # +unchangedsince+ is an optional integer mod-sequence. It prohibits any
2103
+ # changes to messages with +mod-sequence+ greater than the specified
2104
+ # +unchangedsince+ value. A SequenceSet of any messages that fail this
2105
+ # check will be returned in a +MODIFIED+ ResponseCode.
2003
2106
  #
2004
2107
  # The return value is an array of FetchData.
2005
2108
  #
@@ -2008,13 +2111,25 @@ module Net
2008
2111
  # ===== For example:
2009
2112
  #
2010
2113
  # p imap.store(6..8, "+FLAGS", [:Deleted])
2011
- # #=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\
2012
- # #<Net::IMAP::FetchData seqno=7, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\
2114
+ # #=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>,
2115
+ # #<Net::IMAP::FetchData seqno=7, attr={"FLAGS"=>[:Seen, :Deleted]}>,
2013
2116
  # #<Net::IMAP::FetchData seqno=8, attr={"FLAGS"=>[:Seen, :Deleted]}>]
2014
- def store(set, attr, flags)
2015
- return store_internal("STORE", set, attr, flags)
2117
+ #
2118
+ # ===== Capabilities
2119
+ #
2120
+ # Extensions may define new data items to be used with #store.
2121
+ #
2122
+ # The server's capabilities must include +CONDSTORE+
2123
+ # {[RFC7162]}[https://tools.ietf.org/html/rfc7162] in order to use the
2124
+ # +unchangedsince+ argument. Using +unchangedsince+ implicitly enables the
2125
+ # +CONDSTORE+ extension.
2126
+ def store(set, attr, flags, unchangedsince: nil)
2127
+ store_internal("STORE", set, attr, flags, unchangedsince: unchangedsince)
2016
2128
  end
2017
2129
 
2130
+ # :call-seq:
2131
+ # uid_store(set, attr, value, unchangedsince: nil) -> array of FetchData
2132
+ #
2018
2133
  # Sends a {UID STORE command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
2019
2134
  # to alter data associated with messages in the mailbox, in particular their
2020
2135
  # flags.
@@ -2023,8 +2138,11 @@ module Net
2023
2138
  # message sequence numbers.
2024
2139
  #
2025
2140
  # Related: #store
2026
- def uid_store(set, attr, flags)
2027
- return store_internal("UID STORE", set, attr, flags)
2141
+ #
2142
+ # ===== Capabilities
2143
+ # Same as #store.
2144
+ def uid_store(set, attr, flags, unchangedsince: nil)
2145
+ store_internal("UID STORE", set, attr, flags, unchangedsince: unchangedsince)
2028
2146
  end
2029
2147
 
2030
2148
  # Sends a {COPY command [IMAP4rev1 §6.4.7]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.7]
@@ -2200,6 +2318,13 @@ module Net
2200
2318
  # each enabled extension (usually the same name as the enabled extension).
2201
2319
  # The following capabilities may be enabled:
2202
2320
  #
2321
+ # [+CONDSTORE+ {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html]]
2322
+ #
2323
+ # Updates various commands to return +CONDSTORE+ extension responses. It
2324
+ # is not necessary to explicitly enable +CONDSTORE+—using any of the
2325
+ # command parameters defined by the extension will implicitly enable it.
2326
+ # See {[RFC7162 §3.1]}[https://www.rfc-editor.org/rfc/rfc7162.html#section-3.1].
2327
+ #
2203
2328
  # [+:utf8+ --- an alias for <tt>"UTF8=ACCEPT"</tt>]
2204
2329
  #
2205
2330
  # In a future release, <tt>enable(:utf8)</tt> will enable either
@@ -2711,7 +2836,11 @@ module Net
2711
2836
  end
2712
2837
  end
2713
2838
 
2714
- def fetch_internal(cmd, set, attr, mod = nil)
2839
+ def fetch_internal(cmd, set, attr, mod = nil, changedsince: nil)
2840
+ if changedsince
2841
+ mod ||= []
2842
+ mod << "CHANGEDSINCE" << Integer(changedsince)
2843
+ end
2715
2844
  case attr
2716
2845
  when String then
2717
2846
  attr = RawData.new(attr)
@@ -2732,13 +2861,14 @@ module Net
2732
2861
  end
2733
2862
  end
2734
2863
 
2735
- def store_internal(cmd, set, attr, flags)
2736
- if attr.instance_of?(String)
2737
- attr = RawData.new(attr)
2738
- end
2864
+ def store_internal(cmd, set, attr, flags, unchangedsince: nil)
2865
+ attr = RawData.new(attr) if attr.instance_of?(String)
2866
+ args = [MessageSet.new(set)]
2867
+ args << ["UNCHANGEDSINCE", Integer(unchangedsince)] if unchangedsince
2868
+ args << attr << flags
2739
2869
  synchronize do
2740
2870
  clear_responses("FETCH")
2741
- send_command(cmd, MessageSet.new(set), attr, flags)
2871
+ send_command(cmd, *args)
2742
2872
  clear_responses("FETCH")
2743
2873
  end
2744
2874
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-imap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.7
4
+ version: 0.4.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shugo Maeda
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2023-11-29 00:00:00.000000000 Z
12
+ date: 2023-12-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: net-protocol
@@ -113,6 +113,7 @@ files:
113
113
  - lib/net/imap/sasl/stringprep.rb
114
114
  - lib/net/imap/sasl/xoauth2_authenticator.rb
115
115
  - lib/net/imap/sasl_adapter.rb
116
+ - lib/net/imap/search_result.rb
116
117
  - lib/net/imap/sequence_set.rb
117
118
  - lib/net/imap/stringprep.rb
118
119
  - lib/net/imap/stringprep/nameprep.rb