@ -51,28 +51,30 @@ impl ImapOp {
}
}
}
}
impl BackendOp for ImapOp {
impl ImapOp {
fn as_bytes ( & self ) -> ResultFuture < Vec < u8 > > {
async fn fetch ( self ) -> Result < Vec < u8 > > {
let connection = self . connection . clone ( ) ;
let mailbox_hash = self . mailbox_hash ;
let uid = self . uid ;
let uid_store = self . uid_store . clone ( ) ;
Ok ( Box ::pin ( async move {
let exists_in_cache = {
let mut bytes_cache = uid_store . byte_cache . lock ( ) ? ;
let cache = bytes_cache . entry ( uid ) . or_default ( ) ;
cache . bytes . is_some ( )
} ;
if ! exists_in_cache {
let mut response = Vec ::with_capacity ( 8 * 1024 ) ;
let mut response = Vec ::with_capacity ( 8 * 1024 ) ;
let mut use_body = false ;
let ( _uid , _flags , body ) = loop {
{
{
let mut conn = timeout ( uid_store . timeout , connection . lock ( ) ) . await ? ;
let mut conn = timeout ( self . uid_store . timeout , self . connection . lock ( ) ) . await ? ;
conn . connect ( ) . await ? ;
conn . connect ( ) . await ? ;
conn . examine_mailbox ( mailbox_hash , & mut response , false )
conn . examine_mailbox ( self . mailbox_hash , & mut response , false )
. await ? ;
. await ? ;
conn . send_command ( CommandBody ::fetch (
conn . send_command ( CommandBody ::fetch (
uid ,
self . uid ,
vec! [ MessageDataItemName ::Flags , MessageDataItemName ::Rfc822 ] ,
vec! [
MessageDataItemName ::Flags ,
if use_body {
MessageDataItemName ::BodyExt {
section : None ,
partial : None ,
peek : false ,
}
} else {
MessageDataItemName ::Rfc822
} ,
] ,
true ,
true ,
) ? )
) ? )
. await ? ;
. await ? ;
@ -88,7 +90,7 @@ impl BackendOp for ImapOp {
if results . len ( ) > 1 {
if results . len ( ) > 1 {
return Err (
return Err (
Error ::new ( format! ( "Invalid/unexpected response: {:?}" , response ) )
Error ::new ( format! ( "Invalid/unexpected response: {:?}" , response ) )
. set_summary ( format! ( "Message with UID {} was not found." , uid ) )
. set_summary ( format! ( "Message with UID {} was not found." , self . uid ) )
. set_kind ( ErrorKind ::ProtocolError ) ,
. set_kind ( ErrorKind ::ProtocolError ) ,
) ;
) ;
}
}
@ -100,7 +102,7 @@ impl BackendOp for ImapOp {
// without any data or a UID COPY or UID STORE to return an OK without
// without any data or a UID COPY or UID STORE to return an OK without
// performing any operations.
// performing any operations.
return Err ( Error ::new ( "Not found" )
return Err ( Error ::new ( "Not found" )
. set_summary ( format! ( "Message with UID {} was not found." , uid ) )
. set_summary ( format! ( "Message with UID {} was not found." , self . uid ) )
. set_kind ( ErrorKind ::NotFound ) ) ;
. set_kind ( ErrorKind ::NotFound ) ) ;
} ;
} ;
let FetchResponse {
let FetchResponse {
@ -110,30 +112,59 @@ impl BackendOp for ImapOp {
..
..
} = fetch_response
} = fetch_response
else {
else {
if ! use_body {
use_body = true ;
continue ;
}
return Err ( Error ::new ( "Invalid/unexpected response from server" )
return Err ( Error ::new ( "Invalid/unexpected response from server" )
. set_summary ( format! ( "Message with UID {} was not found." , uid ) )
. set_summary ( format! ( "Message with UID {} was not found." , self . uid ) )
. set_details ( format! ( "Full response: {:?}" , fetch_response ) )
. set_details ( format! ( "Full response: {:?}" , fetch_response ) )
. set_kind ( ErrorKind ::ProtocolError ) ) ;
. set_kind ( ErrorKind ::ProtocolError ) ) ;
} ;
} ;
if _uid ! = uid {
break ( _uid , _flags , body ) ;
} ;
if _uid ! = self . uid {
return Err ( Error ::new ( "Invalid/unexpected response from server" )
return Err ( Error ::new ( "Invalid/unexpected response from server" )
. set_summary ( format! ( "Message with UID {} was not found." , uid ) )
. set_summary ( format! ( "Message with UID {} was not found." , self . uid ) )
. set_details ( format! (
. set_details ( format! (
" Requested UID { } but UID FETCH response was for UID { } . Full \
"Requested UID {} but UID FETCH response was for UID {}. Full response: {:?}" ,
response : { :? } " ,
self . uid ,
uid ,
_uid ,
_uid ,
String ::from_utf8_lossy ( & response )
String ::from_utf8_lossy ( & response )
) )
) )
. set_kind ( ErrorKind ::ProtocolError ) ) ;
. set_kind ( ErrorKind ::ProtocolError ) ) ;
}
}
let mut bytes_cache = uid_store . byte_cache . lock ( ) ? ;
let mut bytes_cache = self . uid_store . byte_cache . lock ( ) ? ;
let cache = bytes_cache . entry ( uid ) . or_default ( ) ;
let cache = bytes_cache . entry ( self . uid ) . or_default ( ) ;
if let Some ( ( _flags , _ ) ) = _flags {
if let Some ( ( _flags , _ ) ) = _flags {
cache . flags = Some ( _flags ) ;
cache . flags = Some ( _flags ) ;
}
}
cache . bytes = Some ( body . to_vec ( ) ) ;
cache . bytes = Some ( body . to_vec ( ) ) ;
return Ok ( body . to_vec ( ) ) ;
Ok ( body . to_vec ( ) )
}
}
impl BackendOp for ImapOp {
fn as_bytes ( & self ) -> ResultFuture < Vec < u8 > > {
let connection = self . connection . clone ( ) ;
let mailbox_hash = self . mailbox_hash ;
let uid = self . uid ;
let uid_store = self . uid_store . clone ( ) ;
Ok ( Box ::pin ( async move {
let exists_in_cache = {
let mut bytes_cache = uid_store . byte_cache . lock ( ) ? ;
let cache = bytes_cache . entry ( uid ) . or_default ( ) ;
cache . bytes . is_some ( )
} ;
if ! exists_in_cache {
return Self {
connection ,
mailbox_hash ,
uid ,
uid_store ,
}
. fetch ( )
. await ;
}
}
let mut bytes_cache = uid_store . byte_cache . lock ( ) ? ;
let mut bytes_cache = uid_store . byte_cache . lock ( ) ? ;
let cache = bytes_cache . entry ( uid ) . or_default ( ) ;
let cache = bytes_cache . entry ( uid ) . or_default ( ) ;