notify_me/notifier/
email_notifier.rs

1use super::*;
2use lettre::{
3    message::Mailbox, transport::smtp::authentication::Credentials, Message, SmtpTransport,
4    Transport,
5};
6
7/// Notifier for email.
8/// One EmailNotifier can only notify one corresponding mailbox.
9pub struct EmailNotifier {
10    smtp_host: String,
11    smtp_creds: Credentials,
12    sender: Mailbox,
13    recipient: Mailbox,
14}
15
16impl EmailNotifier {
17    /// # Arguments
18    ///
19    /// * `smtp_host` - SMTP server using TLS connections, e.g., `smtp.gmail.com`
20    /// * `smtp_username` - Your SMTP username, e.g., `sender@gmail.com`
21    /// * `smtp_password` - Your SMTP password.
22    /// * `recipient` - Email recipient, e.g., `recipient@gmail.com`
23    pub fn new(
24        smtp_host: &str,
25        smtp_username: &str,
26        smtp_password: &str,
27        recipient: &str,
28    ) -> Result<Self> {
29        let smtp_host = smtp_host.to_string();
30        let smtp_creds = Credentials::new(smtp_username.to_string(), smtp_password.to_string());
31        let sender = smtp_username.parse()?;
32        let recipient = recipient.parse()?;
33
34        if !SmtpTransport::relay(&smtp_host)?
35            .credentials(smtp_creds.clone())
36            .build()
37            .test_connection()?
38        {
39            return Err(anyhow::anyhow!("test connection failed"));
40        }
41
42        Ok(Self {
43            smtp_host,
44            smtp_creds,
45            sender,
46            recipient,
47        })
48    }
49}
50
51impl Notify for EmailNotifier {
52    fn notify(&self, title: &str, content: &str) -> Result<()> {
53        let mailer = SmtpTransport::relay(&self.smtp_host)?
54            .credentials(self.smtp_creds.clone())
55            .build();
56        let email = Message::builder()
57            .from(self.sender.clone())
58            .to(self.recipient.clone())
59            .subject(title)
60            .body(content.to_string())?;
61
62        mailer.send(&email)?;
63
64        Ok(())
65    }
66}