summaryrefslogtreecommitdiff
path: root/crates/directory/src/core/dispatch.rs
diff options
context:
space:
mode:
authormdecimus <mauro@stalw.art>2023-12-18 22:25:42 +0100
committermdecimus <mauro@stalw.art>2023-12-18 22:25:42 +0100
commitea94de6d7705ca32949447a80b90633dcd4daf95 (patch)
tree8741fa310b11d118e13f061e10b2ca7a62b2203a /crates/directory/src/core/dispatch.rs
parent566a2a0ab8f06bde4eb8086942be2b630086f7f2 (diff)
CLI account management + Directory refactoring
Diffstat (limited to 'crates/directory/src/core/dispatch.rs')
-rw-r--r--crates/directory/src/core/dispatch.rs160
1 files changed, 160 insertions, 0 deletions
diff --git a/crates/directory/src/core/dispatch.rs b/crates/directory/src/core/dispatch.rs
new file mode 100644
index 00000000..510aea7f
--- /dev/null
+++ b/crates/directory/src/core/dispatch.rs
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2023 Stalwart Labs Ltd.
+ *
+ * This file is part of Stalwart Mail Server.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ * in the LICENSE file at the top-level directory of this distribution.
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * You can be released from the requirements of the AGPLv3 license by
+ * purchasing a commercial license. Please contact licensing@stalw.art
+ * for more details.
+*/
+
+use crate::{
+ backend::internal::lookup::DirectoryStore, Directory, DirectoryInner, Principal, QueryBy,
+};
+
+impl Directory {
+ pub async fn query(&self, by: QueryBy<'_>) -> crate::Result<Option<Principal<u32>>> {
+ match &self.store {
+ DirectoryInner::Internal(store) => store.query(by).await,
+ DirectoryInner::Ldap(store) => store.query(by).await,
+ DirectoryInner::Sql(store) => store.query(by).await,
+ DirectoryInner::Imap(store) => store.query(by).await,
+ DirectoryInner::Smtp(store) => store.query(by).await,
+ DirectoryInner::Memory(store) => store.query(by).await,
+ }
+ }
+
+ pub async fn email_to_ids(&self, email: &str) -> crate::Result<Vec<u32>> {
+ let mut address = self.subaddressing.to_subaddress(email);
+ for _ in 0..2 {
+ let result = match &self.store {
+ DirectoryInner::Internal(store) => store.email_to_ids(address.as_ref()).await,
+ DirectoryInner::Ldap(store) => store.email_to_ids(address.as_ref()).await,
+ DirectoryInner::Sql(store) => store.email_to_ids(address.as_ref()).await,
+ DirectoryInner::Imap(store) => store.email_to_ids(address.as_ref()).await,
+ DirectoryInner::Smtp(store) => store.email_to_ids(address.as_ref()).await,
+ DirectoryInner::Memory(store) => store.email_to_ids(address.as_ref()).await,
+ }?;
+
+ if !result.is_empty() {
+ return Ok(result);
+ } else if let Some(catch_all) = self.catch_all.to_catch_all(email) {
+ address = catch_all;
+ } else {
+ break;
+ }
+ }
+
+ Ok(vec![])
+ }
+
+ pub async fn is_local_domain(&self, domain: &str) -> crate::Result<bool> {
+ // Check cache
+ if let Some(cache) = &self.cache {
+ if let Some(result) = cache.get_domain(domain) {
+ return Ok(result);
+ }
+ }
+
+ let result = match &self.store {
+ DirectoryInner::Internal(store) => store.is_local_domain(domain).await,
+ DirectoryInner::Ldap(store) => store.is_local_domain(domain).await,
+ DirectoryInner::Sql(store) => store.is_local_domain(domain).await,
+ DirectoryInner::Imap(store) => store.is_local_domain(domain).await,
+ DirectoryInner::Smtp(store) => store.is_local_domain(domain).await,
+ DirectoryInner::Memory(store) => store.is_local_domain(domain).await,
+ }?;
+
+ // Update cache
+ if let Some(cache) = &self.cache {
+ cache.set_domain(domain, result);
+ }
+
+ Ok(result)
+ }
+
+ pub async fn rcpt(&self, email: &str) -> crate::Result<bool> {
+ // Expand subaddress
+ let mut address = self.subaddressing.to_subaddress(email);
+
+ // Check cache
+ if let Some(cache) = &self.cache {
+ if let Some(result) = cache.get_rcpt(address.as_ref()) {
+ return Ok(result);
+ }
+ }
+
+ for _ in 0..2 {
+ let result = match &self.store {
+ DirectoryInner::Internal(store) => store.rcpt(address.as_ref()).await,
+ DirectoryInner::Ldap(store) => store.rcpt(address.as_ref()).await,
+ DirectoryInner::Sql(store) => store.rcpt(address.as_ref()).await,
+ DirectoryInner::Imap(store) => store.rcpt(address.as_ref()).await,
+ DirectoryInner::Smtp(store) => store.rcpt(address.as_ref()).await,
+ DirectoryInner::Memory(store) => store.rcpt(address.as_ref()).await,
+ }?;
+
+ if result {
+ // Update cache
+ if let Some(cache) = &self.cache {
+ cache.set_rcpt(address.as_ref(), true);
+ }
+ return Ok(true);
+ } else if let Some(catch_all) = self.catch_all.to_catch_all(email) {
+ // Check cache
+ if let Some(cache) = &self.cache {
+ if let Some(result) = cache.get_rcpt(catch_all.as_ref()) {
+ return Ok(result);
+ }
+ }
+ address = catch_all;
+ } else {
+ break;
+ }
+ }
+
+ // Update cache
+ if let Some(cache) = &self.cache {
+ cache.set_rcpt(address.as_ref(), false);
+ }
+
+ Ok(false)
+ }
+
+ pub async fn vrfy(&self, address: &str) -> crate::Result<Vec<String>> {
+ let address = self.subaddressing.to_subaddress(address);
+ match &self.store {
+ DirectoryInner::Internal(store) => store.vrfy(address.as_ref()).await,
+ DirectoryInner::Ldap(store) => store.vrfy(address.as_ref()).await,
+ DirectoryInner::Sql(store) => store.vrfy(address.as_ref()).await,
+ DirectoryInner::Imap(store) => store.vrfy(address.as_ref()).await,
+ DirectoryInner::Smtp(store) => store.vrfy(address.as_ref()).await,
+ DirectoryInner::Memory(store) => store.vrfy(address.as_ref()).await,
+ }
+ }
+
+ pub async fn expn(&self, address: &str) -> crate::Result<Vec<String>> {
+ let address = self.subaddressing.to_subaddress(address);
+ match &self.store {
+ DirectoryInner::Internal(store) => store.expn(address.as_ref()).await,
+ DirectoryInner::Ldap(store) => store.expn(address.as_ref()).await,
+ DirectoryInner::Sql(store) => store.expn(address.as_ref()).await,
+ DirectoryInner::Imap(store) => store.expn(address.as_ref()).await,
+ DirectoryInner::Smtp(store) => store.expn(address.as_ref()).await,
+ DirectoryInner::Memory(store) => store.expn(address.as_ref()).await,
+ }
+ }
+}