]> Untitled Git - lemmy.git/blob - crates/utils/src/email.rs
Moving settings and secrets to context.
[lemmy.git] / crates / utils / src / email.rs
1 use crate::settings::structs::Settings;
2 use lettre::{
3   message::{header, Mailbox, MultiPart, SinglePart},
4   transport::smtp::{
5     authentication::Credentials,
6     client::{Tls, TlsParameters},
7     extension::ClientId,
8   },
9   Address,
10   Message,
11   SmtpTransport,
12   Transport,
13 };
14 use std::str::FromStr;
15
16 pub fn send_email(
17   subject: &str,
18   to_email: &str,
19   to_username: &str,
20   html: &str,
21   settings: &Settings,
22 ) -> Result<(), String> {
23   let email_config = settings.email.to_owned().ok_or("no_email_setup")?;
24   let domain = settings.hostname.to_owned();
25
26   let (smtp_server, smtp_port) = {
27     let email_and_port = email_config.smtp_server.split(':').collect::<Vec<&str>>();
28     (
29       email_and_port[0],
30       email_and_port[1]
31         .parse::<u16>()
32         .expect("email needs a port"),
33     )
34   };
35
36   let email = Message::builder()
37     .from(
38       email_config
39         .smtp_from_address
40         .parse()
41         .expect("email from address isn't valid"),
42     )
43     .to(Mailbox::new(
44       Some(to_username.to_string()),
45       Address::from_str(to_email).expect("email to address isn't valid"),
46     ))
47     .subject(subject)
48     .multipart(
49       MultiPart::mixed().multipart(
50         MultiPart::alternative()
51           .singlepart(
52             SinglePart::builder()
53               .header(header::ContentType::TEXT_PLAIN)
54               .body(html.to_string()),
55           )
56           .multipart(
57             MultiPart::related().singlepart(
58               SinglePart::builder()
59                 .header(header::ContentType::TEXT_HTML)
60                 .body(html.to_string()),
61             ),
62           ),
63       ),
64     )
65     .expect("email built incorrectly");
66
67   // don't worry about 'dangeous'. it's just that leaving it at the default configuration
68   // is bad.
69   let mut builder = SmtpTransport::builder_dangerous(smtp_server).port(smtp_port);
70
71   // Set the TLS
72   if email_config.use_tls {
73     let tls_config = TlsParameters::new(smtp_server.to_string()).expect("the TLS backend is happy");
74     builder = builder.tls(Tls::Wrapper(tls_config));
75   }
76
77   // Set the creds if they exist
78   if let (Some(username), Some(password)) = (email_config.smtp_login, email_config.smtp_password) {
79     builder = builder.credentials(Credentials::new(username, password));
80   }
81
82   let mailer = builder.hello_name(ClientId::Domain(domain)).build();
83
84   let result = mailer.send(&email);
85
86   match result {
87     Ok(_) => Ok(()),
88     Err(e) => Err(e.to_string()),
89   }
90 }