net-imap 0.4.4 → 0.4.9

Sign up to get free protection for your applications and to get access to all the features.
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