mirror of
https://github.com/stalwartlabs/mail-server.git
synced 2025-09-12 06:54:34 +08:00
config_get() expression function + moved lookup.default.[hostname|domain] to server.hostname and report.domain
This commit is contained in:
parent
a4b1d5c39b
commit
a6c744b09a
21 changed files with 167 additions and 107 deletions
|
@ -14,6 +14,8 @@ use super::*;
|
|||
#[derive(Clone)]
|
||||
pub struct Network {
|
||||
pub node_id: u64,
|
||||
pub server_name: String,
|
||||
pub report_domain: String,
|
||||
pub security: Security,
|
||||
pub contact_form: Option<ContactForm>,
|
||||
pub http_response_url: IfBlock,
|
||||
|
@ -84,10 +86,12 @@ impl Default for Network {
|
|||
http_response_url: IfBlock::new::<()>(
|
||||
"server.http.url",
|
||||
[],
|
||||
"protocol + '://' + key_get('default', 'hostname') + ':' + local_port",
|
||||
"protocol + '://' + config_get('server.hostname') + ':' + local_port",
|
||||
),
|
||||
http_allowed_endpoint: IfBlock::new::<()>("server.http.allowed-endpoint", [], "200"),
|
||||
asn_geo_lookup: AsnGeoLookupConfig::Disabled,
|
||||
server_name: Default::default(),
|
||||
report_domain: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -148,8 +152,37 @@ impl FieldOrDefault {
|
|||
|
||||
impl Network {
|
||||
pub fn parse(config: &mut Config) -> Self {
|
||||
let server_name = config
|
||||
.value("server.hostname")
|
||||
.map(|v| v.to_string())
|
||||
.or_else(|| {
|
||||
config
|
||||
.value("lookup.default.hostname")
|
||||
.map(|v| v.to_lowercase())
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
hostname::get()
|
||||
.map(|v| v.to_string_lossy().to_lowercase())
|
||||
.unwrap_or_else(|_| "localhost".to_string())
|
||||
});
|
||||
let report_domain = config
|
||||
.value("report.domain")
|
||||
.map(|v| v.to_lowercase())
|
||||
.or_else(|| {
|
||||
config
|
||||
.value("lookup.default.domain")
|
||||
.map(|v| v.to_lowercase())
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
psl::domain_str(&server_name)
|
||||
.unwrap_or(server_name.as_str())
|
||||
.to_string()
|
||||
});
|
||||
|
||||
let mut network = Network {
|
||||
node_id: config.property("cluster.node-id").unwrap_or_default(),
|
||||
report_domain,
|
||||
server_name,
|
||||
security: Security::parse(config),
|
||||
contact_form: ContactForm::parse(config),
|
||||
asn_geo_lookup: AsnGeoLookupConfig::parse(config).unwrap_or_default(),
|
||||
|
|
|
@ -265,7 +265,7 @@ impl Scripting {
|
|||
|
||||
let hostname = config
|
||||
.value("sieve.trusted.hostname")
|
||||
.or_else(|| config.value("lookup.default.hostname"))
|
||||
.or_else(|| config.value("server.hostname"))
|
||||
.unwrap_or("localhost")
|
||||
.to_string();
|
||||
trusted_runtime.set_local_hostname(hostname.clone());
|
||||
|
@ -327,7 +327,7 @@ impl Scripting {
|
|||
IfBlock::new::<()>(
|
||||
"sieve.trusted.from-addr",
|
||||
[],
|
||||
"'MAILER-DAEMON@' + key_get('default', 'domain')",
|
||||
"'MAILER-DAEMON@' + config_get('report.domain')",
|
||||
)
|
||||
}),
|
||||
from_name: IfBlock::try_parse(config, "sieve.trusted.from-name", &token_map)
|
||||
|
@ -342,8 +342,8 @@ impl Scripting {
|
|||
"sieve.trusted.sign",
|
||||
[],
|
||||
concat!(
|
||||
"['rsa-' + key_get('default', 'domain'), ",
|
||||
"'ed25519-' + key_get('default', 'domain')]"
|
||||
"['rsa-' + config_get('report.domain'), ",
|
||||
"'ed25519-' + config_get('report.domain')]"
|
||||
),
|
||||
)
|
||||
},
|
||||
|
@ -363,7 +363,7 @@ impl Default for Scripting {
|
|||
from_addr: IfBlock::new::<()>(
|
||||
"sieve.trusted.from-addr",
|
||||
[],
|
||||
"'MAILER-DAEMON@' + key_get('default', 'domain')",
|
||||
"'MAILER-DAEMON@' + config_get('report.domain')",
|
||||
),
|
||||
from_name: IfBlock::new::<()>("sieve.trusted.from-name", [], "'Mailer Daemon'"),
|
||||
return_path: IfBlock::empty("sieve.trusted.return-path"),
|
||||
|
@ -371,8 +371,8 @@ impl Default for Scripting {
|
|||
"sieve.trusted.sign",
|
||||
[],
|
||||
concat!(
|
||||
"['rsa-' + key_get('default', 'domain'), ",
|
||||
"'ed25519-' + key_get('default', 'domain')]"
|
||||
"['rsa-' + config_get('report.domain'), ",
|
||||
"'ed25519-' + config_get('report.domain')]"
|
||||
),
|
||||
),
|
||||
untrusted_scripts: AHashMap::new(),
|
||||
|
|
|
@ -109,7 +109,7 @@ impl Default for MailAuthConfig {
|
|||
seal: IfBlock::new::<()>(
|
||||
"auth.arc.seal",
|
||||
[],
|
||||
"'rsa-' + key_get('default', 'domain')",
|
||||
"'rsa-' + config_get('report.domain')",
|
||||
),
|
||||
},
|
||||
spf: SpfAuthConfig {
|
||||
|
|
|
@ -134,11 +134,7 @@ impl Default for QueueConfig {
|
|||
),
|
||||
notify: IfBlock::new::<()>("queue.schedule.notify", [], "[1d, 3d]"),
|
||||
expire: IfBlock::new::<()>("queue.schedule.expire", [], "5d"),
|
||||
hostname: IfBlock::new::<()>(
|
||||
"queue.outbound.hostname",
|
||||
[],
|
||||
"key_get('default', 'hostname')",
|
||||
),
|
||||
hostname: IfBlock::new::<()>("queue.outbound.hostname", [], "config_get('server.hostname')"),
|
||||
next_hop: IfBlock::new::<()>(
|
||||
"queue.outbound.next-hop",
|
||||
#[cfg(not(feature = "test_mode"))]
|
||||
|
@ -187,12 +183,12 @@ impl Default for QueueConfig {
|
|||
address: IfBlock::new::<()>(
|
||||
"report.dsn.from-address",
|
||||
[],
|
||||
"'MAILER-DAEMON@' + key_get('default', 'domain')",
|
||||
"'MAILER-DAEMON@' + config_get('report.domain')",
|
||||
),
|
||||
sign: IfBlock::new::<()>(
|
||||
"report.dsn.sign",
|
||||
[],
|
||||
"['rsa-' + key_get('default', 'domain'), 'ed25519-' + key_get('default', 'domain')]",
|
||||
"['rsa-' + config_get('report.domain'), 'ed25519-' + config_get('report.domain')]",
|
||||
),
|
||||
},
|
||||
timeout: QueueOutboundTimeout {
|
||||
|
|
|
@ -79,7 +79,7 @@ impl ReportConfig {
|
|||
&TokenMap::default().with_variables(RCPT_DOMAIN_VARS),
|
||||
)
|
||||
.unwrap_or_else(|| {
|
||||
IfBlock::new::<()>("report.submitter", [], "key_get('default', 'hostname')")
|
||||
IfBlock::new::<()>("report.submitter", [], "config_get('server.hostname')")
|
||||
}),
|
||||
analysis: ReportAnalysis {
|
||||
addresses: config
|
||||
|
@ -118,7 +118,7 @@ impl Report {
|
|||
address: IfBlock::new::<()>(
|
||||
format!("report.{id}.from-address"),
|
||||
[],
|
||||
format!("'noreply-{id}@' + key_get('default', 'domain')"),
|
||||
format!("'noreply-{id}@' + config_get('report.domain')"),
|
||||
),
|
||||
subject: IfBlock::new::<()>(
|
||||
format!("report.{id}.subject"),
|
||||
|
@ -131,7 +131,7 @@ impl Report {
|
|||
sign: IfBlock::new::<()>(
|
||||
format!("report.{id}.sign"),
|
||||
[],
|
||||
"['rsa-' + key_get('default', 'domain'), 'ed25519-' + key_get('default', 'domain')]",
|
||||
"['rsa-' + config_get('report.domain'), 'ed25519-' + config_get('report.domain')]",
|
||||
),
|
||||
send: IfBlock::new::<()>(format!("report.{id}.send"), [], "[1, 1d]"),
|
||||
};
|
||||
|
@ -164,12 +164,12 @@ impl AggregateReport {
|
|||
address: IfBlock::new::<()>(
|
||||
format!("report.{id}.aggregate.from-address"),
|
||||
[],
|
||||
format!("'noreply-{id}@' + key_get('default', 'domain')"),
|
||||
format!("'noreply-{id}@' + config_get('report.domain')"),
|
||||
),
|
||||
org_name: IfBlock::new::<()>(
|
||||
format!("report.{id}.aggregate.org-name"),
|
||||
[],
|
||||
"key_get('default', 'domain')",
|
||||
"config_get('report.domain')",
|
||||
),
|
||||
contact_info: IfBlock::empty(format!("report.{id}.aggregate.contact-info")),
|
||||
send: IfBlock::new::<AggregateFrequency>(
|
||||
|
@ -180,7 +180,7 @@ impl AggregateReport {
|
|||
sign: IfBlock::new::<()>(
|
||||
format!("report.{id}.aggregate.sign"),
|
||||
[],
|
||||
"['rsa-' + key_get('default', 'domain'), 'ed25519-' + key_get('default', 'domain')]",
|
||||
"['rsa-' + config_get('report.domain'), 'ed25519-' + config_get('report.domain')]",
|
||||
),
|
||||
max_size: IfBlock::new::<()>(format!("report.{id}.aggregate.max-size"), [], "26214400"),
|
||||
};
|
||||
|
|
|
@ -702,13 +702,13 @@ impl Default for SessionConfig {
|
|||
hostname: IfBlock::new::<()>(
|
||||
"server.connect.hostname",
|
||||
[],
|
||||
"key_get('default', 'hostname')",
|
||||
"config_get('server.hostname')",
|
||||
),
|
||||
script: IfBlock::empty("session.connect.script"),
|
||||
greeting: IfBlock::new::<()>(
|
||||
"session.connect.greeting",
|
||||
[],
|
||||
"key_get('default', 'hostname') + ' Stalwart ESMTP at your service'",
|
||||
"config_get('server.hostname') + ' Stalwart ESMTP at your service'",
|
||||
),
|
||||
},
|
||||
ehlo: Ehlo {
|
||||
|
|
|
@ -37,7 +37,9 @@ impl Enterprise {
|
|||
stores: &Stores,
|
||||
data: &Store,
|
||||
) -> Option<Self> {
|
||||
let server_hostname = config.value("lookup.default.hostname")?;
|
||||
let server_hostname = config
|
||||
.value("server.hostname")
|
||||
.or_else(|| config.value("lookup.default.hostname"))?;
|
||||
let mut update_license = None;
|
||||
|
||||
let license_result = match (
|
||||
|
|
|
@ -14,12 +14,12 @@ use crate::Server;
|
|||
use super::{
|
||||
functions::{ResolveVariable, FUNCTIONS},
|
||||
if_block::IfBlock,
|
||||
BinaryOperator, Constant, Expression, ExpressionItem, UnaryOperator, Variable,
|
||||
BinaryOperator, Constant, Expression, ExpressionItem, Setting, UnaryOperator, Variable,
|
||||
};
|
||||
|
||||
impl Server {
|
||||
pub async fn eval_if<'x, R: TryFrom<Variable<'x>>, V: ResolveVariable>(
|
||||
&self,
|
||||
&'x self,
|
||||
if_block: &'x IfBlock,
|
||||
resolver: &'x V,
|
||||
session_id: u64,
|
||||
|
@ -81,7 +81,7 @@ impl Server {
|
|||
}
|
||||
|
||||
pub async fn eval_expr<'x, R: TryFrom<Variable<'x>>, V: ResolveVariable>(
|
||||
&self,
|
||||
&'x self,
|
||||
expr: &'x Expression,
|
||||
resolver: &'x V,
|
||||
expr_id: &str,
|
||||
|
@ -137,15 +137,15 @@ impl Server {
|
|||
}
|
||||
}
|
||||
|
||||
struct EvalContext<'x, 'y, V: ResolveVariable, T, C> {
|
||||
struct EvalContext<'x, V: ResolveVariable, T, C> {
|
||||
resolver: &'x V,
|
||||
core: &'y Server,
|
||||
core: &'x Server,
|
||||
expr: &'x T,
|
||||
captures: C,
|
||||
session_id: u64,
|
||||
}
|
||||
|
||||
impl<'x, V: ResolveVariable> EvalContext<'x, '_, V, IfBlock, Vec<String>> {
|
||||
impl<'x, V: ResolveVariable> EvalContext<'x, V, IfBlock, Vec<String>> {
|
||||
async fn eval(&mut self) -> trc::Result<Variable<'x>> {
|
||||
for if_then in &self.expr.if_then {
|
||||
if (EvalContext {
|
||||
|
@ -183,7 +183,7 @@ impl<'x, V: ResolveVariable> EvalContext<'x, '_, V, IfBlock, Vec<String>> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'x, V: ResolveVariable> EvalContext<'x, '_, V, Expression, &mut Vec<String>> {
|
||||
impl<'x, V: ResolveVariable> EvalContext<'x, V, Expression, &mut Vec<String>> {
|
||||
async fn eval(&mut self) -> trc::Result<Variable<'x>> {
|
||||
let mut stack = Vec::new();
|
||||
let mut exprs = self.expr.items.iter();
|
||||
|
@ -208,6 +208,25 @@ impl<'x, V: ResolveVariable> EvalContext<'x, '_, V, Expression, &mut Vec<String>
|
|||
.to_string(),
|
||||
)));
|
||||
}
|
||||
ExpressionItem::Setting(setting) => match setting {
|
||||
Setting::Hostname => {
|
||||
stack.push(self.core.core.network.server_name.as_str().into())
|
||||
}
|
||||
Setting::ReportDomain => {
|
||||
stack.push(self.core.core.network.report_domain.as_str().into())
|
||||
}
|
||||
Setting::NodeId => stack.push(self.core.core.network.node_id.into()),
|
||||
Setting::Other(key) => stack.push(
|
||||
self.core
|
||||
.core
|
||||
.storage
|
||||
.config
|
||||
.get(key)
|
||||
.await?
|
||||
.unwrap_or_default()
|
||||
.into(),
|
||||
),
|
||||
},
|
||||
ExpressionItem::UnaryOperator(op) => {
|
||||
let value = stack.pop().unwrap_or_default();
|
||||
stack.push(match op {
|
||||
|
|
|
@ -88,6 +88,7 @@ pub struct Expression {
|
|||
pub enum ExpressionItem {
|
||||
Variable(u32),
|
||||
Global(String),
|
||||
Setting(Setting),
|
||||
Capture(u32),
|
||||
Constant(Constant),
|
||||
BinaryOperator(BinaryOperator),
|
||||
|
@ -200,6 +201,7 @@ pub enum Token {
|
|||
num_args: u32,
|
||||
},
|
||||
Constant(Constant),
|
||||
Setting(Setting),
|
||||
Regex(Regex),
|
||||
BinaryOperator(BinaryOperator),
|
||||
UnaryOperator(UnaryOperator),
|
||||
|
@ -210,6 +212,25 @@ pub enum Token {
|
|||
Comma,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Setting {
|
||||
Hostname,
|
||||
ReportDomain,
|
||||
NodeId,
|
||||
Other(String),
|
||||
}
|
||||
|
||||
impl From<String> for Setting {
|
||||
fn from(value: String) -> Self {
|
||||
match value.as_str() {
|
||||
"server.hostname" => Setting::Hostname,
|
||||
"report.domain" => Setting::ReportDomain,
|
||||
"cluster.node-id" => Setting::NodeId,
|
||||
_ => Setting::Other(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Variable<'_> {
|
||||
fn from(value: usize) -> Self {
|
||||
Variable::Integer(value as i64)
|
||||
|
|
|
@ -109,6 +109,16 @@ impl<'x> ExpressionParser<'x> {
|
|||
self.output.push(ExpressionItem::Regex(regex.clone()));
|
||||
self.operator_stack.pop();
|
||||
}
|
||||
Some((Token::Setting(setting), _)) => {
|
||||
if self.arg_count.pop().unwrap() != 0 {
|
||||
return Err(
|
||||
"Expression function \"config_get\" expected 1 argument"
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
self.output.push(ExpressionItem::Setting(setting.clone()));
|
||||
self.operator_stack.pop();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
@ -156,16 +166,10 @@ impl<'x> ExpressionParser<'x> {
|
|||
self.operator_stack
|
||||
.push((Token::BinaryOperator(bop), jmp_pos));
|
||||
}
|
||||
Token::Function { id, name, num_args } => {
|
||||
token @ (Token::Function { .. } | Token::Regex(_) | Token::Setting(_)) => {
|
||||
self.inc_arg_count();
|
||||
self.arg_count.push(0);
|
||||
self.operator_stack
|
||||
.push((Token::Function { id, name, num_args }, None))
|
||||
}
|
||||
Token::Regex(regex) => {
|
||||
self.inc_arg_count();
|
||||
self.arg_count.push(0);
|
||||
self.operator_stack.push((Token::Regex(regex), None))
|
||||
self.operator_stack.push((token, None))
|
||||
}
|
||||
Token::OpenBracket => {
|
||||
// Array functions
|
||||
|
|
|
@ -100,6 +100,13 @@ impl<'x> Tokenizer<'x> {
|
|||
self.buf.clear();
|
||||
self.find_char(b",")?;
|
||||
(Token::Regex(regex).into(), b'(')
|
||||
} else if ch == b'(' && self.buf.eq(b"config_get") {
|
||||
// Parse setting
|
||||
let stop_ch = self.find_char(b"\"'")?;
|
||||
let setting_str = self.parse_string(stop_ch)?;
|
||||
self.has_alpha = false;
|
||||
self.buf.clear();
|
||||
(Token::Setting(Setting::from(setting_str)).into(), b'(')
|
||||
} else if !self.buf.is_empty() {
|
||||
self.is_start = false;
|
||||
(self.parse_buf()?.into(), ch)
|
||||
|
|
|
@ -195,18 +195,6 @@ impl BootManager {
|
|||
StoreOp::None => {
|
||||
// Add hostname lookup if missing
|
||||
let mut insert_keys = Vec::new();
|
||||
if config
|
||||
.value("lookup.default.hostname")
|
||||
.filter(|v| !v.is_empty())
|
||||
.is_none()
|
||||
{
|
||||
insert_keys.push(ConfigKey::from((
|
||||
"lookup.default.hostname",
|
||||
hostname::get()
|
||||
.map(|v| v.to_string_lossy().into_owned())
|
||||
.unwrap_or_else(|_| "localhost".to_string()),
|
||||
)));
|
||||
}
|
||||
|
||||
// Generate an OAuth key if missing
|
||||
if config
|
||||
|
|
|
@ -423,7 +423,7 @@ impl ConfigManager {
|
|||
required_semver = value.as_str().try_into().unwrap_or_default();
|
||||
} else if key.starts_with("spam-filter.")
|
||||
|| key.starts_with("http-lookup.")
|
||||
|| (key.starts_with("lookup.") && !key.starts_with("lookup.default."))
|
||||
|| key.starts_with("lookup.")
|
||||
|| key.starts_with("asn.")
|
||||
{
|
||||
external.keys.push(ConfigKey::from((key, value)));
|
||||
|
@ -537,7 +537,6 @@ impl Patterns {
|
|||
Pattern::Include(MatchType::Equal("storage.lookup".to_string())),
|
||||
Pattern::Include(MatchType::Equal("storage.fts".to_string())),
|
||||
Pattern::Include(MatchType::Equal("storage.directory".to_string())),
|
||||
Pattern::Include(MatchType::Equal("lookup.default.hostname".to_string())),
|
||||
Pattern::Include(MatchType::Equal("enterprise.license-key".to_string())),
|
||||
];
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ impl SmtpDirectory {
|
|||
is_lmtp,
|
||||
credentials: None,
|
||||
local_host: config
|
||||
.value("lookup.default.hostname")
|
||||
.value("server.hostname")
|
||||
.unwrap_or("[127.0.0.1]")
|
||||
.to_string(),
|
||||
say_ehlo: false,
|
||||
|
|
|
@ -180,17 +180,7 @@ impl Autoconfig for Server {
|
|||
})?;
|
||||
|
||||
// Obtain server name
|
||||
let server_name = self
|
||||
.core
|
||||
.storage
|
||||
.config
|
||||
.get("lookup.default.hostname")
|
||||
.await?
|
||||
.ok_or_else(|| {
|
||||
trc::EventType::Config(trc::ConfigEvent::BuildError)
|
||||
.caused_by(trc::location!())
|
||||
.details("Server name not configured")
|
||||
})?;
|
||||
let server_name = self.core.network.server_name.to_string();
|
||||
|
||||
// Find the account name by e-mail address
|
||||
let mut account_name = emailaddress.to_string();
|
||||
|
|
|
@ -77,13 +77,7 @@ impl DnsManagement for Server {
|
|||
|
||||
async fn build_dns_records(&self, domain_name: &str) -> trc::Result<Vec<DnsRecord>> {
|
||||
// Obtain server name
|
||||
let server_name = self
|
||||
.core
|
||||
.storage
|
||||
.config
|
||||
.get("lookup.default.hostname")
|
||||
.await?
|
||||
.unwrap_or_else(|| "localhost".to_string());
|
||||
let server_name = &self.core.network.server_name;
|
||||
let mut records = Vec::new();
|
||||
|
||||
// Obtain DKIM keys
|
||||
|
|
|
@ -146,6 +146,21 @@ impl PrincipalManager for Server {
|
|||
}
|
||||
}
|
||||
|
||||
// Set default report domain if missing
|
||||
let report_domain = if principal.typ() == Type::Domain
|
||||
&& self
|
||||
.core
|
||||
.storage
|
||||
.config
|
||||
.get("report.domain")
|
||||
.await
|
||||
.is_ok_and(|v| v.is_none())
|
||||
{
|
||||
principal.name().to_lowercase().into()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Create principal
|
||||
let result = self
|
||||
.core
|
||||
|
@ -154,6 +169,19 @@ impl PrincipalManager for Server {
|
|||
.create_principal(principal, tenant_id, Some(&access_token.permissions))
|
||||
.await?;
|
||||
|
||||
// Set report domain
|
||||
if let Some(report_domain) = report_domain {
|
||||
if let Err(err) = self
|
||||
.core
|
||||
.storage
|
||||
.config
|
||||
.set([("report.domain", report_domain)], true)
|
||||
.await
|
||||
{
|
||||
trc::error!(err.details("Failed to set report domain"));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(JsonResponse::new(json!({
|
||||
"data": result,
|
||||
}))
|
||||
|
|
|
@ -132,14 +132,7 @@ impl ManageSpamHandler for Server {
|
|||
let ehlo_domain = request.ehlo_domain.to_lowercase();
|
||||
let mail_from = request.env_from.to_lowercase();
|
||||
let mail_from_domain = mail_from.rsplit_once('@').map(|(_, domain)| domain);
|
||||
let local_host = self
|
||||
.core
|
||||
.storage
|
||||
.config
|
||||
.get("lookup.default.hostname")
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
.unwrap_or_else(|| "local.host".to_string());
|
||||
let local_host = &self.core.network.server_name;
|
||||
|
||||
let spf_ehlo_result =
|
||||
self.core
|
||||
|
@ -147,7 +140,7 @@ impl ManageSpamHandler for Server {
|
|||
.resolvers
|
||||
.dns
|
||||
.verify_spf(self.inner.cache.build_auth_parameters(
|
||||
SpfParameters::verify_ehlo(remote_ip, &ehlo_domain, &local_host),
|
||||
SpfParameters::verify_ehlo(remote_ip, &ehlo_domain, local_host),
|
||||
))
|
||||
.await;
|
||||
|
||||
|
@ -168,7 +161,7 @@ impl ManageSpamHandler for Server {
|
|||
remote_ip,
|
||||
mail_from_domain,
|
||||
&ehlo_domain,
|
||||
&local_host,
|
||||
local_host,
|
||||
&mail_from,
|
||||
)))
|
||||
.await
|
||||
|
@ -181,7 +174,7 @@ impl ManageSpamHandler for Server {
|
|||
remote_ip,
|
||||
&ehlo_domain,
|
||||
&ehlo_domain,
|
||||
&local_host,
|
||||
local_host,
|
||||
&format!("postmaster@{ehlo_domain}"),
|
||||
)))
|
||||
.await
|
||||
|
|
|
@ -318,14 +318,7 @@ async fn delivery_troubleshoot(
|
|||
(domain_or_email, None)
|
||||
};
|
||||
|
||||
let local_host = server
|
||||
.core
|
||||
.storage
|
||||
.config
|
||||
.get("lookup.default.hostname")
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
.unwrap_or_else(|| "local.host".to_string());
|
||||
let local_host = &server.core.network.server_name;
|
||||
|
||||
tx.send(DeliveryStage::MxLookupStart {
|
||||
domain: domain.to_string(),
|
||||
|
@ -897,14 +890,7 @@ async fn dmarc_troubleshoot(
|
|||
let mail_from = request.mail_from.to_lowercase();
|
||||
let mail_from_domain = mail_from.rsplit_once('@').map(|(_, domain)| domain);
|
||||
|
||||
let local_host = server
|
||||
.core
|
||||
.storage
|
||||
.config
|
||||
.get("lookup.default.hostname")
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
.unwrap_or_else(|| "local.host".to_string());
|
||||
let local_host = &server.core.network.server_name;
|
||||
|
||||
let now = Instant::now();
|
||||
let ehlo_spf_output = server
|
||||
|
@ -919,7 +905,7 @@ async fn dmarc_troubleshoot(
|
|||
.build_auth_parameters(SpfParameters::verify_ehlo(
|
||||
remote_ip,
|
||||
&ehlo_domain,
|
||||
&local_host,
|
||||
local_host,
|
||||
)),
|
||||
)
|
||||
.await;
|
||||
|
@ -941,7 +927,7 @@ async fn dmarc_troubleshoot(
|
|||
remote_ip,
|
||||
mail_from_domain,
|
||||
&ehlo_domain,
|
||||
&local_host,
|
||||
local_host,
|
||||
&mail_from,
|
||||
)))
|
||||
.await
|
||||
|
@ -955,7 +941,7 @@ async fn dmarc_troubleshoot(
|
|||
remote_ip,
|
||||
&ehlo_domain,
|
||||
&ehlo_domain,
|
||||
&local_host,
|
||||
local_host,
|
||||
&format!("postmaster@{ehlo_domain}"),
|
||||
)))
|
||||
.await
|
||||
|
|
|
@ -56,7 +56,7 @@ use crate::{
|
|||
};
|
||||
|
||||
const SERVER: &str = r#"
|
||||
[lookup.default]
|
||||
[server]
|
||||
hostname = "imap.example.org"
|
||||
|
||||
[server.listener.imap]
|
||||
|
|
|
@ -29,15 +29,15 @@ const CONFIG: &str = r#"
|
|||
[session.rcpt]
|
||||
relay = true
|
||||
|
||||
[lookup.default]
|
||||
domain = "example.org"
|
||||
[server]
|
||||
hostname = "mx.example.org"
|
||||
|
||||
[report]
|
||||
submitter = "'mx.example.org'"
|
||||
|
||||
[report.dmarc.aggregate]
|
||||
from-name = "'DMARC Report'"
|
||||
from-address = "'reports@' + key_get('default', 'domain')"
|
||||
from-address = "'reports@' + config_get('report.domain')"
|
||||
org-name = "'Foobar, Inc.'"
|
||||
contact-info = "'https://foobar.org/contact'"
|
||||
send = "daily"
|
||||
|
|
Loading…
Add table
Reference in a new issue