net-imap 0.4.4 → 0.4.9

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,18 +404,16 @@ 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+, and +UNSELECT+.
407
+ # +ENABLE+, +IDLE+, +MOVE+, +NAMESPACE+, +SASL-IR+, +UIDPLUS+, +UNSELECT+,
408
+ # <tt>STATUS=SIZE</tt>, and the fetch side of +BINARY+.
408
409
  # Commands for these extensions are listed with the {Core IMAP
409
410
  # commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands], above.
410
411
  #
411
412
  # >>>
412
413
  # <em>The following are folded into +IMAP4rev2+ but are currently
413
414
  # unsupported or incompletely supported by</em> Net::IMAP<em>: RFC4466
414
- # extensions, +ESEARCH+, +SEARCHRES+, +LIST-EXTENDED+,
415
- # +LIST-STATUS+, +LITERAL-+, +BINARY+ fetch, and +SPECIAL-USE+. The
416
- # following extensions are implicitly supported, but will be updated with
417
- # more direct support: RFC5530 response codes, <tt>STATUS=SIZE</tt>, and
418
- # <tt>STATUS=DELETED</tt>.</em>
415
+ # extensions, +ESEARCH+, +SEARCHRES+, +LIST-EXTENDED+, +LIST-STATUS+,
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
@@ -437,6 +435,15 @@ module Net
437
435
  # ==== RFC2971: +ID+
438
436
  # - #id: exchanges client and server implementation information.
439
437
  #
438
+ # ==== RFC3516: +BINARY+
439
+ # The fetch side of +BINARY+ has been folded into
440
+ # IMAP4rev2[https://tools.ietf.org/html/rfc9051].
441
+ # - Updates #fetch and #uid_fetch with the +BINARY+, +BINARY.PEEK+, and
442
+ # +BINARY.SIZE+ items. See FetchData#binary and FetchData#binary_size.
443
+ #
444
+ # >>>
445
+ # *NOTE:* The binary extension the #append command is _not_ supported yet.
446
+ #
440
447
  # ==== RFC3691: +UNSELECT+
441
448
  # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051] and also included
442
449
  # above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
@@ -474,9 +481,17 @@ module Net
474
481
  # which arranges the results into ordered groups or threads according to a
475
482
  # chosen algorithm.
476
483
  #
477
- # ==== +XLIST+ (non-standard, deprecated)
484
+ # ==== +X-GM-EXT-1+
485
+ # +X-GM-EXT-1+ is a non-standard Gmail extension. See {Google's
486
+ # documentation}[https://developers.google.com/gmail/imap/imap-extensions].
487
+ # - Updates #fetch and #uid_fetch with support for +X-GM-MSGID+ (unique
488
+ # message ID), +X-GM-THRID+ (thread ID), and +X-GM-LABELS+ (Gmail labels).
489
+ # - Updates #search with the +X-GM-RAW+ search attribute.
478
490
  # - #xlist: replaced by +SPECIAL-USE+ attributes in #list responses.
479
491
  #
492
+ # *NOTE:* The +OBJECTID+ extension should replace +X-GM-MSGID+ and
493
+ # +X-GM-THRID+, but Gmail does not support it (as of 2023-11-10).
494
+ #
480
495
  # ==== RFC6851: +MOVE+
481
496
  # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051] and also included
482
497
  # above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
@@ -487,6 +502,32 @@ module Net
487
502
  #
488
503
  # - See #enable for information about support for UTF-8 string encoding.
489
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
+ #
524
+ # ==== RFC8474: +OBJECTID+
525
+ # - Adds +MAILBOXID+ ResponseCode to #create tagged response.
526
+ # - Adds +MAILBOXID+ ResponseCode to #select and #examine untagged response.
527
+ # - Updates #fetch and #uid_fetch with the +EMAILID+ and +THREADID+ items.
528
+ # See FetchData#emailid and FetchData#emailid.
529
+ # - Updates #status with support for the +MAILBOXID+ status attribute.
530
+ #
490
531
  # == References
491
532
  #
492
533
  # [{IMAP4rev1}[https://www.rfc-editor.org/rfc/rfc3501.html]]::
@@ -612,6 +653,10 @@ module Net
612
653
  # [ID[https://tools.ietf.org/html/rfc2971]]::
613
654
  # Showalter, T., "IMAP4 ID extension", RFC 2971, DOI 10.17487/RFC2971,
