diff --git a/crates/directory/src/memory/config.rs b/crates/directory/src/memory/config.rs index dc5a28ae..2ee3281f 100644 --- a/crates/directory/src/memory/config.rs +++ b/crates/directory/src/memory/config.rs @@ -73,43 +73,8 @@ impl MemoryDirectory { member_of, }, ); - let mut emails = Vec::new(); - for (pos, (_, email)) in config - .values((prefix.as_str(), "users", lookup_id, "email")) - .enumerate() - { - directory - .emails_to_names - .entry(email.to_string()) - .or_default() - .push(if pos > 0 { - EmailType::Alias(name.clone()) - } else { - EmailType::Primary(name.clone()) - }); - if let Some((_, domain)) = email.rsplit_once('@') { - directory.domains.insert(domain.to_lowercase()); - } - - emails.push(if pos > 0 { - EmailType::Alias(email.to_lowercase()) - } else { - EmailType::Primary(email.to_lowercase()) - }); - } - for (_, email) in config.values((prefix.as_str(), "users", lookup_id, "email-list")) { - directory - .emails_to_names - .entry(email.to_lowercase()) - .or_default() - .push(EmailType::List(name.clone())); - if let Some((_, domain)) = email.rsplit_once('@') { - directory.domains.insert(domain.to_lowercase()); - } - emails.push(EmailType::List(email.to_lowercase())); - } - directory.names_to_email.insert(name, emails); + directory.parse_emails(config, (prefix.as_str(), "users", lookup_id), name)?; } for lookup_id in config.sub_keys((prefix.as_str(), "groups")) { @@ -119,7 +84,7 @@ impl MemoryDirectory { directory.principals.insert( name.clone(), Principal { - name, + name: name.clone(), secrets: vec![], typ: Type::Group, description: config @@ -134,6 +99,8 @@ impl MemoryDirectory { .collect(), }, ); + + directory.parse_emails(config, (prefix.as_str(), "groups", lookup_id), name)?; } directory @@ -143,3 +110,49 @@ impl MemoryDirectory { Ok(Arc::new(directory)) } } + +impl MemoryDirectory { + fn parse_emails( + &mut self, + config: &Config, + prefix: impl AsKey, + name: String, + ) -> utils::config::Result<()> { + let prefix = prefix.as_key(); + let mut emails = Vec::new(); + + for (pos, (_, email)) in config.values((prefix.as_str(), "email")).enumerate() { + self.emails_to_names + .entry(email.to_string()) + .or_default() + .push(if pos > 0 { + EmailType::Alias(name.clone()) + } else { + EmailType::Primary(name.clone()) + }); + + if let Some((_, domain)) = email.rsplit_once('@') { + self.domains.insert(domain.to_lowercase()); + } + + emails.push(if pos > 0 { + EmailType::Alias(email.to_lowercase()) + } else { + EmailType::Primary(email.to_lowercase()) + }); + } + for (_, email) in config.values((prefix.as_str(), "email-list")) { + self.emails_to_names + .entry(email.to_lowercase()) + .or_default() + .push(EmailType::List(name.clone())); + if let Some((_, domain)) = email.rsplit_once('@') { + self.domains.insert(domain.to_lowercase()); + } + emails.push(EmailType::List(email.to_lowercase())); + } + + self.names_to_email.insert(name, emails); + Ok(()) + } +} diff --git a/crates/directory/src/memory/mod.rs b/crates/directory/src/memory/mod.rs index 8aade901..916333a8 100644 --- a/crates/directory/src/memory/mod.rs +++ b/crates/directory/src/memory/mod.rs @@ -28,7 +28,7 @@ use crate::{DirectoryOptions, Principal}; pub mod config; pub mod lookup; -#[derive(Default)] +#[derive(Default, Debug)] pub struct MemoryDirectory { principals: AHashMap, emails_to_names: AHashMap>, @@ -37,6 +37,7 @@ pub struct MemoryDirectory { opt: DirectoryOptions, } +#[derive(Debug)] enum EmailType { Primary(String), Alias(String), diff --git a/crates/imap/src/core/mailbox.rs b/crates/imap/src/core/mailbox.rs index cc7b2df4..740dd774 100644 --- a/crates/imap/src/core/mailbox.rs +++ b/crates/imap/src/core/mailbox.rs @@ -81,17 +81,13 @@ impl SessionData { mailbox_prefix: Option, access_token: &AccessToken, ) -> crate::Result { - let mailbox_ids = if access_token.is_primary_id(account_id) { + let mailbox_ids = if access_token.is_primary_id(account_id) + || access_token.member_of.contains(&account_id) + { self.jmap .mailbox_get_or_create(account_id) .await .map_err(|_| {})? - } else if access_token.member_of.contains(&account_id) { - self.jmap - .get_document_ids(account_id, Collection::Mailbox) - .await - .map_err(|_| {})? - .unwrap_or_default() } else { self.jmap .shared_documents(access_token, account_id, Collection::Mailbox, Acl::Read) diff --git a/crates/imap/src/core/writer.rs b/crates/imap/src/core/writer.rs index 9f4c1953..b97d7f7b 100644 --- a/crates/imap/src/core/writer.rs +++ b/crates/imap/src/core/writer.rs @@ -57,8 +57,7 @@ pub fn spawn_writer(mut stream: Event, span: tracing::Span) -> mpsc::Sender IMAPTest { ManageSieveSessionManager::new(jmap.clone(), imap.clone()), shutdown_rx, ), + ServerProtocol::Smtp | ServerProtocol::Lmtp => { + server.spawn(SmtpSessionManager::new(smtp.clone()), shutdown_rx) + } _ => unreachable!(), }; }); @@ -289,6 +299,18 @@ async fn init_imap_tests(delete_if_exists: bool) -> IMAPTest { "Bill Foobar", ) .await; + create_test_group_with_email( + jmap.directory.as_ref(), + "support@example.com", + "Support Group", + ) + .await; + add_to_group( + jmap.directory.as_ref(), + "jane.smith@example.com", + "support@example.com", + ) + .await; if delete_if_exists { jmap.store.destroy().await; diff --git a/tests/src/jmap/delivery.rs b/tests/src/jmap/delivery.rs index cab155b8..5e129eb4 100644 --- a/tests/src/jmap/delivery.rs +++ b/tests/src/jmap/delivery.rs @@ -295,8 +295,15 @@ impl SmtpConnection { } pub async fn connect() -> Self { - let (reader, writer) = - tokio::io::split(TcpStream::connect("127.0.0.1:11200").await.unwrap()); + SmtpConnection::connect_port(11200).await + } + + pub async fn connect_port(port: u16) -> Self { + let (reader, writer) = tokio::io::split( + TcpStream::connect(&format!("127.0.0.1:{port}")) + .await + .unwrap(), + ); let mut conn = SmtpConnection { reader: BufReader::new(reader).lines(), writer,