Skip to content

Commit 38cfa66

Browse files
committed
✨ QRESYNC: Add qresync kwarg to #select/#examine [🚧 tests, validate args]
1 parent e5ab356 commit 38cfa66

File tree

1 file changed

+35
-11
lines changed

1 file changed

+35
-11
lines changed

lib/net/imap.rb

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,7 +1557,7 @@ def login(user, password)
15571557
end
15581558

15591559
# :call-seq:
1560-
# select(mailbox, **opts) -> result
1560+
# select(mailbox, condstore: false, qresync: nil) -> result
15611561
#
15621562
# Sends a {SELECT command [IMAP4rev1 §6.3.1]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.1]
15631563
# to select a +mailbox+ so that messages in the +mailbox+ can be accessed.
@@ -1572,8 +1572,29 @@ def login(user, password)
15721572
# When the +condstore+ keyword argument is true, the server is told to
15731573
# enable the extension. If +mailbox+ supports persistence of mod-sequences,
15741574
# the +HIGHESTMODSEQ+ ResponseCode will be sent as an untagged response to
1575-
# #select and all `FETCH` responses will include FetchData#modseq.
1575+
# #select and all +FETCH+ responses will include FetchStruct#modseq.
15761576
# Otherwise, the +NOMODSEQ+ ResponseCode will be sent.
1577+
# <em>Requires the +CONDSTORE+ capabability.</em>
1578+
# {[RFC7162]}[https://rfc-editor.org/rfc/rfc7162]
1579+
#
1580+
# imap.select("mbox", condstore: true)
1581+
# modseq = imap.responses("HIGHESTMODSEQ", &:last)
1582+
#
1583+
# The optional +qresync+ argument can provide quick resynchronization
1584+
# parameters: the last known UIDVALIDITY, the last known MODSEQ,
1585+
# known UIDs <em>(optional)</em>, and message sequence match data
1586+
# <em>(optional)</em>. When +qresync+ is provided, a SelectResult object
1587+
# is returned with +UIDVALIDITY+, +HIGHESTMODSEQ+, +VANISHED+, and +FETCH+
1588+
# results. Sending +qresync+ implicitly enables +condstore+, too.
1589+
# <em>Requires the +QRESYNC+ capabability.</em>
1590+
# {[RFC7162]}[https://rfc-editor.org/rfc/rfc7162]
1591+
#
1592+
# imap.enable("QRESYNC") # must enable before selecting the mailbox
1593+
# qresync = imap.select("INBOX", qresync: [uidvalidity, modseq, known_uids])
1594+
# qresync => { uidvalidity: ^uidvalidity, highestmodseq: modseq,
1595+
# vanished:, updated: }
1596+
# vanished.each do delete_message _1 end
1597+
# updated .each do update_message _1.uid, flags: _1.flags, modseq: _1.modseq end
15771598
#
15781599
# A Net::IMAP::NoResponseError is raised if the mailbox does not
15791600
# exist or is for some reason non-selectable.
@@ -1582,22 +1603,24 @@ def login(user, password)
15821603
#
15831604
# ==== Capabilities
15841605
#
1585-
# If [UIDPLUS[https://www.rfc-editor.org/rfc/rfc4315.html]] is supported,
1606+
# If either [UIDPLUS[https://www.rfc-editor.org/rfc/rfc4315.html]]
1607+
# or [IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051.html]] is supported,
15861608
# the server may return an untagged "NO" response with a "UIDNOTSTICKY"
15871609
# response code indicating that the mailstore does not support persistent
15881610
# UIDs:
15891611
# imap.responses("NO", &:last)&.code&.name == "UIDNOTSTICKY"
15901612
#
15911613
# If [CONDSTORE[https://www.rfc-editor.org/rfc/rfc7162.html]] is supported,
15921614
# the +condstore+ keyword parameter may be used.
1593-
# imap.select("mbox", condstore: true)
1594-
# modseq = imap.responses("HIGHESTMODSEQ", &:last)
1615+
#
1616+
# If [QRESYNC[https://www.rfc-editor.org/rfc/rfc7162.html]] is enabled,
1617+
# the +qresync+ keyword parameter may be used.
15951618
def select(...)
15961619
select_internal("SELECT", ...)
15971620
end
15981621

15991622
# :call-seq:
1600-
# examine(mailbox, **opts) -> result
1623+
# examine(mailbox, condstore: false, qresync: nil) -> result
16011624
#
16021625
# Sends a {EXAMINE command [IMAP4rev1 §6.3.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.2]
16031626
# to select a +mailbox+ so that messages in the +mailbox+ can be accessed.
@@ -2951,9 +2974,7 @@ def uid_thread(algorithm, search_keys, charset)
29512974
# See {[RFC7162 §3.1]}[https://www.rfc-editor.org/rfc/rfc7162.html#section-3.1].
29522975
#
29532976
# [+QRESYNC+ {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html]]
2954-
# *NOTE:* Enabling QRESYNC will replace +EXPUNGE+ with +VANISHED+, but
2955-
# the extension arguments to #select, #examine, and #uid_fetch are not
2956-
# supported yet.
2977+
# *NOTE:* The +QRESYNC+ argument to #uid_fetch is not supported yet.
29572978
#
29582979
# Adds quick resynchronization options to #select, #examine, and
29592980
# #uid_fetch. +QRESYNC+ _must_ be explicitly enabled before using any of
@@ -3577,9 +3598,12 @@ def enforce_logindisabled?
35773598
end
35783599
end
35793600

3580-
def select_internal(command, mailbox, condstore: false)
3601+
def select_internal(command, mailbox, condstore: false, qresync: nil)
35813602
args = [command, mailbox]
3582-
args << ["CONDSTORE"] if condstore
3603+
params = []
3604+
params << "CONDSTORE" if condstore
3605+
params << "QRESYNC" << qresync if qresync # TODO: validate qresync params
3606+
args << params unless params.empty?
35833607
synchronize do
35843608
state_unselected! # implicitly closes current mailbox
35853609
@responses.clear

0 commit comments

Comments
 (0)