614
655
  # October 2000, <https://www.rfc-editor.org/info/rfc2971>.
656
+ # [BINARY[https://tools.ietf.org/html/rfc3516]]::
657
+ # Nerenberg, L., "IMAP4 Binary Content Extension", RFC 3516,
658
+ # DOI 10.17487/RFC3516, April 2003,
659
+ # <https://www.rfc-editor.org/info/rfc3516>.
615
660
  # [ACL[https://tools.ietf.org/html/rfc4314]]::
616
661
  # Melnikov, A., "IMAP4 Access Control List (ACL) Extension", RFC 4314,
617
662
  # DOI 10.17487/RFC4314, December 2005,
@@ -640,6 +685,16 @@ module Net
640
685
  # Resnick, P., Ed., Newman, C., Ed., and S. Shen, Ed.,
641
686
  # "IMAP Support for UTF-8", RFC 6855, DOI 10.17487/RFC6855, March 2013,
642
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>.
643
698
  #
644
699
  # === IANA registries
645
700
  # * {IMAP Capabilities}[http://www.iana.org/assignments/imap4-capabilities]
@@ -662,7 +717,7 @@ module Net
662
717
  # * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
663
718
  #
664
719
  class IMAP < Protocol
665
- VERSION = "0.4.4"
720
+ VERSION = "0.4.9"
666
721
 
667
722
  # Aliases for supported capabilities, to be used with the #enable command.
668
723
  ENABLE_ALIASES = {
@@ -1316,6 +1371,12 @@ module Net
1316
1371
  # or when existing messages are expunged; see #add_response_handler for a
1317
1372
  # way to detect these events.
1318
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
+ #
1319
1380
  # A Net::IMAP::NoResponseError is raised if the mailbox does not
1320
1381
  # exist or is for some reason non-selectable.
1321
1382
  #
@@ -1328,10 +1389,17 @@ module Net
1328
1389
  # response code indicating that the mailstore does not support persistent
1329
1390
  # UIDs:
1330
1391
  # imap.responses("NO", &:last)&.code&.name == "UIDNOTSTICKY"
1331
- 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
1332
1400
  synchronize do
1333
1401
  @responses.clear
1334
- send_command("SELECT", mailbox)
1402
+ send_command(*args)
1335
1403
  end
1336
1404
  end
1337
1405
 
@@ -1344,10 +1412,12 @@ module Net
1344
1412
  # exist or is for some reason non-examinable.
1345
1413
  #
1346
1414
  # Related: #select
1347
- def examine(mailbox)
1415
+ def examine(mailbox, condstore: false)
1416
+ args = ["EXAMINE", mailbox]
1417
+ args << ["CONDSTORE"] if condstore
1348
1418
  synchronize do
1349
1419
  @responses.clear
1350
- send_command("EXAMINE", mailbox)
1420
+ send_command(*args)
1351
1421
  end
1352
1422
  end
1353
1423
 
@@ -1660,23 +1730,66 @@ module Net
1660
1730
  end
1661
1731
  end
1662
1732
 
1663
- # 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]
1664
1734
  # and returns the status of the indicated +mailbox+. +attr+ is a list of one
1665
- # or more attributes whose statuses are to be requested. Supported
1666
- # attributes include:
1735
+ # or more attributes whose statuses are to be requested.
1736
+ #
1737
+ # The return value is a hash of attributes. Most status attributes return
1738
+ # integer values, but some return other value types (documented below).
1739
+ #
1740
+ # A Net::IMAP::NoResponseError is raised if status values
1741
+ # for +mailbox+ cannot be returned; for instance, because it
1742
+ # does not exist.
1743
+ #
1744
+ # ===== Supported attributes
1745
+ #
1746
+ # +MESSAGES+:: The number of messages in the mailbox.
1747
+ #
1748
+ # +UIDNEXT+:: The next unique identifier value of the mailbox.
1749
+ #
1750
+ # +UIDVALIDITY+:: The unique identifier validity value of the mailbox.
1751
+ #
1752
+ # +UNSEEN+:: The number of messages without the <tt>\Seen</tt> flag.
1667
1753
  #
1668
- # MESSAGES:: the number of messages in the mailbox.
1669
- # RECENT:: the number of recent messages in the mailbox.
1670
- # UNSEEN:: the number of unseen messages in the mailbox.
1754
+ # +DELETED+:: The number of messages with the <tt>\Deleted</tt> flag.
1671
1755
  #
1672
- # The return value is a hash of attributes. For example:
1756
+ # +SIZE+::
1757
+ # The approximate size of the mailbox---must be greater than or equal to
1758
+ # the sum of all messages' +RFC822.SIZE+ fetch item values.
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
+ #
1764
+ # +MAILBOXID+::
1765
+ # A server-allocated unique _string_ identifier for the mailbox. See
1766
+ # +OBJECTID+ {[RFC8474]}[https://www.rfc-editor.org/rfc/rfc8474.html].
1767
+ #
1768
+ # +RECENT+::
1769
+ # The number of messages with the <tt>\Recent</tt> flag.
1770
+ # _NOTE:_ +RECENT+ was removed from IMAP4rev2.
1771
+ #
1772
+ # Unsupported attributes may be requested. The attribute value will be
1773
+ # either an Integer or an ExtensionData object.
1774
+ #
1775
+ # ===== For example:
1673
1776
  #
1674
1777
  # p imap.status("inbox", ["MESSAGES", "RECENT"])
1675
1778
  # #=> {"RECENT"=>0, "MESSAGES"=>44}
1676
1779
  #
1677
- # A Net::IMAP::NoResponseError is raised if status values
1678
- # for +mailbox+ cannot be returned; for instance, because it
1679
- # does not exist.
1780
+ # ===== Capabilities
1781
+ #
1782
+ # +SIZE+ requires the server's capabilities to include either +IMAP4rev2+ or
1783
+ # <tt>STATUS=SIZE</tt>
1784
+ # {[RFC8483]}[https://www.rfc-editor.org/rfc/rfc8483.html].
1785
+ #
1786
+ # +DELETED+ requires the server's capabilities to include +IMAP4rev2+.
1787
+ #
1788
+ # +HIGHESTMODSEQ+ requires the server's capabilities to include +CONDSTORE+
1789
+ # {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html].
1790
+ #
1791
+ # +MAILBOXID+ requires the server's capabilities to include +OBJECTID+
1792
+ # {[RFC8474]}[https://www.rfc-editor.org/rfc/rfc8474.html].
1680
1793
  def status(mailbox, attr)
1681
1794
  synchronize do
1682
1795
  send_command("STATUS", mailbox, attr)
@@ -1811,6 +1924,10 @@ module Net
1811
1924
  # string holding the entire search string, or a single-dimension array of
1812
1925
  # search keywords and arguments.
1813
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
+ #
1814
1931
  # Related: #uid_search
1815
1932
  #
1816
1933
  # ===== Search criteria
@@ -1859,6 +1976,15 @@ module Net
1859
1976
  # p imap.search(["SUBJECT", "hello", "NOT", "NEW"])
1860
1977
  # #=> [1, 6, 7, 8]
1861
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
1862
1988
  def search(keys, charset = nil)
1863
1989
  return search_internal("SEARCH", keys, charset)
1864
1990
  end
@@ -1867,11 +1993,18 @@ module Net
1867
1993
  # to search the mailbox for messages that match the given searching
1868
1994
  # criteria, and returns unique identifiers (<tt>UID</tt>s).
1869
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
+ #
1870
2000
  # See #search for documentation of search criteria.
1871
2001
  def uid_search(keys, charset = nil)
1872
2002
  return search_internal("UID SEARCH", keys, charset)
1873
2003
  end
1874
2004
 
2005
+ # :call-seq:
2006
+ # fetch(set, attr, changedsince: nil) -> array of FetchData
2007
+ #
1875
2008
  # Sends a {FETCH command [IMAP4rev1 §6.4.5]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.5]
1876
2009
  # to retrieve data associated with a message in the mailbox.
1877
2010
  #
@@ -1887,6 +2020,9 @@ module Net
1887
2020
  # +attr+ is a list of attributes to fetch; see the documentation
1888
2021
  # for FetchData for a list of valid attributes.
1889
2022
  #
2023
+ # +changedsince+ is an optional integer mod-sequence. It limits results to
2024
+ # messages with a mod-sequence greater than +changedsince+.
2025
+ #
1890
2026
  # The return value is an array of FetchData.
1891
2027
  #
1892
2028
  # Related: #uid_search, FetchData
@@ -1908,10 +2044,23 @@ module Net
1908
2044
  # #=> "12-Oct-2000 22:40:59 +0900"
1909
2045
  # p data.attr["UID"]
1910
2046
  # #=> 98
1911
- def fetch(set, attr, mod = nil)
1912
- 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)
1913
2059
  end
