net-imap 0.4.6 → 0.4.8

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.

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.6"
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
data/net-imap.gemspec CHANGED
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.metadata["homepage_uri"] = spec.homepage
23
23
  spec.metadata["source_code_uri"] = spec.homepage
24
+ spec.metadata["changelog_uri"] = spec.homepage + "/releases"
24
25
 
25
26
  # Specify which files should be added to the gem when it is released.
26
27
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
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.6
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-21 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
@@ -133,6 +134,7 @@ licenses:
133
134
  metadata:
134
135
  homepage_uri: https://github.com/ruby/net-imap
135
136
  source_code_uri: https://github.com/ruby/net-imap
137
+ changelog_uri: https://github.com/ruby/net-imap/releases
136
138
  post_install_message:
137
139
  rdoc_options: []
138
140
  require_paths: