Merge upstream v0.16.23
Five conflicts, resolved: - crates/common/src/auth/authentication.rs: upstream's get_directory_for_token and JwtClaims replace extract_jwt_domain; the per-domain directory code (DIR-1, DIR-5 to DIR-7) is kept, and the token lookup routes through it. The release's one new Enterprise snippet was the body of get_directory_for_issuer, which stays returning None: a token naming no address gets the server default, as DIR-2 specifies and as v0.16.22 did. - crates/common/src/manager/application.rs: upstream's rewrite of the tests, with the temp directory names renamed again, and the 5(a) notice the name-purge change should have added. - crates/common/src/network/mta.rs: both sides' imports. - crates/main/Cargo.toml: the AGPL-only license kept, version 0.16.23. - Cargo.lock: upstream's, with the fork's crates added by Cargo.
This commit is contained in:
@@ -23,6 +23,7 @@ use crate::{
|
||||
manager::SPAM_CLASSIFIER_KEY,
|
||||
network::RcptResolution,
|
||||
};
|
||||
use ahash::AHashSet;
|
||||
use directory::Recipient;
|
||||
use mail_auth::IpLookupStrategy;
|
||||
use registry::schema::enums::ExpressionVariable;
|
||||
@@ -37,6 +38,8 @@ use store::{
|
||||
write::{AlignedBytes, Archive, QueueClass, ValueClass},
|
||||
};
|
||||
use trc::{AddContext, SpamEvent};
|
||||
use types::id::Id;
|
||||
use utils::DomainPart;
|
||||
|
||||
impl Server {
|
||||
pub async fn rcpt_resolve(
|
||||
@@ -163,7 +166,10 @@ impl Server {
|
||||
}
|
||||
EmailCache::MailingList(id) => {
|
||||
if let Some(list) = self.try_list(id).await? {
|
||||
return Ok(RcptResolution::Expand(list.recipients.clone()));
|
||||
return Ok(RcptResolution::Expand(
|
||||
self.expand_nested_lists(id, list.recipients.clone())
|
||||
.await?,
|
||||
));
|
||||
} else {
|
||||
self.inner
|
||||
.cache
|
||||
@@ -195,6 +201,56 @@ impl Server {
|
||||
}
|
||||
}
|
||||
|
||||
async fn expand_nested_lists(
|
||||
&self,
|
||||
list_id: u32,
|
||||
recipients: Arc<[Box<str>]>,
|
||||
) -> trc::Result<Arc<[Box<str>]>> {
|
||||
let mut has_nested = false;
|
||||
for member in recipients.iter() {
|
||||
if let Some(EmailCache::MailingList(_)) = self.rcpt_id_from_email(member).await? {
|
||||
has_nested = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !has_nested {
|
||||
return Ok(recipients);
|
||||
}
|
||||
|
||||
let mut expanded = Vec::with_capacity(recipients.len());
|
||||
let mut seen: AHashSet<Box<str>> = AHashSet::with_capacity(recipients.len());
|
||||
let mut visited = AHashSet::from_iter([list_id]);
|
||||
let mut pending: Vec<Arc<[Box<str>]>> = Vec::new();
|
||||
let mut members = recipients;
|
||||
|
||||
loop {
|
||||
for member in members.iter() {
|
||||
if let Some(EmailCache::MailingList(nested_id)) =
|
||||
self.rcpt_id_from_email(member).await?
|
||||
{
|
||||
if !visited.insert(nested_id) {
|
||||
continue;
|
||||
}
|
||||
if let Some(nested) = self.try_list(nested_id).await? {
|
||||
pending.push(nested.recipients.clone());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if seen.insert(member.to_canonical_address().into()) {
|
||||
expanded.push(member.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let Some(next) = pending.pop() else {
|
||||
break;
|
||||
};
|
||||
members = next;
|
||||
}
|
||||
|
||||
Ok(expanded.into())
|
||||
}
|
||||
|
||||
pub async fn get_dkim_signers(
|
||||
&self,
|
||||
domain: &str,
|
||||
|
||||
Reference in New Issue
Block a user