1 parent
5b22add1f3
commit
2c98b8f925
38 files changed
+915
-87
No files matched your search
+62
-12
@@ -218,6 +218,18 @@ pub struct AppConfig {
|
||||
#[serde(default)]
|
||||
pub base_path: Option<String>,
|
||||
|
||||
#[serde(default = "default_feature_enabled")]
|
||||
pub sieve_enabled: bool,
|
||||
|
||||
#[serde(default = "default_feature_enabled")]
|
||||
pub diagnostics_enabled: bool,
|
||||
|
||||
#[serde(default = "default_feature_enabled")]
|
||||
pub about_enabled: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub security_headers_enabled: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub sieve_host: Option<String>,
|
||||
|
||||
@@ -406,6 +418,10 @@ fn default_interface_skin() -> String {
|
||||
"rustbox".to_string()
|
||||
}
|
||||
|
||||
fn default_feature_enabled() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn default_sieve_port() -> u16 {
|
||||
4190
|
||||
}
|
||||
@@ -470,6 +486,10 @@ impl Default for AppConfig {
|
||||
default_theme: default_theme(),
|
||||
default_interface_skin: default_interface_skin(),
|
||||
base_path: None,
|
||||
sieve_enabled: true,
|
||||
diagnostics_enabled: true,
|
||||
about_enabled: true,
|
||||
security_headers_enabled: false,
|
||||
sieve_host: None,
|
||||
sieve_port: default_sieve_port(),
|
||||
sieve_tls_mode: default_sieve_tls_mode(),
|
||||
@@ -654,8 +674,12 @@ impl AppConfig {
|
||||
{
|
||||
return Err("IMAP_HOST / imap_host must be configured".to_string());
|
||||
}
|
||||
if self.port == 0 || self.imap_port == 0 || self.smtp_port == 0 || self.sieve_port == 0 {
|
||||
return Err("network ports must be greater than zero".to_string());
|
||||
if self.port == 0
|
||||
|| self.imap_port == 0
|
||||
|| self.smtp_port == 0
|
||||
|| (self.sieve_enabled && self.sieve_port == 0)
|
||||
{
|
||||
return Err("enabled network ports must be greater than zero".to_string());
|
||||
}
|
||||
if let Some(log_dir) = self.log_dir.as_deref() {
|
||||
let log_dir = log_dir.trim();
|
||||
@@ -925,16 +949,18 @@ impl AppConfig {
|
||||
) {
|
||||
return Err("DEFAULT_INTERFACE_SKIN must be one of: rustbox, roundcube-classic, roundcube-larry, roundcube-elastic, clean, gmail, proton, zoho, outlook, minimal, graphite, high-contrast, fastmail, apple-mail, yahoo, hey, nord, github, gitlab, discord, slack, reddit, notion".to_string());
|
||||
}
|
||||
if !matches!(
|
||||
self.sieve_tls_mode.as_str(),
|
||||
"starttls" | "implicit" | "none"
|
||||
) {
|
||||
return Err("SIEVE_TLS_MODE must be one of: starttls, implicit, none".to_string());
|
||||
}
|
||||
if self.sieve_tls_mode == "none" && !self.sieve_allow_insecure_auth {
|
||||
tracing::warn!(
|
||||
"ManageSieve plaintext transport selected; authentication will remain blocked until SIEVE_ALLOW_INSECURE_AUTH=true"
|
||||
);
|
||||
if self.sieve_enabled {
|
||||
if !matches!(
|
||||
self.sieve_tls_mode.as_str(),
|
||||
"starttls" | "implicit" | "none"
|
||||
) {
|
||||
return Err("SIEVE_TLS_MODE must be one of: starttls, implicit, none".to_string());
|
||||
}
|
||||
if self.sieve_tls_mode == "none" && !self.sieve_allow_insecure_auth {
|
||||
tracing::warn!(
|
||||
"ManageSieve plaintext transport selected; authentication will remain blocked until SIEVE_ALLOW_INSECURE_AUTH=true"
|
||||
);
|
||||
}
|
||||
}
|
||||
self.parsed_outgoing_headers()?;
|
||||
if self.pgp_network_timeout_secs == 0 || self.pgp_network_timeout_secs > 60 {
|
||||
@@ -993,6 +1019,10 @@ mod tests {
|
||||
assert_eq!(config.environment, "development");
|
||||
assert_eq!(config.default_theme, "system");
|
||||
assert_eq!(config.default_interface_skin, "rustbox");
|
||||
assert!(config.sieve_enabled);
|
||||
assert!(config.diagnostics_enabled);
|
||||
assert!(config.about_enabled);
|
||||
assert!(!config.security_headers_enabled);
|
||||
assert!(config.sieve_host.is_none());
|
||||
assert_eq!(config.sieve_port, 4190);
|
||||
assert_eq!(config.sieve_tls_mode, "starttls");
|
||||
@@ -1029,6 +1059,10 @@ mod tests {
|
||||
.merge(("environment", "production"))
|
||||
.merge(("default_theme", "light"))
|
||||
.merge(("default_interface_skin", "gmail"))
|
||||
.merge(("sieve_enabled", false))
|
||||
.merge(("diagnostics_enabled", false))
|
||||
.merge(("about_enabled", false))
|
||||
.merge(("security_headers_enabled", true))
|
||||
.merge(("sieve_host", "sieve.example.com"))
|
||||
.merge(("sieve_port", 4191u16))
|
||||
.merge(("sieve_tls_mode", "implicit"))
|
||||
@@ -1056,6 +1090,10 @@ mod tests {
|
||||
assert_eq!(config.environment, "production");
|
||||
assert_eq!(config.default_theme, "light");
|
||||
assert_eq!(config.default_interface_skin, "gmail");
|
||||
assert!(!config.sieve_enabled);
|
||||
assert!(!config.diagnostics_enabled);
|
||||
assert!(!config.about_enabled);
|
||||
assert!(config.security_headers_enabled);
|
||||
assert_eq!(config.sieve_host.as_deref(), Some("sieve.example.com"));
|
||||
assert_eq!(config.sieve_port, 4191);
|
||||
assert_eq!(config.sieve_tls_mode, "implicit");
|
||||
@@ -1082,6 +1120,18 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disabled_sieve_skips_sieve_specific_validation() {
|
||||
let config = AppConfig {
|
||||
imap_host: Some("imap.example.com".to_string()),
|
||||
sieve_enabled: false,
|
||||
sieve_port: 0,
|
||||
sieve_tls_mode: "unsupported".to_string(),
|
||||
..AppConfig::default()
|
||||
};
|
||||
assert!(config.validate().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_default_theme_is_rejected() {
|
||||
let config = AppConfig {
|
||||
|
||||
Reference in new issue
Block a user