diff --git a/pkgs/mailnix/src/config.rs b/pkgs/mailnix/src/config.rs index 09d8c9a..f7a686c 100644 --- a/pkgs/mailnix/src/config.rs +++ b/pkgs/mailnix/src/config.rs @@ -132,6 +132,34 @@ impl Config { Ok(()) } + fn is_valid_destination(&self, address: &String) -> bool { + if self.accounts.contains_key(address) { + return true; + } + + // There is no explicit account matching 'address'. However, 'address' may still be + // implicitly valid due to the existence of a catchall-alias or the domain being aliased. + let (local_part, domain) = parse_address(address).unwrap(); + if let Some(dests) = self.aliases.get(&domain) { + if dests.iter().filter(|dest| !is_domain(dest)).count() > 0 { + // At least one explicit catchall-address exists! + return true; + } + // At this point, we need to (recursively) iterate over domain-aliases to check whether + // there is an exact match (or a catchall-alias for the aliased domain). + for dest in dests.iter().filter(|addr| is_domain(addr)) { + let aliased_addr = format!("{local_part}@{dest}"); + // FIXME: This current implementation may not terminate if the configured aliases + // contain a loop! + if self.is_valid_destination(&aliased_addr) { + return true; + } + } + } + // alias destination is not valid + false + } + pub fn check(&self) -> Result<(), Box> { // check whether all account domains exist for name in self.accounts.keys() { @@ -149,7 +177,7 @@ impl Config { for dest in dests.iter() { if is_domain(dest) && !self.domains.contains(dest) { panic!("Aliased dest-domain \"{dest}\" does not exist"); - } else if !is_domain(dest) && !self.accounts.contains_key(dest) { + } else if !is_domain(dest) && !self.is_valid_destination(dest) { panic!("Aliased dest-account \"{dest}\" does not exist"); } }