@ -24,8 +24,8 @@ use smallvec::SmallVec;
#[ macro_use ]
mod protocol_parser ;
pub use protocol_parser ::{ UntaggedResponse ::* , * } ;
mod folder ;
pub use folder ::* ;
mod mailbox ;
pub use mailbox ::* ;
mod operations ;
pub use operations ::* ;
mod connection ;
@ -35,10 +35,10 @@ pub use watch::*;
use crate ::async_workers ::{ Async , AsyncBuilder , AsyncStatus , WorkContext } ;
use crate ::backends ::BackendOp ;
use crate ::backends ::Folder Hash;
use crate ::backends ::Mailbox Hash;
use crate ::backends ::RefreshEvent ;
use crate ::backends ::RefreshEventKind ::{ self , * } ;
use crate ::backends ::{ BackendFolder , Folder , MailBackend , RefreshEventConsumer } ;
use crate ::backends ::{ BackendMailbox , MailBackend , Mailbox , RefreshEventConsumer } ;
use crate ::conf ::AccountSettings ;
use crate ::email ::* ;
use crate ::error ::{ MeliError , Result } ;
@ -117,8 +117,8 @@ macro_rules! get_conf_val {
#[ derive(Debug) ]
pub struct UIDStore {
uidvalidity : Arc < Mutex < FnvHashMap < Folder Hash, UID > > > ,
hash_index : Arc < Mutex < FnvHashMap < EnvelopeHash , ( UID , Folder Hash) > > > ,
uidvalidity : Arc < Mutex < FnvHashMap < Mailbox Hash, UID > > > ,
hash_index : Arc < Mutex < FnvHashMap < EnvelopeHash , ( UID , Mailbox Hash) > > > ,
uid_index : Arc < Mutex < FnvHashMap < UID , EnvelopeHash > > > ,
byte_cache : Arc < Mutex < FnvHashMap < UID , EnvelopeCache > > > ,
@ -134,7 +134,7 @@ pub struct ImapType {
can_create_flags : Arc < Mutex < bool > > ,
tag_index : Arc < RwLock < BTreeMap < u64 , String > > > ,
folder s : Arc < RwLock < FnvHashMap < FolderHash , ImapFolder > > > ,
mailboxe s : Arc < RwLock < FnvHashMap < MailboxHash , ImapMailbox > > > ,
}
impl MailBackend for ImapType {
@ -152,16 +152,16 @@ impl MailBackend for ImapType {
}
}
fn get ( & mut self , folder : & Folder ) -> Async < Result < Vec < Envelope > > > {
fn get ( & mut self , mailbox : & Mailbox ) -> Async < Result < Vec < Envelope > > > {
let mut w = AsyncBuilder ::new ( ) ;
let handle = {
let tx = w . tx ( ) ;
let uid_store = self . uid_store . clone ( ) ;
let tag_index = self . tag_index . clone ( ) ;
let can_create_flags = self . can_create_flags . clone ( ) ;
let folder _hash = folder . hash ( ) ;
let ( permissions , folder_path , folder _exists, no_select , unseen ) = {
let f = & self . folder s. read ( ) . unwrap ( ) [ & folder _hash] ;
let mailbox _hash = mailbox . hash ( ) ;
let ( permissions , mailbox_path , mailbox _exists, no_select , unseen ) = {
let f = & self . mailboxe s. read ( ) . unwrap ( ) [ & mailbox _hash] ;
(
f . permissions . clone ( ) ,
f . imap_path ( ) . to_string ( ) ,
@ -182,24 +182,24 @@ impl MailBackend for ImapType {
let tx = _tx ;
let mut response = String ::with_capacity ( 8 * 1024 ) ;
let mut conn = connection . lock ( ) ? ;
debug ! ( "locked for get {}" , folder _path) ;
debug ! ( "locked for get {}" , mailbox _path) ;
/* first SELECT the mailbox to get READ / WRITE permissions (because EXAMINE only
* returns READ - ONLY for both cases ) * /
conn . send_command ( format ! ( "SELECT \"{}\"" , folder _path) . as_bytes ( ) ) ? ;
conn . send_command ( format ! ( "SELECT \"{}\"" , mailbox _path) . as_bytes ( ) ) ? ;
conn . read_response ( & mut response ) ? ;
let examine_response = protocol_parser ::select_response ( & response ) ? ;
* can_create_flags . lock ( ) . unwrap ( ) = examine_response . can_create_flags ;
debug ! (
"folder : {} examine_response: {:?}" ,
folder _path, examine_response
"mailbox : {} examine_response: {:?}" ,
mailbox _path, examine_response
) ;
let mut exists : usize = examine_response . uidnext - 1 ;
{
let mut uidvalidities = uid_store . uidvalidity . lock ( ) . unwrap ( ) ;
let v = uidvalidities
. entry ( folder _hash)
. entry ( mailbox _hash)
. or_insert ( examine_response . uidvalidity ) ;
* v = examine_response . uidvalidity ;
@ -210,11 +210,11 @@ impl MailBackend for ImapType {
permissions . rename_messages = ! examine_response . read_only ;
permissions . delete_messages = ! examine_response . read_only ;
permissions . delete_messages = ! examine_response . read_only ;
let mut folder _exists = folder _exists. lock ( ) . unwrap ( ) ;
* folder _exists = exists ;
let mut mailbox _exists = mailbox _exists. lock ( ) . unwrap ( ) ;
* mailbox _exists = exists ;
}
/* reselecting the same mailbox with EXAMINE prevents expunging it */
conn . send_command ( format ! ( "EXAMINE \"{}\"" , folder _path) . as_bytes ( ) ) ? ;
conn . send_command ( format ! ( "EXAMINE \"{}\"" , mailbox _path) . as_bytes ( ) ) ? ;
conn . read_response ( & mut response ) ? ;
let mut tag_lck = tag_index . write ( ) . unwrap ( ) ;
@ -247,7 +247,7 @@ impl MailBackend for ImapType {
let mut env = envelope . unwrap ( ) ;
let mut h = DefaultHasher ::new ( ) ;
h . write_usize ( uid ) ;
h . write ( folder _path. as_bytes ( ) ) ;
h . write ( mailbox _path. as_bytes ( ) ) ;
env . set_hash ( h . finish ( ) ) ;
if let Some ( ( flags , keywords ) ) = flags {
if ! flags . contains ( Flag ::SEEN ) {
@ -266,7 +266,7 @@ impl MailBackend for ImapType {
. hash_index
. lock ( )
. unwrap ( )
. insert ( env . hash ( ) , ( uid , folder _hash) ) ;
. insert ( env . hash ( ) , ( uid , mailbox _hash) ) ;
uid_store . uid_index . lock ( ) . unwrap ( ) . insert ( uid , env . hash ( ) ) ;
envelopes . push ( env ) ;
}
@ -290,15 +290,15 @@ impl MailBackend for ImapType {
fn refresh (
& mut self ,
folder_hash : Folder Hash,
mailbox_hash : Mailbox Hash,
sender : RefreshEventConsumer ,
) -> Result < Async < ( ) > > {
self . connection . lock ( ) . unwrap ( ) . connect ( ) ? ;
let inbox = self
. folder s
. mailboxe s
. read ( )
. unwrap ( )
. get ( & folder _hash)
. get ( & mailbox _hash)
. map ( std ::clone ::Clone ::clone )
. unwrap ( ) ;
let tag_index = self . tag_index . clone ( ) ;
@ -340,7 +340,7 @@ impl MailBackend for ImapType {
sender : RefreshEventConsumer ,
work_context : WorkContext ,
) -> Result < std ::thread ::ThreadId > {
let folder s = self . folder s. clone ( ) ;
let mailboxe s = self . mailboxe s. clone ( ) ;
let tag_index = self . tag_index . clone ( ) ;
let conn = ImapConnection ::new_connection ( & self . server_conf , self . online . clone ( ) ) ;
let main_conn = self . connection . clone ( ) ;
@ -365,7 +365,7 @@ impl MailBackend for ImapType {
is_online ,
main_conn ,
uid_store ,
folder s,
mailboxe s,
sender ,
work_context ,
tag_index ,
@ -379,38 +379,41 @@ impl MailBackend for ImapType {
Ok ( handle . thread ( ) . id ( ) )
}
fn folder s( & self ) -> Result < FnvHashMap < FolderHash , Folder > > {
fn mailboxe s( & self ) -> Result < FnvHashMap < MailboxHash , Mailbox > > {
{
let folder s = self . folder s. read ( ) . unwrap ( ) ;
if ! folder s. is_empty ( ) {
return Ok ( folder s
let mailboxe s = self . mailboxe s. read ( ) . unwrap ( ) ;
if ! mailboxe s. is_empty ( ) {
return Ok ( mailboxe s
. iter ( )
. map ( | ( h , f ) | ( * h , Box ::new ( Clone ::clone ( f ) ) as Folder ) )
. map ( | ( h , f ) | ( * h , Box ::new ( Clone ::clone ( f ) ) as Mailbox ) )
. collect ( ) ) ;
}
}
let mut folders = self . folders . write ( ) ? ;
* folders = ImapType ::imap_folders ( & self . connection ) ? ;
folders . retain ( | _ , f | ( self . is_subscribed ) ( f . path ( ) ) ) ;
let keys = folders . keys ( ) . cloned ( ) . collect ::< FnvHashSet < FolderHash > > ( ) ;
let mut mailboxes = self . mailboxes . write ( ) ? ;
* mailboxes = ImapType ::imap_mailboxes ( & self . connection ) ? ;
mailboxes . retain ( | _ , f | ( self . is_subscribed ) ( f . path ( ) ) ) ;
let keys = mailboxes
. keys ( )
. cloned ( )
. collect ::< FnvHashSet < MailboxHash > > ( ) ;
let mut uid_lock = self . uid_store . uidvalidity . lock ( ) . unwrap ( ) ;
for f in folders . values_mut ( ) {
for f in mailboxe s. values_mut ( ) {
uid_lock . entry ( f . hash ( ) ) . or_default ( ) ;
f . children . retain ( | c | keys . contains ( c ) ) ;
}
drop ( uid_lock ) ;
Ok ( folder s
Ok ( mailboxe s
. iter ( )
. filter ( | ( _ , f ) | f . is_subscribed )
. map ( | ( h , f ) | ( * h , Box ::new ( Clone ::clone ( f ) ) as Folder ) )
. map ( | ( h , f ) | ( * h , Box ::new ( Clone ::clone ( f ) ) as Mailbox ) )
. collect ( ) )
}
fn operation ( & self , hash : EnvelopeHash ) -> Box < dyn BackendOp > {
let ( uid , folder _hash) = self . uid_store . hash_index . lock ( ) . unwrap ( ) [ & hash ] ;
let ( uid , mailbox _hash) = self . uid_store . hash_index . lock ( ) . unwrap ( ) [ & hash ] ;
Box ::new ( ImapOp ::new (
uid ,
self . folder s. read ( ) . unwrap ( ) [ & folder _hash]
self . mailboxe s. read ( ) . unwrap ( ) [ & mailbox _hash]
. imap_path ( )
. to_string ( ) ,
self . connection . clone ( ) ,
@ -419,28 +422,28 @@ impl MailBackend for ImapType {
) )
}
fn save ( & self , bytes : & [ u8 ] , folder : & str , flags : Option < Flag > ) -> Result < ( ) > {
fn save ( & self , bytes : & [ u8 ] , mailbox : & str , flags : Option < Flag > ) -> Result < ( ) > {
let path = {
let folder s = self . folder s. read ( ) . unwrap ( ) ;
let mailboxe s = self . mailboxe s. read ( ) . unwrap ( ) ;
let f_result = folder s
let f_result = mailboxe s
. values ( )
. find ( | v | v . path = = folder | | v . name = = folder ) ;
. find ( | v | v . path = = mailbox | | v . name = = mailbox ) ;
if f_result
. map ( | f | ! f . permissions . lock ( ) . unwrap ( ) . create_messages )
. unwrap_or ( false )
{
return Err ( MeliError ::new ( format ! (
"You are not allowed to create messages in folder {}" ,
folder
"You are not allowed to create messages in mailbox {}" ,
mailbox
) ) ) ;
}
f_result
. map ( | v | v . imap_path ( ) . to_string ( ) )
. ok_or ( MeliError ::new ( format ! (
"Folder with name {} not found." ,
folder
"Mailbox with name {} not found." ,
mailbox
) ) ) ?
} ;
let mut response = String ::with_capacity ( 8 * 1024 ) ;
@ -478,10 +481,10 @@ impl MailBackend for ImapType {
}
}
fn create_folder (
fn create_mailbox (
& mut self ,
mut path : String ,
) -> Result < ( Folder Hash, FnvHashMap < FolderHash , Folder > ) > {
) -> Result < ( Mailbox Hash, FnvHashMap < MailboxHash , Mailbox > ) > {
/* Must transform path to something the IMAP server will accept
*
* Each root mailbox has a hierarchy delimeter reported by the LIST entry . All paths
@ -496,21 +499,21 @@ impl MailBackend for ImapType {
* decision is unpleasant for you .
* /
let mut folder s = self . folder s. write ( ) . unwrap ( ) ;
for root_folder in folder s . values ( ) . filter ( | f | f . parent . is_none ( ) ) {
if path . starts_with ( & root_folder . name ) {
debug ! ( "path starts with {:?}" , & root_folder ) ;
let mut mailboxe s = self . mailboxe s. write ( ) . unwrap ( ) ;
for root_mailbox in mailboxe s . values ( ) . filter ( | f | f . parent . is_none ( ) ) {
if path . starts_with ( & root_mailbox . name ) {
debug ! ( "path starts with {:?}" , & root_mailbox ) ;
path = path . replace (
'/' ,
( root_folder . separator as char ) . encode_utf8 ( & mut [ 0 ; 4 ] ) ,
( root_mailbox . separator as char ) . encode_utf8 ( & mut [ 0 ; 4 ] ) ,
) ;
break ;
}
}
if folder s. values ( ) . any ( | f | f . path = = path ) {
if mailboxe s. values ( ) . any ( | f | f . path = = path ) {
return Err ( MeliError ::new ( format ! (
"Folder named `{}` in account `{}` already exists." ,
"Mailbox named `{}` in account `{}` already exists." ,
path , self . account_name ,
) ) ) ;
}
@ -527,21 +530,24 @@ impl MailBackend for ImapType {
let ret : Result < ( ) > = ImapResponse ::from ( & response ) . into ( ) ;
ret ? ;
let new_hash = get_path_hash ! ( path . as_str ( ) ) ;
folder s. clear ( ) ;
drop ( folder s) ;
Ok ( ( new_hash , self . folder s( ) . map_err ( | err | MeliError ::new ( format ! ( "Mailbox create was succesful (returned `{}`) but listing mailboxes afterwards returned `{}`" , response , err ) ) ) ? ) )
mailboxe s. clear ( ) ;
drop ( mailboxe s) ;
Ok ( ( new_hash , self . mailboxe s( ) . map_err ( | err | MeliError ::new ( format ! ( "Mailbox create was succesful (returned `{}`) but listing mailboxes afterwards returned `{}`" , response , err ) ) ) ? ) )
}
fn delete_folder ( & mut self , folder_hash : FolderHash ) -> Result < FnvHashMap < FolderHash , Folder > > {
let mut folders = self . folders . write ( ) . unwrap ( ) ;
let permissions = folders [ & folder_hash ] . permissions ( ) ;
fn delete_mailbox (
& mut self ,
mailbox_hash : MailboxHash ,
) -> Result < FnvHashMap < MailboxHash , Mailbox > > {
let mut mailboxes = self . mailboxes . write ( ) . unwrap ( ) ;
let permissions = mailboxes [ & mailbox_hash ] . permissions ( ) ;
if ! permissions . delete_mailbox {
return Err ( MeliError ::new ( format ! ( "You do not have permission to delete `{}`. Set permissions for this mailbox are {}" , folders [ & folder_hash ] . name ( ) , permissions ) ) ) ;
return Err ( MeliError ::new ( format ! ( "You do not have permission to delete `{}`. Set permissions for this mailbox are {}" , mailboxes [ & mailbox _hash] . name ( ) , permissions ) ) ) ;
}
let mut response = String ::with_capacity ( 8 * 1024 ) ;
{
let mut conn_lck = self . connection . lock ( ) ? ;
if ! folders [ & folder _hash] . no_select {
if ! mailboxes [ & mailbox _hash] . no_select {
/* make sure mailbox is not selected before it gets deleted, otherwise
* connection gets dropped by server * /
if conn_lck
@ -550,42 +556,46 @@ impl MailBackend for ImapType {
. any ( | cap | cap . eq_ignore_ascii_case ( b" UNSELECT " ) )
{
conn_lck . send_command (
format ! ( "UNSELECT \"{}\"" , folders [ & folder _hash] . imap_path ( ) ) . as_bytes ( ) ,
format ! ( "UNSELECT \"{}\"" , mailboxes [ & mailbox _hash] . imap_path ( ) ) . as_bytes ( ) ,
) ? ;
conn_lck . read_response ( & mut response ) ? ;
} else {
conn_lck . send_command (
format ! ( "SELECT \"{}\"" , folders [ & folder _hash] . imap_path ( ) ) . as_bytes ( ) ,
format ! ( "SELECT \"{}\"" , mailboxes [ & mailbox _hash] . imap_path ( ) ) . as_bytes ( ) ,
) ? ;
conn_lck . read_response ( & mut response ) ? ;
conn_lck . send_command (
format ! ( "EXAMINE \"{}\"" , folders [ & folder _hash] . imap_path ( ) ) . as_bytes ( ) ,
format ! ( "EXAMINE \"{}\"" , mailboxes [ & mailbox _hash] . imap_path ( ) ) . as_bytes ( ) ,
) ? ;
conn_lck . read_response ( & mut response ) ? ;
}
}
if folders [ & folder _hash] . is_subscribed ( ) {
if mailboxes [ & mailbox _hash] . is_subscribed ( ) {
conn_lck . send_command (
format ! ( "UNSUBSCRIBE \"{}\"" , folders [ & folder _hash] . imap_path ( ) ) . as_bytes ( ) ,
format ! ( "UNSUBSCRIBE \"{}\"" , mailboxes [ & mailbox _hash] . imap_path ( ) ) . as_bytes ( ) ,
) ? ;
conn_lck . read_response ( & mut response ) ? ;
}
conn_lck . send_command (
debug ! ( format ! ( "DELETE \"{}\"" , folders [ & folder_hash ] . imap_path ( ) ) ) . as_bytes ( ) ,
debug ! ( format ! (
"DELETE \"{}\"" ,
mailboxes [ & mailbox_hash ] . imap_path ( )
) )
. as_bytes ( ) ,
) ? ;
conn_lck . read_response ( & mut response ) ? ;
}
let ret : Result < ( ) > = ImapResponse ::from ( & response ) . into ( ) ;
ret ? ;
folder s. clear ( ) ;
drop ( folder s) ;
self . folder s( ) . map_err ( | err | format ! ( "Mailbox delete was succesful (returned `{}`) but listing mailboxes afterwards returned `{}`" , response , err ) . into ( ) )
mailboxe s. clear ( ) ;
drop ( mailboxe s) ;
self . mailboxe s( ) . map_err ( | err | format ! ( "Mailbox delete was succesful (returned `{}`) but listing mailboxes afterwards returned `{}`" , response , err ) . into ( ) )
}
fn set_folder _subscription ( & mut self , folder_hash : Folder Hash, new_val : bool ) -> Result < ( ) > {
let mut folder s = self . folder s. write ( ) . unwrap ( ) ;
if folders [ & folder _hash] . is_subscribed ( ) = = new_val {
fn set_mailbox _subscription ( & mut self , mailbox_hash : Mailbox Hash, new_val : bool ) -> Result < ( ) > {
let mut mailboxe s = self . mailboxe s. write ( ) . unwrap ( ) ;
if mailboxes [ & mailbox _hash] . is_subscribed ( ) = = new_val {
return Ok ( ( ) ) ;
}
@ -594,11 +604,11 @@ impl MailBackend for ImapType {
let mut conn_lck = self . connection . lock ( ) ? ;
if new_val {
conn_lck . send_command (
format ! ( "SUBSCRIBE \"{}\"" , folders [ & folder _hash] . imap_path ( ) ) . as_bytes ( ) ,
format ! ( "SUBSCRIBE \"{}\"" , mailboxes [ & mailbox _hash] . imap_path ( ) ) . as_bytes ( ) ,
) ? ;
} else {
conn_lck . send_command (
format ! ( "UNSUBSCRIBE \"{}\"" , folders [ & folder _hash] . imap_path ( ) ) . as_bytes ( ) ,
format ! ( "UNSUBSCRIBE \"{}\"" , mailboxes [ & mailbox _hash] . imap_path ( ) ) . as_bytes ( ) ,
) ? ;
}
conn_lck . read_response ( & mut response ) ? ;
@ -606,24 +616,28 @@ impl MailBackend for ImapType {
let ret : Result < ( ) > = ImapResponse ::from ( & response ) . into ( ) ;
if ret . is_ok ( ) {
folder s. entry ( folder _hash) . and_modify ( | entry | {
mailboxe s. entry ( mailbox _hash) . and_modify ( | entry | {
let _ = entry . set_is_subscribed ( new_val ) ;
} ) ;
}
ret
}
fn rename_folder ( & mut self , folder_hash : FolderHash , mut new_path : String ) -> Result < Folder > {
let mut folders = self . folders . write ( ) . unwrap ( ) ;
let permissions = folders [ & folder_hash ] . permissions ( ) ;
fn rename_mailbox (
& mut self ,
mailbox_hash : MailboxHash ,
mut new_path : String ,
) -> Result < Mailbox > {
let mut mailboxes = self . mailboxes . write ( ) . unwrap ( ) ;
let permissions = mailboxes [ & mailbox_hash ] . permissions ( ) ;
if ! permissions . delete_mailbox {
return Err ( MeliError ::new ( format ! ( "You do not have permission to rename folder `{}` (rename is equivalent to delete + create). Set permissions for this mailbox are {}" , folders [ & folder_hash ] . name ( ) , permissions ) ) ) ;
return Err ( MeliError ::new ( format ! ( "You do not have permission to rename mailbox `{}` (rename is equivalent to delete + create). Set permissions for this mailbox are {}" , mailboxes [ & mailbox _hash] . name ( ) , permissions ) ) ) ;
}
let mut response = String ::with_capacity ( 8 * 1024 ) ;
if folders [ & folder _hash] . separator ! = b'/' {
if mailboxes [ & mailbox _hash] . separator ! = b'/' {
new_path = new_path . replace (
'/' ,
( folders [ & folder _hash] . separator as char ) . encode_utf8 ( & mut [ 0 ; 4 ] ) ,
( mailboxes [ & mailbox _hash] . separator as char ) . encode_utf8 ( & mut [ 0 ; 4 ] ) ,
) ;
}
{
@ -631,7 +645,7 @@ impl MailBackend for ImapType {
conn_lck . send_command (
debug ! ( format ! (
"RENAME \"{}\" \"{}\"" ,
folders [ & folder _hash] . imap_path ( ) ,
mailboxes [ & mailbox _hash] . imap_path ( ) ,
new_path
) )
. as_bytes ( ) ,
@ -641,23 +655,23 @@ impl MailBackend for ImapType {
let new_hash = get_path_hash ! ( new_path . as_str ( ) ) ;
let ret : Result < ( ) > = ImapResponse ::from ( & response ) . into ( ) ;
ret ? ;
folder s. clear ( ) ;
drop ( folder s) ;
self . folder s( ) . map_err ( | err | format ! ( "Mailbox rename was succesful (returned `{}`) but listing mailboxes afterwards returned `{}`" , response , err ) ) ? ;
Ok ( BackendFolder ::clone (
& self . folder s. read ( ) . unwrap ( ) [ & new_hash ] ,
mailboxe s. clear ( ) ;
drop ( mailboxe s) ;
self . mailboxe s( ) . map_err ( | err | format ! ( "Mailbox rename was succesful (returned `{}`) but listing mailboxes afterwards returned `{}`" , response , err ) ) ? ;
Ok ( BackendMailbox ::clone (
& self . mailboxe s. read ( ) . unwrap ( ) [ & new_hash ] ,
) )
}
fn set_folder _permissions (
fn set_mailbox _permissions (
& mut self ,
folder_hash : Folder Hash,
_val : crate ::backends ::Folder Permissions,
mailbox_hash : Mailbox Hash,
_val : crate ::backends ::Mailbox Permissions,
) -> Result < ( ) > {
let folder s = self . folder s. write ( ) . unwrap ( ) ;
let permissions = folders [ & folder _hash] . permissions ( ) ;
let mailboxe s = self . mailboxe s. write ( ) . unwrap ( ) ;
let permissions = mailboxes [ & mailbox _hash] . permissions ( ) ;
if ! permissions . change_permissions {
return Err ( MeliError ::new ( format ! ( "You do not have permission to change permissions for folder `{}`. Set permissions for this mailbox are {}" , folders [ & folder _hash] . name ( ) , permissions ) ) ) ;
return Err ( MeliError ::new ( format ! ( "You do not have permission to change permissions for mailbox `{}`. Set permissions for this mailbox are {}" , mailboxes [ & mailbox _hash] . name ( ) , permissions ) ) ) ;
}
Err ( MeliError ::new ( "Unimplemented." ) )
@ -698,7 +712,7 @@ impl ImapType {
can_create_flags : Arc ::new ( Mutex ::new ( false ) ) ,
tag_index : Arc ::new ( RwLock ::new ( Default ::default ( ) ) ) ,
folder s : Arc ::new ( RwLock ::new ( Default ::default ( ) ) ) ,
mailboxe s : Arc ::new ( RwLock ::new ( Default ::default ( ) ) ) ,
connection : Arc ::new ( Mutex ::new ( connection ) ) ,
uid_store : Arc ::new ( UIDStore {
uidvalidity : Default ::default ( ) ,
@ -742,10 +756,10 @@ impl ImapType {
}
}
pub fn imap_folder s (
pub fn imap_mailboxe s (
connection : & Arc < Mutex < ImapConnection > > ,
) -> Result < FnvHashMap < FolderHash , ImapFolder > > {
let mut folders : FnvHashMap < FolderHash , ImapFolder > = Default ::default ( ) ;
) -> Result < FnvHashMap < MailboxHash , ImapMailbox > > {
let mut mailboxes : FnvHashMap < MailboxHash , ImapMailbox > = Default ::default ( ) ;
let mut res = String ::with_capacity ( 8 * 1024 ) ;
let mut conn = connection . lock ( ) . unwrap ( ) ;
conn . send_command ( b" LIST \" \" \" * \" " ) ? ;
@ -755,33 +769,33 @@ impl ImapType {
/* Remove "M__ OK .." line */
lines . next_back ( ) ;
for l in lines . map ( | l | l . trim ( ) ) {
if let Ok ( mut folder ) =
protocol_parser ::list_folder _result ( l . as_bytes ( ) ) . to_full_result ( )
if let Ok ( mut mailbox ) =
protocol_parser ::list_mailbox _result ( l . as_bytes ( ) ) . to_full_result ( )
{
if let Some ( parent ) = folder . parent {
if folder s. contains_key ( & parent ) {
folder s
if let Some ( parent ) = mailbox . parent {
if mailboxe s. contains_key ( & parent ) {
mailboxe s
. entry ( parent )
. and_modify ( | e | e . children . push ( folder . hash ) ) ;
. and_modify ( | e | e . children . push ( mailbox . hash ) ) ;
} else {
/* Insert dummy parent entry, populating only the children field. Later
* when we encounter the parent entry we will swap its children with
* dummy 's * /
folder s. insert (
mailboxe s. insert (
parent ,
ImapFolder {
children : vec ! [ folder . hash ] ,
. . ImapFolder ::default ( )
ImapMailbox {
children : vec ! [ mailbox . hash ] ,
. . ImapMailbox ::default ( )
} ,
) ;
}
}
if folder s. contains_key ( & folder . hash ) {
let entry = folder s. entry ( folder . hash ) . or_default ( ) ;
std ::mem ::swap ( & mut entry . children , & mut folder . children ) ;
* entry = folder ;
if mailboxe s. contains_key ( & mailbox . hash ) {
let entry = mailboxe s. entry ( mailbox . hash ) . or_default ( ) ;
std ::mem ::swap ( & mut entry . children , & mut mailbox . children ) ;
* entry = mailbox ;
} else {
folder s. insert ( folder . hash , folder ) ;
mailboxe s. insert ( mailbox . hash , mailbox ) ;
}
} else {
debug ! ( "parse error for {:?}" , l ) ;
@ -795,9 +809,9 @@ impl ImapType {
lines . next_back ( ) ;
for l in lines . map ( | l | l . trim ( ) ) {
if let Ok ( subscription ) =
protocol_parser ::list_folder _result ( l . as_bytes ( ) ) . to_full_result ( )
protocol_parser ::list_mailbox _result ( l . as_bytes ( ) ) . to_full_result ( )
{
if let Some ( f ) = folder s. get_mut ( & subscription . hash ( ) ) {
if let Some ( f ) = mailboxe s. get_mut ( & subscription . hash ( ) ) {
if subscription . no_select {
continue ;
}
@ -807,7 +821,7 @@ impl ImapType {
debug ! ( "parse error for {:?}" , l ) ;
}
}
Ok ( debug ! ( folder s) )
Ok ( debug ! ( mailboxe s) )
}
pub fn capabilities ( & self ) -> Vec < String > {
@ -823,13 +837,13 @@ impl ImapType {
pub fn search (
& self ,
query : String ,
folder_hash : Folder Hash,
mailbox_hash : Mailbox Hash,
) -> Result < SmallVec < [ EnvelopeHash ; 512 ] > > {
let folder s_lck = self . folder s. read ( ) ? ;
let mailboxe s_lck = self . mailboxe s. read ( ) ? ;
let mut response = String ::with_capacity ( 8 * 1024 ) ;
let mut conn = self . connection . lock ( ) ? ;
conn . send_command (
format ! ( "EXAMINE \"{}\"" , folders_lck [ & folder _hash] . imap_path ( ) ) . as_bytes ( ) ,
format ! ( "EXAMINE \"{}\"" , mailboxes_lck [ & mailbox _hash] . imap_path ( ) ) . as_bytes ( ) ,
) ? ;
conn . read_response ( & mut response ) ? ;
conn . send_command ( format ! ( "UID SEARCH CHARSET UTF-8 {}" , query ) . as_bytes ( ) ) ? ;