gargoyle_email_notifier/lib.rs
1use gargoyle::Notify;
2
3use lettre::{
4 Message,
5 transport::smtp::authentication::Credentials,
6 SmtpTransport,
7 Transport
8};
9
10pub use lettre::{
11 message::Mailbox,
12 Address,
13};
14
15use log::info;
16
17/// Send an email notification.
18///
19/// # Example
20///
21/// ```
22/// # use std::thread::sleep;
23/// # use std::time::Duration;
24/// use gargoyle::{modules::{notify, monitor}, Schedule};
25/// let service_name = "nginx";
26/// let service_monitor = monitor::ExactService::new(service_name);
27/// let email_notifier = notify::Email {
28/// from: "The Gargoyle <from@example.com>".parse().unwrap(),
29/// to: "Administrator <admin@example.com>".parse().unwrap(),
30/// relay: "smtp.example.com".to_string(),
31/// smtp_username: "username".to_string(),
32/// smtp_password: "password".to_string(),
33/// };
34/// let mut schedule = Schedule::default();
35/// schedule.add(
36/// &format!("The Gargoyle has detected that {service_name} has gone down"),
37/// &format!("The Gargoyle has detected that {service_name} has recovered"),
38/// Duration::from_secs(60),
39/// &service_monitor,
40/// &email_notifier,
41/// );
42///
43/// loop {
44/// schedule.run();
45/// sleep(Duration::from_millis(100));
46/// }
47/// ```
48pub struct Email {
49 pub from: Mailbox,
50 pub to: Mailbox,
51 pub relay: String,
52 pub smtp_username: String,
53 pub smtp_password: String,
54}
55
56/// Sends an email notification.
57impl Notify for Email {
58 fn send(&self, msg: &str, diagnostic: Option<String>) -> Result<(), String> {
59 let email = Message::builder()
60 .from(self.from.clone())
61 .to(self.to.clone())
62 .subject(msg)
63 .body(diagnostic.unwrap_or(msg.to_string()))
64 .map_err(|e| format!("Failed to build a message: {e}"))?;
65
66 let creds = Credentials::new(self.smtp_username.clone(), self.smtp_password.clone());
67
68 let mailer = SmtpTransport::relay(&self.relay)
69 .map_err(|e| format!("Failed to create a mailer: {e}"))?
70 .credentials(creds)
71 .build();
72
73 info!("Sending email notification from {} to {} via {}.", self.from, self.to, self.relay);
74 match mailer.send(&email) {
75 Ok(_) => Ok(()),
76 Err(e) => Err(format!("Failed to send email: {e}")),
77 }
78 }
79}
80