Re-write email backend, use SMTP directly.

This commit is contained in:
Paul Makles
2020-08-30 17:16:53 +01:00
parent ff0e539c7b
commit cbac802978
21 changed files with 354 additions and 303 deletions

View File

@@ -1,11 +1,11 @@
use serde::{Serialize, Deserialize};
use reqwest::blocking::Client;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::env;
#[derive(Serialize, Deserialize)]
struct CaptchaResponse {
success: bool
success: bool,
}
pub fn verify(user_token: &Option<String>) -> Result<(), String> {

96
src/util/email.rs Normal file
View File

@@ -0,0 +1,96 @@
use lettre::message::{header, MultiPart, SinglePart};
use lettre::transport::smtp::authentication::Credentials;
use lettre::{Message, SmtpTransport, Transport};
use super::variables::{PUBLIC_URL, SMTP_FROM, SMTP_HOST, SMTP_PASSWORD, SMTP_USERNAME};
lazy_static! {
static ref MAILER: lettre::transport::smtp::SmtpTransport =
SmtpTransport::relay(SMTP_HOST.as_ref())
.unwrap()
.credentials(Credentials::new(
SMTP_USERNAME.to_string(),
SMTP_PASSWORD.to_string()
))
.build();
}
fn send(message: Message) -> Result<(), String> {
MAILER
.send(&message)
.map_err(|err| format!("Failed to send email! {}", err.to_string()))?;
Ok(())
}
fn generate_multipart(text: &str, html: &str) -> MultiPart {
MultiPart::mixed().multipart(
MultiPart::alternative()
.singlepart(
SinglePart::quoted_printable()
.header(header::ContentType(
"text/plain; charset=utf8".parse().unwrap(),
))
.body(text),
)
.multipart(
MultiPart::related().singlepart(
SinglePart::eight_bit()
.header(header::ContentType(
"text/html; charset=utf8".parse().unwrap(),
))
.body(html),
),
),
)
}
pub fn send_verification_email(email: String, code: String) -> Result<(), String> {
let url = format!("{}/api/account/verify/{}", PUBLIC_URL.to_string(), code);
let email = Message::builder()
.from(SMTP_FROM.to_string().parse().unwrap())
.to(email.parse().unwrap())
.subject("Verify your email!")
.multipart(generate_multipart(
&format!("Verify your email here: {}", url),
&format!("<a href=\"{}\">Click to verify your email!</a>", url),
))
.unwrap();
send(email)
}
pub fn send_password_reset(email: String, code: String) -> Result<(), String> {
let url = format!("{}/api/account/reset/{}", PUBLIC_URL.to_string(), code);
let email = Message::builder()
.from(SMTP_FROM.to_string().parse().unwrap())
.to(email.parse().unwrap())
.subject("Reset your password.")
.multipart(generate_multipart(
&format!("Reset your password here: {}", url),
&format!("<a href=\"{}\">Click to reset your password!</a>", url),
))
.unwrap();
send(email)
}
pub fn send_welcome_email(email: String, username: String) -> Result<(), String> {
let email = Message::builder()
.from(SMTP_FROM.to_string().parse().unwrap())
.to(email.parse().unwrap())
.subject("Welcome to REVOLT!")
.multipart(
generate_multipart(
&format!("Welcome, {}! You can now use REVOLT.", username),
&format!(
"<b>Welcome, {}!</b><br/>You can now use REVOLT.<br/><a href=\"{}\">Go to REVOLT</a>",
username,
PUBLIC_URL.to_string()
)
)
)
.unwrap();
send(email)
}

View File

@@ -3,6 +3,8 @@ use rand::{distributions::Alphanumeric, Rng};
use std::iter::FromIterator;
pub mod captcha;
pub mod email;
pub mod variables;
pub fn vec_to_set<T: Clone + Eq + std::hash::Hash>(data: &[T]) -> HashSet<T> {
HashSet::from_iter(data.iter().cloned())

27
src/util/variables.rs Normal file
View File

@@ -0,0 +1,27 @@
use std::env;
lazy_static! {
pub static ref MONGO_URI: String =
env::var("REVOLT_MONGO_URI").expect("Missing REVOLT_MONGO_URI environment variable.");
pub static ref PUBLIC_URL: String =
env::var("REVOLT_PUBLIC_URL").expect("Missing REVOLT_PUBLIC_URL environment variable.");
pub static ref USE_EMAIL_VERIFICATION: bool = env::var("REVOLT_USE_EMAIL_VERIFICATION").map_or(
env::var("REVOLT_SMTP_HOST").is_ok()
&& env::var("REVOLT_SMTP_USERNAME").is_ok()
&& env::var("REVOLT_SMTP_PASSWORD").is_ok()
&& env::var("REVOLT_SMTP_FROM").is_ok(),
|v| v == *"1"
);
pub static ref USE_HCAPTCHA: bool = env::var("REVOLT_HCAPTCHA_KEY").is_ok();
pub static ref SMTP_HOST: String =
env::var("REVOLT_SMTP_HOST").unwrap_or_else(|_| "".to_string());
pub static ref SMTP_USERNAME: String =
env::var("SMTP_USERNAME").unwrap_or_else(|_| "".to_string());
pub static ref SMTP_PASSWORD: String =
env::var("SMTP_PASSWORD").unwrap_or_else(|_| "".to_string());
pub static ref SMTP_FROM: String = env::var("SMTP_FROM").unwrap_or_else(|_| "".to_string());
pub static ref HCAPTCHA_KEY: String =
env::var("REVOLT_HCAPTCHA_KEY").unwrap_or_else(|_| "".to_string());
pub static ref WS_HOST: String =
env::var("REVOLT_WS_HOST").unwrap_or_else(|_| "0.0.0.0:9999".to_string());
}