Replace endpoint /calendar/schedule_recipe by /calendar/sheduled_recipe
[recipes.git] / backend / src / email.rs
1 use lettre::{
2 AsyncTransport, Message, Tokio1Executor,
3 transport::smtp::{AsyncSmtpTransport, authentication::Credentials},
4 };
5 use tracing::{Level, event};
6
7 use crate::consts;
8
9 #[derive(Debug, thiserror::Error)]
10 pub enum Error {
11 #[error("Parse error: {0}")]
12 Parse(#[from] lettre::address::AddressError),
13
14 #[error("SMTP error: {0}")]
15 Smtp(#[from] lettre::transport::smtp::Error),
16
17 #[error("Email error: {0}")]
18 Email(#[from] lettre::error::Error),
19 }
20
21 /// A function to send an email using the given SMTP address.
22 /// It may timeout if the SMTP server is not reachable, see [const::SEND_EMAIL_TIMEOUT].
23 pub async fn send_email(
24 email: &str,
25 title: &str,
26 message: &str,
27 smtp_relay_address: &str,
28 smtp_login: &str,
29 smtp_password: &str,
30 ) -> Result<(), Error> {
31 let email = Message::builder()
32 .message_id(None)
33 .from("recipes@recipes.gburri.org".parse()?)
34 .to(email.parse()?)
35 .subject(title)
36 .body(message.to_string())?;
37
38 let credentials = Credentials::new(smtp_login.to_string(), smtp_password.to_string());
39
40 let mailer = AsyncSmtpTransport::<Tokio1Executor>::relay(smtp_relay_address)?
41 .credentials(credentials)
42 .timeout(Some(consts::SEND_EMAIL_TIMEOUT))
43 .build();
44
45 if let Err(error) = mailer.send(email).await {
46 event!(Level::ERROR, "Error when sending E-mail: {}", &error);
47 }
48
49 Ok(())
50 }