feat: alerter module SMTP avec lettre
This commit is contained in:
124
src/alerter.rs
124
src/alerter.rs
@@ -1 +1,123 @@
|
|||||||
// Alerter module — Task 3
|
use crate::config::SmtpConfig;
|
||||||
|
use lettre::{
|
||||||
|
message::header::ContentType,
|
||||||
|
transport::smtp::authentication::Credentials,
|
||||||
|
AsyncSmtpTransport, AsyncTransport, Message, Tokio1Executor,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn is_smtp_configured(smtp: &SmtpConfig) -> bool {
|
||||||
|
!smtp.server.is_empty() && !smtp.from_email.is_empty() && !smtp.to_emails.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Alerter;
|
||||||
|
|
||||||
|
impl Alerter {
|
||||||
|
pub async fn send(&self, smtp: &SmtpConfig, subject: &str, body: &str) -> (bool, String) {
|
||||||
|
if !is_smtp_configured(smtp) {
|
||||||
|
return (false, "SMTP non configure".into());
|
||||||
|
}
|
||||||
|
match self.send_email(smtp, subject, body).await {
|
||||||
|
Ok(msg) => (true, msg),
|
||||||
|
Err(e) => (false, e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn send_email(
|
||||||
|
&self,
|
||||||
|
smtp: &SmtpConfig,
|
||||||
|
subject: &str,
|
||||||
|
body: &str,
|
||||||
|
) -> Result<String, String> {
|
||||||
|
let from = smtp
|
||||||
|
.from_email
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| "Email expediteur invalide".to_string())?;
|
||||||
|
|
||||||
|
let mut builder = Message::builder().from(from).subject(subject);
|
||||||
|
for recipient in &smtp.to_emails {
|
||||||
|
let mb = recipient
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| format!("Destinataire invalide: {}", recipient))?;
|
||||||
|
builder = builder.to(mb);
|
||||||
|
}
|
||||||
|
let email = builder
|
||||||
|
.header(ContentType::TEXT_PLAIN)
|
||||||
|
.body(body.to_string())
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let transport = self.build_transport(smtp)?;
|
||||||
|
transport
|
||||||
|
.send(email)
|
||||||
|
.await
|
||||||
|
.map(|_| "Email envoye avec succes".to_string())
|
||||||
|
.map_err(|e| format!("Erreur SMTP: {}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_transport(
|
||||||
|
&self,
|
||||||
|
smtp: &SmtpConfig,
|
||||||
|
) -> Result<AsyncSmtpTransport<Tokio1Executor>, String> {
|
||||||
|
let mut builder = if smtp.use_tls {
|
||||||
|
AsyncSmtpTransport::<Tokio1Executor>::starttls_relay(&smtp.server)
|
||||||
|
.map_err(|e| e.to_string())?
|
||||||
|
} else {
|
||||||
|
AsyncSmtpTransport::<Tokio1Executor>::builder_dangerous(&smtp.server)
|
||||||
|
};
|
||||||
|
|
||||||
|
builder = builder.port(smtp.port);
|
||||||
|
|
||||||
|
if !smtp.username.is_empty() {
|
||||||
|
builder = builder.credentials(Credentials::new(
|
||||||
|
smtp.username.clone(),
|
||||||
|
smtp.password.clone(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(builder.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_test(&self, smtp: &SmtpConfig) -> (bool, String) {
|
||||||
|
let subject = "[TEST] Supervision - Test de configuration email";
|
||||||
|
let body = "Ceci est un email de test.\n\nSi vous recevez ce message, la configuration SMTP est correcte.\n\n-- Supervision";
|
||||||
|
self.send(smtp, subject, body).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn not_configured_when_server_empty() {
|
||||||
|
let smtp = SmtpConfig::default();
|
||||||
|
assert!(!is_smtp_configured(&smtp));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn configured_when_all_fields_present() {
|
||||||
|
let smtp = SmtpConfig {
|
||||||
|
server: "smtp.example.com".into(),
|
||||||
|
port: 587,
|
||||||
|
use_tls: true,
|
||||||
|
username: "user".into(),
|
||||||
|
password: "pass".into(),
|
||||||
|
from_email: "from@example.com".into(),
|
||||||
|
to_emails: vec!["to@example.com".into()],
|
||||||
|
};
|
||||||
|
assert!(is_smtp_configured(&smtp));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn not_configured_when_no_recipients() {
|
||||||
|
let smtp = SmtpConfig {
|
||||||
|
server: "smtp.example.com".into(),
|
||||||
|
port: 587,
|
||||||
|
use_tls: true,
|
||||||
|
username: "user".into(),
|
||||||
|
password: "pass".into(),
|
||||||
|
from_email: "from@example.com".into(),
|
||||||
|
to_emails: vec![],
|
||||||
|
};
|
||||||
|
assert!(!is_smtp_configured(&smtp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user