1use anyhow::Result;
2use lettre::{
3 message::{header::ContentType, Mailbox},
4 transport::smtp::authentication::Credentials,
5 Message, SmtpTransport, Transport,
6};
7
8use serde::Deserialize;
9
10#[derive(Deserialize, Debug)]
11pub struct SMTP {
12 pub enabled: bool,
13
14 pub username: String,
15 pub password: String,
16 pub smtp_host: String,
17 pub smtp_port: u16,
18
19 pub from: String,
20 pub to: Vec<String>,
21 pub cc: Option<Vec<String>>,
22}
23
24impl SMTP {
25 pub fn send_email(&self, subjet: String, body: String) -> Result<()> {
26 let from_address: Mailbox = self.from.parse()?;
27 let to_addresses: Vec<Mailbox> = self
28 .to
29 .iter()
30 .filter_map(|email| email.parse().ok())
31 .collect();
32
33 let mut builder = Message::builder().from(from_address).subject(subjet);
34 for to_addr in &to_addresses {
35 builder = builder.to(to_addr.clone());
36 }
37
38 if let Some(cc_list) = &self.cc {
39 for email in cc_list {
40 if let Ok(cc_addr) = email.parse() {
41 builder = builder.cc(cc_addr);
42 }
43 }
44 }
45
46 let email = builder.header(ContentType::TEXT_PLAIN).body(body)?;
47 let creds = Credentials::new(self.username.to_owned(), self.password.to_owned());
48
49 let mailer = SmtpTransport::relay(&self.smtp_host)
50 .unwrap()
51 .credentials(creds)
52 .build();
53
54 match mailer.send(&email) {
55 Ok(_) => Ok(()),
56 Err(e) => Err(anyhow::anyhow!("Could not send email: {e:?}")),
57 }
58 }
59}