use lombok::{Builder, Getter, Setter}; #[derive( serde::Deserialize, serde::Serialize, Debug, Clone, PartialEq, Eq, Getter, Setter, Builder, )] #[serde(default)] pub struct AppEmailSettings { pub enabled: bool, pub smtp_host: String, pub smtp_port: u16, pub smtp_username: Option, pub smtp_password: Option, pub from_address: String, pub from_name: Option, pub connection_timeout_ms: u64, pub response_timeout_ms: u64, pub template_dir: Option, pub default_locale: String, pub max_attachment_bytes: usize, pub subscriber_group_id: String, pub auto_offset_reset: String, } impl Default for AppEmailSettings { fn default() -> Self { Self { enabled: true, smtp_host: "127.0.0.1".to_string(), smtp_port: 587, smtp_username: None, smtp_password: None, from_address: "no-reply@example.com".to_string(), from_name: Some("No Reply".to_string()), connection_timeout_ms: 5_000, response_timeout_ms: 10_000, template_dir: None, default_locale: "en".to_string(), max_attachment_bytes: 25 * 1024 * 1024, subscriber_group_id: "email-service".to_string(), auto_offset_reset: "earliest".to_string(), } } } impl AppEmailSettings { pub fn is_valid(&self) -> Result<(), String> { if !self.enabled { return Ok(()); } if self.smtp_host.trim().is_empty() { return Err("smtp_host must not be empty when enabled".to_string()); } if self.smtp_port == 0 { return Err("smtp_port must be > 0".to_string()); } if self.from_address.trim().is_empty() { return Err("from_address must not be empty".to_string()); } if self.max_attachment_bytes == 0 { return Err("max_attachment_bytes must be > 0".to_string()); } match self.auto_offset_reset.as_str() { "earliest" | "latest" | "none" => {} other => { return Err(format!( "auto_offset_reset must be earliest|latest|none, got {other}" )); } } if self.subscriber_group_id.is_empty() { return Err("subscriber_group_id must not be empty".to_string()); } Ok(()) } }