use crate::config::NotificationConfig; use anyhow::Result; use chrono::Utc; use lettre::transport::smtp::SmtpTransport; use lettre::{Message, Transport}; use tracing::{debug, error, info}; /// Manages notifications pub struct NotificationManager { config: NotificationConfig, } impl NotificationManager { pub fn new(config: &NotificationConfig, _hostname: &str) -> Result { Ok(Self { config: config.clone(), }) } pub async fn send_direct_email(&mut self, subject: &str, body: &str) -> Result<()> { if !self.config.enabled { return Ok(()); } if self.is_maintenance_mode() { debug!("Maintenance mode active, suppressing email notification"); return Ok(()); } let hostname = gethostname::gethostname() .to_string_lossy() .to_string(); let from_email = self.config.from_email.replace("{hostname}", &hostname); let email_body = format!( "{}\n\n--\nCM Dashboard Agent\nGenerated at {}", body, Utc::now().format("%Y-%m-%d %H:%M:%S %Z") ); let email = Message::builder() .from(from_email.parse()?) .to(self.config.to_email.parse()?) .subject(subject) .body(email_body)?; let mailer = SmtpTransport::unencrypted_localhost(); match mailer.send(&email) { Ok(_) => info!("Direct email sent successfully: {}", subject), Err(e) => { error!("Failed to send email: {}", e); return Err(e.into()); } } Ok(()) } fn is_maintenance_mode(&self) -> bool { std::fs::metadata(&self.config.maintenance_mode_file).is_ok() } }