diff --git a/crates/common/build.rs b/crates/common/build.rs index 3234d19e..4f90ae1b 100644 --- a/crates/common/build.rs +++ b/crates/common/build.rs @@ -20,7 +20,7 @@ fn main() { fs::write(&dest_path, generated_code).expect("Failed to write generated locales"); - println!("cargo:rerun-if-changed={yaml_path:?}"); + println!("cargo:rerun-if-changed={}", yaml_path.display()); } fn parse_yaml(content: &str) -> HashMap> { diff --git a/crates/imap/src/op/create.rs b/crates/imap/src/op/create.rs index ab4f59c9..6e7820c1 100644 --- a/crates/imap/src/op/create.rs +++ b/crates/imap/src/op/create.rs @@ -175,44 +175,55 @@ impl SessionData { } // Validate special folders - let full_path: String = path.join("/"); let mut parent_mailbox_id = None; let mut parent_mailbox_name = None; let (account_id, path) = { let mailboxes = self.mailboxes.lock(); - let account = if path.first() == Some(&self.server.core.jmap.shared_folder.as_str()) { - // Shared Folders// - if path.len() < 3 { + let (account, full_path) = + if path.first() == Some(&self.server.core.jmap.shared_folder.as_str()) { + // Shared Folders// + if path.len() < 3 { + return Err(trc::ImapEvent::Error + .into_err() + .details("Mailboxes under root shared folders are not allowed.") + .code(ResponseCode::Cannot)); + } + // Build path + let root = &mut path[2]; + if root.eq_ignore_ascii_case("INBOX") { + *root = "INBOX"; + } + let full_path = path.join("/"); + let prefix = Some(format!("{}/{}", path.remove(0), path.remove(0))); + + // Locate account + if let Some(account) = mailboxes + .iter() + .skip(1) + .find(|account| account.prefix == prefix) + { + (account, full_path) + } else { + #[allow(clippy::unnecessary_literal_unwrap)] + return Err(trc::ImapEvent::Error.into_err().details(format!( + "Shared account '{}' not found.", + prefix.unwrap_or_default() + ))); + } + } else if let Some(account) = mailboxes.first() { + let root = &mut path[0]; + if root.eq_ignore_ascii_case("INBOX") { + *root = "INBOX"; + } + + (account, path.join("/")) + } else { return Err(trc::ImapEvent::Error .into_err() - .details("Mailboxes under root shared folders are not allowed.") - .code(ResponseCode::Cannot)); - } - let prefix = Some(format!("{}/{}", path.remove(0), path.remove(0))); - - // Locate account - if let Some(account) = mailboxes - .iter() - .skip(1) - .find(|account| account.prefix == prefix) - { - account - } else { - #[allow(clippy::unnecessary_literal_unwrap)] - return Err(trc::ImapEvent::Error.into_err().details(format!( - "Shared account '{}' not found.", - prefix.unwrap_or_default() - ))); - } - } else if let Some(account) = mailboxes.first() { - account - } else { - return Err(trc::ImapEvent::Error - .into_err() - .details("Internal server error.") - .caused_by(trc::location!()) - .code(ResponseCode::ContactAdmin)); - }; + .details("Internal server error.") + .caused_by(trc::location!()) + .code(ResponseCode::ContactAdmin)); + }; // Locate parent mailbox if account.mailbox_names.contains_key(&full_path) { @@ -270,7 +281,6 @@ impl SessionData { Ok(CreateParams { account_id, path, - full_path, parent_mailbox_id, parent_mailbox_name, special_use: if let Some(mailbox_role) = mailbox_role { @@ -305,7 +315,6 @@ impl SessionData { pub struct CreateParams<'x> { pub account_id: u32, pub path: Vec<&'x str>, - pub full_path: String, pub parent_mailbox_id: Option, pub parent_mailbox_name: Option, pub special_use: Option, diff --git a/tests/src/imap/mailbox.rs b/tests/src/imap/mailbox.rs index c6e1f163..3071eabd 100644 --- a/tests/src/imap/mailbox.rs +++ b/tests/src/imap/mailbox.rs @@ -109,7 +109,7 @@ pub async fn test(mut imap: &mut ImapConnection, mut imap_check: &mut ImapConnec imap.assert_read(Type::Tagged, ResponseType::Ok).await; imap.send("RENAME \"Tofu\" \"INBOX\"").await; imap.assert_read(Type::Tagged, ResponseType::No).await; - imap.send("RENAME \"Tofu\" \"INBOX/Tofu\"").await; + imap.send("RENAME \"Tofu\" \"Inbox/Tofu\"").await; imap.assert_read(Type::Tagged, ResponseType::Ok).await; imap.send("RENAME \"Deleted Items\" \"Recycle Bin\"").await; imap.assert_read(Type::Tagged, ResponseType::Ok).await;