1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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(())
}
|