1914
2060
 
2061
+ # :call-seq:
2062
+ # uid_fetch(set, attr, changedsince: nil) -> array of FetchData
2063
+ #
1915
2064
  # Sends a {UID FETCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
1916
2065
  # to retrieve data associated with a message in the mailbox.
1917
2066
  #
@@ -1924,17 +2073,36 @@ module Net
1924
2073
  # whether a +UID+ was specified as a message data item to the +FETCH+.
1925
2074
  #
1926
2075
  # Related: #fetch, FetchData
1927
- def uid_fetch(set, attr, mod = nil)
1928
- 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)
1929
2081
  end
1930
2082
 
2083
+ # :call-seq:
2084
+ # store(set, attr, value, unchangedsince: nil) -> array of FetchData
2085
+ #
1931
2086
  # Sends a {STORE command [IMAP4rev1 §6.4.6]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.6]
1932
2087
  # to alter data associated with messages in the mailbox, in particular their
1933
- # flags. The +set+ parameter is a number, an array of numbers, or a Range
1934
- # object. Each number is a message sequence number. +attr+ is the name of a
1935
- # data item to store: <tt>"FLAGS"</tt> will replace the message's flag list
1936
- # with the provided one, <tt>"+FLAGS"</tt> will add the provided flags, and
1937
- # <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.
1938
2106
  #
1939
2107
  # The return value is an array of FetchData.
1940
2108
  #
@@ -1943,13 +2111,25 @@ module Net
1943
2111
  # ===== For example:
1944
2112
  #
1945
2113
  # p imap.store(6..8, "+FLAGS", [:Deleted])
1946
- # #=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\
1947
- # #<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]}>,
1948
2116
  # #<Net::IMAP::FetchData seqno=8, attr={"FLAGS"=>[:Seen, :Deleted]}>]
1949
- def store(set, attr, flags)
1950
- 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)
1951
2128
  end
1952
2129
 
2130
+ # :call-seq:
2131
+ # uid_store(set, attr, value, unchangedsince: nil) -> array of FetchData
2132
+ #
1953
2133
  # Sends a {UID STORE command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
1954
2134
  # to alter data associated with messages in the mailbox, in particular their
1955
2135
  # flags.
@@ -1958,8 +2138,11 @@ module Net
1958
2138
  # message sequence numbers.
1959
2139
  #
1960
2140
  # Related: #store
1961
- def uid_store(set, attr, flags)
1962
- 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)
1963
2146
  end
1964
2147
 
1965
2148
  # Sends a {COPY command [IMAP4rev1 §6.4.7]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.7]
@@ -2135,6 +2318,13 @@ module Net
2135
2318
  # each enabled extension (usually the same name as the enabled extension).
2136
2319
  # The following capabilities may be enabled:
2137
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
+ #
2138
2328
  # [+:utf8+ --- an alias for <tt>"UTF8=ACCEPT"</tt>]
2139
2329
  #
2140
2330
  # In a future release, <tt>enable(:utf8)</tt> will enable either
@@ -2646,7 +2836,11 @@ module Net
2646
2836
  end
2647
2837
  end
2648
2838
 
2649
- 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
2650
2844
  case attr
2651
2845
  when String then
2652
2846
  attr = RawData.new(attr)
@@ -2667,13 +2861,14 @@ module Net
2667
2861
  end
2668
2862
  end
2669
2863
 
2670
- def store_internal(cmd, set, attr, flags)
2671
- if attr.instance_of?(String)
2672
- attr = RawData.new(attr)
2673
- 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
2674
2869
  synchronize do
2675
2870
  clear_responses("FETCH")
2676
- send_command(cmd, MessageSet.new(set), attr, flags)
2871
+ send_command(cmd, *args)
2677
2872
  clear_responses("FETCH")
2678
2873
  end
2679
2874
  end
@@ -2688,7 +2883,6 @@ module Net
2688
2883
  else
2689
2884
  normalize_searching_criteria(search_keys)
2690
2885
  end
2691
- normalize_searching_criteria(search_keys)
2692
2886
  synchronize do
2693
2887
  send_command(cmd, sort_keys, charset, *search_keys)
