]> Untitled Git - lemmy.git/blob - lemmy_utils/src/email.rs
Merge pull request #1328 from LemmyNet/move_views_to_diesel
[lemmy.git] / lemmy_utils / src / email.rs
1 use crate::settings::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::eight_bit()
52               .header(header::ContentType(
53                 "text/plain; charset=utf8"
54                   .parse()
55                   .expect("email could not parse header"),
56               ))
57               .body(html),
58           )
59           .multipart(
60             MultiPart::related().singlepart(
61               SinglePart::eight_bit()
62                 .header(header::ContentType(
63                   "text/html; charset=utf8"
64                     .parse()
65                     .expect("email could not parse header"),
66                 ))
67                 .body(html),
68             ),
69           ),
70       ),
71     )
72     .expect("email built incorrectly");
73
74   // don't worry about 'dangeous'. it's just that leaving it at the default configuration
75   // is bad.
76   let mut builder = SmtpTransport::builder_dangerous(smtp_server).port(smtp_port);
77
78   // Set the TLS
79   if email_config.use_tls {
80     let tls_config = TlsParameters::new(smtp_server.to_string()).expect("the TLS backend is happy");
81     builder = builder.tls(Tls::Wrapper(tls_config));
82   }
83
84   // Set the creds if they exist
85   if let (Some(username), Some(password)) = (email_config.smtp_login, email_config.smtp_password) {
86     builder = builder.credentials(Credentials::new(username, password));
87   }
88
89   let mailer = builder.hello_name(ClientId::Domain(domain)).build();
90
91   let result = mailer.send(&email);
92
93   match result {
94     Ok(_) => Ok(()),
95     Err(e) => Err(e.to_string()),
96   }
97 }