rnotifylib/destination/kinds/
mail.rs

1use std::error::Error;
2use lettre::message::{Mailbox, SinglePart};
3use lettre::{SmtpTransport, Transport};
4use lettre::transport::smtp::authentication;
5use serde::{Serialize, Deserialize};
6use crate::destination::{MessageDestination, SerializableDestination};
7use crate::message::{Message, MessageDetail};
8use crate::util::html::HtmlMessageDetail;
9
10#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
11pub struct MailDestination {
12    from: Mailbox,
13    relay: Relay,
14    to: Mailbox,
15    reply_to: Option<Mailbox>,
16}
17
18#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
19pub struct Relay {
20    url: String,
21    #[serde(default = "default_port")]
22    port: u16,
23    #[serde(default = "bool::default")]
24    start_tls_relay: bool,
25    username: String,
26    password: String,
27}
28
29fn default_port() -> u16 {
30    return lettre::transport::smtp::SMTP_PORT;
31}
32
33impl MessageDestination for MailDestination {
34    fn send(&self, message: &Message) -> Result<(), Box<dyn Error>> {
35        println!("Message destination.");
36        let mut message_builder = lettre::Message::builder()
37            .from(self.from.clone())
38            .to(self.to.clone());
39
40        if let Some(reply_to) = self.reply_to.clone() {
41            message_builder = message_builder.reply_to(reply_to);
42        }
43        if let Some(title) = message.get_title() {
44            message_builder = message_builder.subject(title);
45        }
46
47        let email = message_builder.singlepart(create_body(message.get_message_detail()))?;
48
49        let creds = authentication::Credentials::new(self.relay.username.clone(), self.relay.password.clone());
50        let mailer =
51            if self.relay.start_tls_relay { SmtpTransport::starttls_relay(&self.relay.url) } else { SmtpTransport::relay(&self.relay.url) }?.port(self.relay.port)
52                .credentials(creds)
53                .build();
54
55        mailer.send(&email)?;
56        println!("Mail successfully sent.");
57        Ok(())
58    }
59}
60
61#[typetag::serde(name = "Mail")]
62impl SerializableDestination for MailDestination {
63    fn as_message_destination(&self) -> &dyn MessageDestination {
64        self
65    }
66}
67
68fn create_body(detail: &MessageDetail) -> SinglePart {
69    match detail {
70        MessageDetail::Raw(raw) => {
71            SinglePart::plain(raw.to_owned())
72        }
73        MessageDetail::Formatted(formatted) => {
74            SinglePart::html(formatted.create_html())
75        }
76    }
77}