2694
2888
  clear_responses("SORT").last || []
@@ -2701,7 +2895,6 @@ module Net
2701
2895
  else
2702
2896
  normalize_searching_criteria(search_keys)
2703
2897
  end
2704
- normalize_searching_criteria(search_keys)
2705
2898
  synchronize do
2706
2899
  send_command(cmd, algorithm, charset, *search_keys)
2707
2900
  clear_responses("THREAD").last || []
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.
@@ -17,11 +17,6 @@ BENCHMARK_INIT = <<RUBY
17
17
  parser = Net::IMAP::ResponseParser.new
18
18
  RUBY
19
19
 
20
- PER_BENCHMARK_PRELUDE = <<RUBY
21
- response = load_response(%p,
22
- %p)
23
- RUBY
24
-
25
20
  file "benchmarks/parser.yml" => PARSER_TEST_FIXTURES do |t|
26
21
  require "yaml"
27
22
  require "pathname"
@@ -31,7 +26,7 @@ file "benchmarks/parser.yml" => PARSER_TEST_FIXTURES do |t|
31
26
  files = path.glob("*.yml")
32
27
  tests = files.flat_map {|file|
33
28
  file.read
34
- .gsub(%r{([-:]) !ruby/struct:\S+}) { $1 }
29
+ .gsub(%r{([-:]) !ruby/(object|struct):\S+}) { $1 }
35
30
  .then {
36
31
  YAML.safe_load(_1, filename: file,
37
32
  permitted_classes: [Symbol, Regexp], aliases: true)
@@ -42,14 +37,12 @@ file "benchmarks/parser.yml" => PARSER_TEST_FIXTURES do |t|
42
37
  test.key?(:expected) ? :parser_assert_equal : :parser_pending
43
38
  }
44
39
  }
45
- .map {|test_name, _|
46
- [file.relative_path_from(__dir__).to_s, test_name.to_s]
47
- }
40
+ .map {|test_name, test| [test_name.to_s, test.fetch(:response)] }
48
41
  }
49
42
 
50
- benchmarks = tests.map {|file, fixture_name|
43
+ benchmarks = tests.map {|fixture_name, response|
51
44
  {"name" => fixture_name.delete_prefix("test_"),
52
- "prelude" => PER_BENCHMARK_PRELUDE % [file, fixture_name],
45
+ "prelude" => "response = -%s.b" % [response.dump],
53
46
  "script" => "parser.parse(response)"}
54
47
  }
55
48
  .sort_by { _1["name"] }
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.4
4
+ version: 0.4.9
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-03 00:00:00.000000000 Z
12
+ date: 2023-12-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: net-protocol
@@ -90,6 +90,7 @@ files:
90
90
  - lib/net/imap/data_encoding.rb
91
91
  - lib/net/imap/deprecated_client_options.rb
92
92
  - lib/net/imap/errors.rb
93
+ - lib/net/imap/fetch_data.rb
93
94
  - lib/net/imap/flags.rb
94
95
  - lib/net/imap/response_data.rb
95
96
  - lib/net/imap/response_parser.rb
@@ -112,6 +113,8 @@ files:
112
113
  - lib/net/imap/sasl/stringprep.rb
113
114
  - lib/net/imap/sasl/xoauth2_authenticator.rb
114
115
  - lib/net/imap/sasl_adapter.rb
116
+ - lib/net/imap/search_result.rb
117
+ - lib/net/imap/sequence_set.rb
115
118
  - lib/net/imap/stringprep.rb
116
119
  - lib/net/imap/stringprep/nameprep.rb
117
120
  - lib/net/imap/stringprep/saslprep.rb
@@ -131,6 +134,7 @@ licenses:
131
134
  metadata:
132
135
  homepage_uri: https://github.com/ruby/net-imap
133
136
  source_code_uri: https://github.com/ruby/net-imap
137
+ changelog_uri: https://github.com/ruby/net-imap/releases
134
138
  post_install_message:
135
139
  rdoc_options: []
136
140
  require_paths:
@@ -146,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
150
  - !ruby/object:Gem::Version
147
151
  version: '0'
148
152
  requirements: []
149
- rubygems_version: 3.4.10
153
+ rubygems_version: 3.4.22
150
154
  signing_key:
151
155
  specification_version: 4
152
156
  summary: Ruby client api for Internet Message Access Protocol