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