aboutsummaryrefslogtreecommitdiff
path: root/src/mail.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mail.rs')
-rw-r--r--src/mail.rs81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/mail.rs b/src/mail.rs
index e69de29..841b552 100644
--- a/src/mail.rs
+++ b/src/mail.rs
@@ -0,0 +1,81 @@
+use std::{str::FromStr, sync::Arc, time::Duration};
+
+use anyhow::{anyhow, Result};
+use lettre::{
+ message::Mailbox, transport::smtp::authentication::Credentials, Message, SmtpTransport,
+ Transport,
+};
+use log::info;
+use serde::Deserialize;
+
+use crate::Config;
+
+#[derive(Debug, Deserialize)]
+pub struct MailConfig {
+ from: String,
+ to: Vec<String>,
+ smtp_auth: SmtpAuth,
+ smtp_port: u16,
+ smtp_timeout: Option<f64>,
+ smtp_server: String,
+ smtp_username: Option<String>,
+ smtp_password: Option<String>,
+}
+
+#[derive(Clone, Deserialize, Debug)]
+#[serde(rename_all = "snake_case")]
+enum SmtpAuth {
+ Plain,
+ Tls,
+ Starttls,
+}
+
+pub async fn send_mail(
+ config: &Arc<Config>,
+ service: usize,
+ check: usize,
+ error: String,
+) -> Result<()> {
+ let config = config.to_owned();
+ tokio::task::spawn_blocking(move || {
+ if let Some(mconfig) = &config.mail {
+ info!("sending mail!");
+ let mut transport = match mconfig.smtp_auth {
+ SmtpAuth::Plain => SmtpTransport::builder_dangerous(&mconfig.smtp_server),
+ SmtpAuth::Tls => SmtpTransport::relay(&mconfig.smtp_server)?,
+ SmtpAuth::Starttls => SmtpTransport::starttls_relay(&mconfig.smtp_server)?,
+ }
+ .port(mconfig.smtp_port);
+
+ if let Some(username) = mconfig.smtp_username.clone() {
+ let password = mconfig
+ .smtp_password
+ .clone()
+ .ok_or(anyhow!("smtp password missing"))?;
+ transport = transport.credentials(Credentials::new(username, password));
+ }
+ if let Some(timeout) = mconfig.smtp_timeout {
+ transport = transport.timeout(Some(Duration::from_secs_f64(timeout)))
+ }
+ let transport = transport.build();
+
+ for recipient in &mconfig.to {
+ let service = &config.services[service];
+
+ let message = Message::builder()
+ .from(Mailbox::from_str(&mconfig.from)?)
+ .to(Mailbox::from_str(&recipient)?)
+ .subject(format!("{} failed.", service.title))
+ .body(format!(
+ "Check {:?} reported:\n{}",
+ service.checks[check].display(),
+ error
+ ))?;
+ transport.send(&message)?;
+ }
+ }
+ Ok::<_, anyhow::Error>(())
+ })
+ .await??;
+ Ok(())
+}