@@ -2632,6 +2632,7 @@ def fetch(...)
26322632
26332633 # :call-seq:
26342634 # uid_fetch(set, attr, changedsince: nil, partial: nil) -> array of FetchData (or UIDFetchData)
2635+ # uid_fetch(set, attr, changedsince:, vanished: true, partial: nil) -> array of VanishedData and FetchData (or UIDFetchData)
26352636 #
26362637 # Sends a {UID FETCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
26372638 # to retrieve data associated with a message in the mailbox.
@@ -2648,6 +2649,22 @@ def fetch(...)
26482649 #
26492650 # +changedsince+ (optional) behaves the same as with #fetch.
26502651 #
2652+ # +vanished+ can be used to request a list all of the message UIDs in +set+
2653+ # that have been expunged since +changedsince+. Setting +vanished+ to true
2654+ # prepends a VanishedData object to the returned array. If the server does
2655+ # not return a +VANISHED+ response, an empty VanishedData object will still
2656+ # be added.
2657+ # <em>The +QRESYNC+ capabability must be enabled.</em>
2658+ # {[RFC7162]}[https://rfc-editor.org/rfc/rfc7162]
2659+ #
2660+ # For example:
2661+ #
2662+ # imap.enable("QRESYNC") # must enable before selecting the mailbox
2663+ # imap.select("INBOX")
2664+ # # first value in the array is VanishedData
2665+ # vanished, *fetched = imap.uid_fetch(301..500, %w[flags],
2666+ # changedsince: 12345, vanished: true)
2667+ #
26512668 # +partial+ is an optional range to limit the number of results returned.
26522669 # It's useful when +set+ contains an unknown number of messages.
26532670 # <tt>1..500</tt> returns the first 500 messages in +set+ (in mailbox
@@ -2680,6 +2697,9 @@ def fetch(...)
26802697 #
26812698 # ==== Capabilities
26822699 #
2700+ # QRESYNC[https://www.rfc-editor.org/rfc/rfc7162] must be enabled in order
2701+ # to use the +vanished+ fetch modifier.
2702+ #
26832703 # The server's capabilities must include +PARTIAL+
26842704 # {[RFC9394]}[https://rfc-editor.org/rfc/rfc9394] in order to use the
26852705 # +partial+ argument.
@@ -2959,9 +2979,8 @@ def uid_thread(algorithm, search_keys, charset)
29592979 # See {[RFC7162 §3.1]}[https://www.rfc-editor.org/rfc/rfc7162.html#section-3.1].
29602980 #
29612981 # [+QRESYNC+ {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html]]
2962- # *NOTE:* Enabling QRESYNC will replace +EXPUNGE+ with +VANISHED+, but
2963- # the extension arguments to #select, #examine, and #uid_fetch are not
2964- # supported yet.
2982+ # *NOTE:* The +QRESYNC+ argument to #select and #examine is not supported
2983+ # yet.
29652984 #
29662985 # Adds quick resynchronization options to #select, #examine, and
29672986 # #uid_fetch. +QRESYNC+ _must_ be explicitly enabled before using any of
@@ -3680,19 +3699,23 @@ def search_internal(cmd, ...)
36803699 end
36813700 end
36823701
3683- def fetch_internal ( cmd , set , attr , mod = nil , partial : nil , changedsince : nil )
3684- if partial && !cmd . start_with? ( "UID " )
3702+ def fetch_internal ( cmd , set , attr , mod = nil ,
3703+ partial : nil ,
3704+ changedsince : nil ,
3705+ vanished : false )
3706+ if cmd . start_with? ( "UID " )
3707+ if vanished && !changedsince
3708+ raise ArgumentError , "vanished must be used with changedsince"
3709+ end
3710+ elsif vanished
3711+ raise ArgumentError , "vanished can only be used with uid_fetch"
3712+ elsif partial
36853713 raise ArgumentError , "partial can only be used with uid_fetch"
36863714 end
36873715 set = SequenceSet [ set ]
3688- if partial
3689- mod ||= [ ]
3690- mod << "PARTIAL" << PartialRange [ partial ]
3691- end
3692- if changedsince
3693- mod ||= [ ]
3694- mod << "CHANGEDSINCE" << Integer ( changedsince )
3695- end
3716+ ( mod ||= [ ] ) << "PARTIAL" << PartialRange [ partial ] if partial
3717+ ( mod ||= [ ] ) << "CHANGEDSINCE" << Integer ( changedsince ) if changedsince
3718+ ( mod ||= [ ] ) << "VANISHED" if vanished
36963719 case attr
36973720 when String then
36983721 attr = RawData . new ( attr )
@@ -3704,7 +3727,7 @@ def fetch_internal(cmd, set, attr, mod = nil, partial: nil, changedsince: nil)
37043727
37053728 args = [ cmd , set , attr ]
37063729 args << mod if mod
3707- send_command_returning_fetch_results ( *args )
3730+ send_command_returning_fetch_results ( *args , vanished : )
37083731 end
37093732
37103733 def store_internal ( cmd , set , attr , flags , unchangedsince : nil )
@@ -3715,14 +3738,20 @@ def store_internal(cmd, set, attr, flags, unchangedsince: nil)
37153738 send_command_returning_fetch_results ( cmd , *args )
37163739 end
37173740
3718- def send_command_returning_fetch_results ( ... )
3741+ def send_command_returning_fetch_results ( * args , vanished : false )
37193742 synchronize do
37203743 clear_responses ( "FETCH" )
37213744 clear_responses ( "UIDFETCH" )
3722- send_command ( ... )
3745+ send_command ( * args )
37233746 fetches = clear_responses ( "FETCH" )
37243747 uidfetches = clear_responses ( "UIDFETCH" )
3725- uidfetches . any? ? uidfetches : fetches
3748+ fetches = uidfetches if uidfetches . any?
3749+ if vanished
3750+ vanished = extract_responses ( "VANISHED" , &:earlier? ) . last ||
3751+ VanishedData [ uids : SequenceSet . empty , earlier : true ]
3752+ fetches = [ vanished , *fetches ] . freeze
3753+ end
3754+ fetches
37263755 end
37273756 end
37283757
0 commit comments