2020-09-14 15:29:50 +00:00
|
|
|
use crate::settings::Settings;
|
|
|
|
use lettre::{
|
2020-10-30 17:19:00 +00:00
|
|
|
message::{header, Mailbox, MultiPart, SinglePart},
|
|
|
|
transport::smtp::{
|
|
|
|
authentication::Credentials,
|
|
|
|
client::{Tls, TlsParameters},
|
2020-09-14 15:29:50 +00:00
|
|
|
extension::ClientId,
|
|
|
|
},
|
2020-10-30 17:19:00 +00:00
|
|
|
Address,
|
|
|
|
Message,
|
|
|
|
SmtpTransport,
|
2020-09-14 15:29:50 +00:00
|
|
|
Transport,
|
|
|
|
};
|
2020-10-30 17:19:00 +00:00
|
|
|
use std::str::FromStr;
|
2020-09-14 15:29:50 +00:00
|
|
|
|
|
|
|
pub fn send_email(
|
|
|
|
subject: &str,
|
|
|
|
to_email: &str,
|
|
|
|
to_username: &str,
|
|
|
|
html: &str,
|
|
|
|
) -> Result<(), String> {
|
|
|
|
let email_config = Settings::get().email.ok_or("no_email_setup")?;
|
2020-10-30 17:19:00 +00:00
|
|
|
let domain = Settings::get().hostname;
|
2020-09-14 15:29:50 +00:00
|
|
|
|
2020-10-30 17:19:00 +00:00
|
|
|
let (smtp_server, smtp_port) = {
|
|
|
|
let email_and_port = email_config.smtp_server.split(':').collect::<Vec<&str>>();
|
|
|
|
(
|
|
|
|
email_and_port[0],
|
|
|
|
email_and_port[1]
|
|
|
|
.parse::<u16>()
|
|
|
|
.expect("email needs a port"),
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
let email = Message::builder()
|
|
|
|
.from(
|
|
|
|
email_config
|
|
|
|
.smtp_from_address
|
|
|
|
.parse()
|
|
|
|
.expect("email from address isn't valid"),
|
|
|
|
)
|
|
|
|
.to(Mailbox::new(
|
|
|
|
Some(to_username.to_string()),
|
|
|
|
Address::from_str(to_email).expect("email to address isn't valid"),
|
|
|
|
))
|
2020-09-14 15:29:50 +00:00
|
|
|
.subject(subject)
|
2020-10-30 17:19:00 +00:00
|
|
|
.multipart(
|
|
|
|
MultiPart::mixed().multipart(
|
|
|
|
MultiPart::alternative()
|
|
|
|
.singlepart(
|
2021-02-01 20:56:37 +00:00
|
|
|
SinglePart::builder()
|
2020-10-30 17:19:00 +00:00
|
|
|
.header(header::ContentType(
|
|
|
|
"text/plain; charset=utf8"
|
|
|
|
.parse()
|
|
|
|
.expect("email could not parse header"),
|
|
|
|
))
|
2021-02-01 20:56:37 +00:00
|
|
|
.body(html.to_string()),
|
2020-10-30 17:19:00 +00:00
|
|
|
)
|
|
|
|
.multipart(
|
|
|
|
MultiPart::related().singlepart(
|
2021-02-01 20:56:37 +00:00
|
|
|
SinglePart::builder()
|
2020-10-30 17:19:00 +00:00
|
|
|
.header(header::ContentType(
|
|
|
|
"text/html; charset=utf8"
|
|
|
|
.parse()
|
|
|
|
.expect("email could not parse header"),
|
|
|
|
))
|
2021-02-01 20:56:37 +00:00
|
|
|
.body(html.to_string()),
|
2020-10-30 17:19:00 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
.expect("email built incorrectly");
|
|
|
|
|
|
|
|
// don't worry about 'dangeous'. it's just that leaving it at the default configuration
|
|
|
|
// is bad.
|
|
|
|
let mut builder = SmtpTransport::builder_dangerous(smtp_server).port(smtp_port);
|
|
|
|
|
|
|
|
// Set the TLS
|
|
|
|
if email_config.use_tls {
|
|
|
|
let tls_config = TlsParameters::new(smtp_server.to_string()).expect("the TLS backend is happy");
|
|
|
|
builder = builder.tls(Tls::Wrapper(tls_config));
|
2020-09-14 15:29:50 +00:00
|
|
|
}
|
|
|
|
|
2020-10-30 17:19:00 +00:00
|
|
|
// Set the creds if they exist
|
|
|
|
if let (Some(username), Some(password)) = (email_config.smtp_login, email_config.smtp_password) {
|
|
|
|
builder = builder.credentials(Credentials::new(username, password));
|
|
|
|
}
|
|
|
|
|
|
|
|
let mailer = builder.hello_name(ClientId::Domain(domain)).build();
|
|
|
|
|
|
|
|
let result = mailer.send(&email);
|
2020-09-14 15:29:50 +00:00
|
|
|
|
|
|
|
match result {
|
|
|
|
Ok(_) => Ok(()),
|
|
|
|
Err(e) => Err(e.to_string()),
|
|
|
|
}
|
|
|
|
}
|