From a3ad927a213cf6f272ef8f46b6a0bbd99a223a03 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Sat, 4 Apr 2026 17:29:45 -0300 Subject: [PATCH] fix: remove mime crate dependency, use lettre ContentType for mime types --- src/email/types.rs | 59 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/src/email/types.rs b/src/email/types.rs index 0fe45e56..d635139b 100644 --- a/src/email/types.rs +++ b/src/email/types.rs @@ -383,9 +383,7 @@ impl EmailService { file_data: Vec, filename: &str, ) -> Result<(), String> { - use lettre::message::{ - header::ContentType, Attachment, Body, Message, MultiPart, SinglePart, - }; + use lettre::message::{header::ContentType, Attachment, Body, Message, MultiPart, SinglePart}; use lettre::transport::smtp::authentication::Credentials; use lettre::{SmtpTransport, Transport}; @@ -403,6 +401,61 @@ impl EmailService { return Err("SMTP not configured: set email credentials in Vault".into()); } + let mime_str = match filename.split('.').last().unwrap_or("") { + "pdf" => "application/pdf", + "png" => "image/png", + "jpg" | "jpeg" => "image/jpeg", + "gif" => "image/gif", + "txt" => "text/plain", + "csv" => "text/csv", + "html" => "text/html", + "xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + _ => "application/octet-stream", + }; + let mime_type = mime_str + .parse::() + .unwrap_or(ContentType::APPLICATION_OCTET_STREAM); + + let email = Message::builder() + .from( + smtp_from + .parse() + .map_err(|e| format!("Invalid from address: {}", e))?, + ) + .to(to + .parse() + .map_err(|e| format!("Invalid to address: {}", e))?) + .subject(subject) + .multipart( + MultiPart::mixed() + .singlepart(SinglePart::html(body.to_string())) + .singlepart(Attachment::new(filename.to_string()).body(Body::new(file_data), mime_type)), + ) + .map_err(|e| format!("Failed to build email: {}", e))?; + + let mailer = if !smtp_user.is_empty() && !smtp_pass.is_empty() { + let creds = Credentials::new(smtp_user, smtp_pass); + SmtpTransport::relay(&smtp_host) + .map_err(|e| format!("SMTP relay error: {}", e))? + .port(smtp_port) + .credentials(creds) + .build() + } else { + SmtpTransport::relay(&smtp_host) + .map_err(|e| format!("SMTP relay error: {}", e))? + .port(smtp_port) + .build() + }; + + mailer + .send(&email) + .map_err(|e| format!("Failed to send email: {}", e))?; + + info!("Email with attachment sent to {} (bot {})", to, bot_id); + Ok(()) + } + let mime_type: mime::Mime = filename .split('.') .last()