@@ -2647,6 +2647,7 @@ def fetch(...)
26472647
26482648 # :call-seq:
26492649 # uid_fetch(set, attr, changedsince: nil, partial: nil) -> array of FetchData (or UIDFetchData)
2650+ # uid_fetch(set, attr, changedsince:, vanished: true, partial: nil) -> array of VanishedData and FetchData (or UIDFetchData)
26502651 #
26512652 # Sends a {UID FETCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
26522653 # to retrieve data associated with a message in the mailbox.
@@ -2663,6 +2664,22 @@ def fetch(...)
26632664 #
26642665 # +changedsince+ (optional) behaves the same as with #fetch.
26652666 #
2667+ # +vanished+ can be used to request a list all of the message UIDs in +set+
2668+ # that have been expunged since +changedsince+. Setting +vanished+ to true
2669+ # prepends a VanishedData object to the returned array. If the server does
2670+ # not return a +VANISHED+ response, an empty VanishedData object will still
2671+ # be added.
2672+ # <em>The +QRESYNC+ capabability must be enabled.</em>
2673+ # {[RFC7162]}[https://rfc-editor.org/rfc/rfc7162]
2674+ #
2675+ # For example:
2676+ #
2677+ # imap.enable("QRESYNC") # must enable before selecting the mailbox
2678+ # imap.select("INBOX")
2679+ # # first value in the array is VanishedData
2680+ # vanished, *fetched = imap.uid_fetch(301..500, %w[flags],
2681+ # changedsince: 12345, vanished: true)
2682+ #
26662683 # +partial+ is an optional range to limit the number of results returned.
26672684 # It's useful when +set+ contains an unknown number of messages.
26682685 # <tt>1..500</tt> returns the first 500 messages in +set+ (in mailbox
@@ -2695,6 +2712,9 @@ def fetch(...)
26952712 #
26962713 # ==== Capabilities
26972714 #
2715+ # QRESYNC[https://www.rfc-editor.org/rfc/rfc7162] must be enabled in order
2716+ # to use the +vanished+ fetch modifier.
2717+ #
26982718 # The server's capabilities must include +PARTIAL+
26992719 # {[RFC9394]}[https://rfc-editor.org/rfc/rfc9394] in order to use the
27002720 # +partial+ argument.
@@ -2974,7 +2994,6 @@ def uid_thread(algorithm, search_keys, charset)
29742994 # See {[RFC7162 §3.1]}[https://www.rfc-editor.org/rfc/rfc7162.html#section-3.1].
29752995 #
29762996 # [+QRESYNC+ {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html]]
2977- # *NOTE:* The +QRESYNC+ argument to #uid_fetch is not supported yet.
29782997 #
29792998 # Adds quick resynchronization options to #select, #examine, and
29802999 # #uid_fetch. +QRESYNC+ _must_ be explicitly enabled before using any of
@@ -3707,19 +3726,23 @@ def search_internal(cmd, ...)
37073726 end
37083727 end
37093728
3710- def fetch_internal ( cmd , set , attr , mod = nil , partial : nil , changedsince : nil )
3711- if partial && !cmd . start_with? ( "UID " )
3729+ def fetch_internal ( cmd , set , attr , mod = nil ,
3730+ partial : nil ,
3731+ changedsince : nil ,
3732+ vanished : false )
3733+ if cmd . start_with? ( "UID " )
3734+ if vanished && !changedsince
3735+ raise ArgumentError , "vanished must be used with changedsince"
3736+ end
3737+ elsif vanished
3738+ raise ArgumentError , "vanished can only be used with uid_fetch"
3739+ elsif partial
37123740 raise ArgumentError , "partial can only be used with uid_fetch"
37133741 end
37143742 set = SequenceSet [ set ]
3715- if partial
3716- mod ||= [ ]
3717- mod << "PARTIAL" << PartialRange [ partial ]
3718- end
3719- if changedsince
3720- mod ||= [ ]
3721- mod << "CHANGEDSINCE" << Integer ( changedsince )
3722- end
3743+ ( mod ||= [ ] ) << "PARTIAL" << PartialRange [ partial ] if partial
3744+ ( mod ||= [ ] ) << "CHANGEDSINCE" << Integer ( changedsince ) if changedsince
3745+ ( mod ||= [ ] ) << "VANISHED" if vanished
37233746 case attr
37243747 when String then
37253748 attr = RawData . new ( attr )
@@ -3731,7 +3754,7 @@ def fetch_internal(cmd, set, attr, mod = nil, partial: nil, changedsince: nil)
37313754
37323755 args = [ cmd , set , attr ]
37333756 args << mod if mod
3734- send_command_returning_fetch_results ( *args )
3757+ send_command_returning_fetch_results ( *args , vanished : )
37353758 end
37363759
37373760 def store_internal ( cmd , set , attr , flags , unchangedsince : nil )
@@ -3742,14 +3765,20 @@ def store_internal(cmd, set, attr, flags, unchangedsince: nil)
37423765 send_command_returning_fetch_results ( cmd , *args )
37433766 end
37443767
3745- def send_command_returning_fetch_results ( ... )
3768+ def send_command_returning_fetch_results ( * args , vanished : false )
37463769 synchronize do
37473770 clear_responses ( "FETCH" )
37483771 clear_responses ( "UIDFETCH" )
3749- send_command ( ... )
3772+ send_command ( * args )
37503773 fetches = clear_responses ( "FETCH" )
37513774 uidfetches = clear_responses ( "UIDFETCH" )
3752- uidfetches . any? ? uidfetches : fetches
3775+ fetches = uidfetches if uidfetches . any?
3776+ if vanished
3777+ vanished = extract_responses ( "VANISHED" , &:earlier? ) . last ||
3778+ VanishedData [ uids : SequenceSet . empty , earlier : true ]
3779+ fetches = [ vanished , *fetches ] . freeze
3780+ end
3781+ fetches
37533782 end
37543783 end
37553784
0 commit comments