mirror of https://github.com/LemmyNet/lemmy.git
Adding and reorganizing some email helpers.
parent
b0385830ed
commit
d17470c86c
|
@ -10,6 +10,9 @@ use lemmy_api_common::{
|
||||||
is_admin,
|
is_admin,
|
||||||
password_length_check,
|
password_length_check,
|
||||||
person::*,
|
person::*,
|
||||||
|
send_email_verification_success,
|
||||||
|
send_password_reset_email,
|
||||||
|
send_verification_email,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
diesel_option_overwrite,
|
diesel_option_overwrite,
|
||||||
|
@ -47,14 +50,12 @@ use lemmy_db_views_actor::{
|
||||||
};
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
claims::Claims,
|
claims::Claims,
|
||||||
email::send_email,
|
|
||||||
location_info,
|
location_info,
|
||||||
utils::{generate_random_string, is_valid_display_name, is_valid_matrix_id, naive_from_unix},
|
utils::{is_valid_display_name, is_valid_matrix_id, naive_from_unix},
|
||||||
ConnectionId,
|
ConnectionId,
|
||||||
LemmyError,
|
LemmyError,
|
||||||
};
|
};
|
||||||
use lemmy_websocket::{
|
use lemmy_websocket::{
|
||||||
email::send_verification_email,
|
|
||||||
messages::{CaptchaItem, SendAllMessage},
|
messages::{CaptchaItem, SendAllMessage},
|
||||||
LemmyContext,
|
LemmyContext,
|
||||||
UserOperation,
|
UserOperation,
|
||||||
|
@ -96,6 +97,10 @@ impl Perform for Login {
|
||||||
return Err(LemmyError::from_message("email_not_verified"));
|
return Err(LemmyError::from_message("email_not_verified"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if site.require_application && !local_user_view.local_user.accepted_application {
|
||||||
|
return Err(LemmyError::from_message("registration_application_pending"));
|
||||||
|
}
|
||||||
|
|
||||||
// Return the jwt
|
// Return the jwt
|
||||||
Ok(LoginResponse {
|
Ok(LoginResponse {
|
||||||
jwt: Some(
|
jwt: Some(
|
||||||
|
@ -187,7 +192,8 @@ impl Perform for SaveUserSettings {
|
||||||
local_user_view.local_user.id,
|
local_user_view.local_user.id,
|
||||||
email,
|
email,
|
||||||
&local_user_view.person.name,
|
&local_user_view.person.name,
|
||||||
context,
|
context.pool(),
|
||||||
|
&context.settings(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
None
|
None
|
||||||
|
@ -774,31 +780,8 @@ impl Perform for PasswordReset {
|
||||||
.map_err(LemmyError::from)
|
.map_err(LemmyError::from)
|
||||||
.map_err(|e| e.with_message("couldnt_find_that_username_or_email"))?;
|
.map_err(|e| e.with_message("couldnt_find_that_username_or_email"))?;
|
||||||
|
|
||||||
// Generate a random token
|
|
||||||
let token = generate_random_string();
|
|
||||||
|
|
||||||
// Insert the row
|
|
||||||
let token2 = token.clone();
|
|
||||||
let local_user_id = local_user_view.local_user.id;
|
|
||||||
blocking(context.pool(), move |conn| {
|
|
||||||
PasswordResetRequest::create_token(conn, local_user_id, &token2)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
// Email the pure token to the user.
|
// Email the pure token to the user.
|
||||||
// TODO no i18n support here.
|
send_password_reset_email(&local_user_view, context.pool(), &context.settings()).await?;
|
||||||
let email = &local_user_view.local_user.email.expect("email");
|
|
||||||
let subject = &format!("Password reset for {}", local_user_view.person.name);
|
|
||||||
let protocol_and_hostname = &context.settings().get_protocol_and_hostname();
|
|
||||||
let html = &format!("<h1>Password Reset Request for {}</h1><br><a href={}/password_change/{}>Click here to reset your password</a>", local_user_view.person.name, protocol_and_hostname, &token);
|
|
||||||
send_email(
|
|
||||||
subject,
|
|
||||||
email,
|
|
||||||
&local_user_view.person.name,
|
|
||||||
html,
|
|
||||||
&context.settings(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(PasswordResetResponse {})
|
Ok(PasswordResetResponse {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -963,6 +946,13 @@ impl Perform for VerifyEmail {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
let local_user_view = blocking(context.pool(), move |conn| {
|
||||||
|
LocalUserView::read(conn, local_user_id)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
|
||||||
|
send_email_verification_success(&local_user_view, &context.settings())?;
|
||||||
|
|
||||||
Ok(VerifyEmailResponse {})
|
Ok(VerifyEmailResponse {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ use lemmy_api_common::{
|
||||||
get_local_user_view_from_jwt,
|
get_local_user_view_from_jwt,
|
||||||
get_local_user_view_from_jwt_opt,
|
get_local_user_view_from_jwt_opt,
|
||||||
is_admin,
|
is_admin,
|
||||||
|
send_application_approved_email,
|
||||||
site::*,
|
site::*,
|
||||||
};
|
};
|
||||||
use lemmy_apub::{
|
use lemmy_apub::{
|
||||||
|
@ -656,6 +657,14 @@ impl Perform for ApproveRegistrationApplication {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
let require_email_verification = blocking(context.pool(), Site::read_simple)
|
||||||
|
.await??
|
||||||
|
.require_email_verification;
|
||||||
|
|
||||||
|
if require_email_verification && data.approve {
|
||||||
|
send_application_approved_email(&local_user_view, &context.settings())?;
|
||||||
|
}
|
||||||
|
|
||||||
// Read the view
|
// Read the view
|
||||||
let registration_application = blocking(context.pool(), move |conn| {
|
let registration_application = blocking(context.pool(), move |conn| {
|
||||||
RegistrationApplicationView::read(conn, app_id)
|
RegistrationApplicationView::read(conn, app_id)
|
||||||
|
|
|
@ -10,6 +10,8 @@ use lemmy_db_schema::{
|
||||||
newtypes::{CommunityId, LocalUserId, PersonId, PostId},
|
newtypes::{CommunityId, LocalUserId, PersonId, PostId},
|
||||||
source::{
|
source::{
|
||||||
community::Community,
|
community::Community,
|
||||||
|
email_verification::{EmailVerification, EmailVerificationForm},
|
||||||
|
password_reset_request::PasswordResetRequest,
|
||||||
person_block::PersonBlock,
|
person_block::PersonBlock,
|
||||||
post::{Post, PostRead, PostReadForm},
|
post::{Post, PostRead, PostReadForm},
|
||||||
secret::Secret,
|
secret::Secret,
|
||||||
|
@ -23,7 +25,14 @@ use lemmy_db_views_actor::{
|
||||||
community_person_ban_view::CommunityPersonBanView,
|
community_person_ban_view::CommunityPersonBanView,
|
||||||
community_view::CommunityView,
|
community_view::CommunityView,
|
||||||
};
|
};
|
||||||
use lemmy_utils::{claims::Claims, settings::structs::FederationConfig, LemmyError, Sensitive};
|
use lemmy_utils::{
|
||||||
|
claims::Claims,
|
||||||
|
email::send_email,
|
||||||
|
settings::structs::{FederationConfig, Settings},
|
||||||
|
utils::generate_random_string,
|
||||||
|
LemmyError,
|
||||||
|
Sensitive,
|
||||||
|
};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub async fn blocking<F, T>(pool: &DbPool, f: F) -> Result<T, LemmyError>
|
pub async fn blocking<F, T>(pool: &DbPool, f: F) -> Result<T, LemmyError>
|
||||||
|
@ -333,3 +342,122 @@ pub fn honeypot_check(honeypot: &Option<String>) -> Result<(), LemmyError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn send_email_to_user(
|
||||||
|
local_user_view: &LocalUserView,
|
||||||
|
subject_text: &str,
|
||||||
|
body_text: &str,
|
||||||
|
comment_content: &str,
|
||||||
|
settings: &Settings,
|
||||||
|
) {
|
||||||
|
if local_user_view.person.banned || !local_user_view.local_user.send_notifications_to_email {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(user_email) = &local_user_view.local_user.email {
|
||||||
|
let subject = &format!(
|
||||||
|
"{} - {} {}",
|
||||||
|
subject_text, settings.hostname, local_user_view.person.name,
|
||||||
|
);
|
||||||
|
let html = &format!(
|
||||||
|
"<h1>{}</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
|
||||||
|
body_text,
|
||||||
|
local_user_view.person.name,
|
||||||
|
comment_content,
|
||||||
|
settings.get_protocol_and_hostname()
|
||||||
|
);
|
||||||
|
match send_email(
|
||||||
|
subject,
|
||||||
|
user_email,
|
||||||
|
&local_user_view.person.name,
|
||||||
|
html,
|
||||||
|
settings,
|
||||||
|
) {
|
||||||
|
Ok(_o) => _o,
|
||||||
|
Err(e) => tracing::error!("{}", e),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_password_reset_email(
|
||||||
|
local_user_view: &LocalUserView,
|
||||||
|
pool: &DbPool,
|
||||||
|
settings: &Settings,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
// Generate a random token
|
||||||
|
let token = generate_random_string();
|
||||||
|
|
||||||
|
// Insert the row
|
||||||
|
let token2 = token.clone();
|
||||||
|
let local_user_id = local_user_view.local_user.id;
|
||||||
|
blocking(pool, move |conn| {
|
||||||
|
PasswordResetRequest::create_token(conn, local_user_id, &token2)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
|
||||||
|
let email = &local_user_view.local_user.email.to_owned().expect("email");
|
||||||
|
let subject = &format!("Password reset for {}", local_user_view.person.name);
|
||||||
|
let protocol_and_hostname = settings.get_protocol_and_hostname();
|
||||||
|
let html = &format!("<h1>Password Reset Request for {}</h1><br><a href={}/password_change/{}>Click here to reset your password</a>", local_user_view.person.name, protocol_and_hostname, &token);
|
||||||
|
send_email(subject, email, &local_user_view.person.name, html, settings)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Send a verification email
|
||||||
|
pub async fn send_verification_email(
|
||||||
|
local_user_id: LocalUserId,
|
||||||
|
new_email: &str,
|
||||||
|
username: &str,
|
||||||
|
pool: &DbPool,
|
||||||
|
settings: &Settings,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
let form = EmailVerificationForm {
|
||||||
|
local_user_id,
|
||||||
|
email: new_email.to_string(),
|
||||||
|
verification_token: generate_random_string(),
|
||||||
|
};
|
||||||
|
let verify_link = format!(
|
||||||
|
"{}/verify_email/{}",
|
||||||
|
settings.get_protocol_and_hostname(),
|
||||||
|
&form.verification_token
|
||||||
|
);
|
||||||
|
blocking(pool, move |conn| EmailVerification::create(conn, &form)).await??;
|
||||||
|
|
||||||
|
let subject = format!("Verify your email address for {}", settings.hostname);
|
||||||
|
let body = format!(
|
||||||
|
concat!(
|
||||||
|
"Please click the link below to verify your email address ",
|
||||||
|
"for the account @{}@{}. Ignore this email if the account isn't yours.\n\n",
|
||||||
|
"<a href=\"{}\"></a>"
|
||||||
|
),
|
||||||
|
username, settings.hostname, verify_link
|
||||||
|
);
|
||||||
|
send_email(&subject, new_email, username, &body, settings)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_email_verification_success(
|
||||||
|
local_user_view: &LocalUserView,
|
||||||
|
settings: &Settings,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
let email = &local_user_view.local_user.email.to_owned().expect("email");
|
||||||
|
let subject = &format!("Email verified for {}", local_user_view.person.name);
|
||||||
|
let html = "Your email has been verified.";
|
||||||
|
send_email(subject, email, &local_user_view.person.name, html, settings)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_application_approved_email(
|
||||||
|
local_user_view: &LocalUserView,
|
||||||
|
settings: &Settings,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
let email = &local_user_view.local_user.email.to_owned().expect("email");
|
||||||
|
let subject = &format!(
|
||||||
|
"Registration to {} approved for {}",
|
||||||
|
settings.hostname, local_user_view.person.name
|
||||||
|
);
|
||||||
|
let html = &format!(
|
||||||
|
"Your registration application has been approved. Welcome to {}!",
|
||||||
|
settings.hostname
|
||||||
|
);
|
||||||
|
send_email(subject, email, &local_user_view.person.name, html, settings)
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ use lemmy_api_common::{
|
||||||
check_person_block,
|
check_person_block,
|
||||||
get_local_user_view_from_jwt,
|
get_local_user_view_from_jwt,
|
||||||
person::{CreatePrivateMessage, PrivateMessageResponse},
|
person::{CreatePrivateMessage, PrivateMessageResponse},
|
||||||
|
send_email_to_user,
|
||||||
};
|
};
|
||||||
use lemmy_apub::{
|
use lemmy_apub::{
|
||||||
generate_local_apub_endpoint,
|
generate_local_apub_endpoint,
|
||||||
|
@ -20,11 +21,7 @@ use lemmy_db_schema::{
|
||||||
};
|
};
|
||||||
use lemmy_db_views::local_user_view::LocalUserView;
|
use lemmy_db_views::local_user_view::LocalUserView;
|
||||||
use lemmy_utils::{utils::remove_slurs, ConnectionId, LemmyError};
|
use lemmy_utils::{utils::remove_slurs, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{
|
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
||||||
send::{send_email_to_user, send_pm_ws_message},
|
|
||||||
LemmyContext,
|
|
||||||
UserOperationCrud,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for CreatePrivateMessage {
|
impl PerformCrud for CreatePrivateMessage {
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
use crate::PerformCrud;
|
use crate::PerformCrud;
|
||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
use lemmy_api_common::{blocking, honeypot_check, password_length_check, person::*};
|
use lemmy_api_common::{
|
||||||
|
blocking,
|
||||||
|
honeypot_check,
|
||||||
|
password_length_check,
|
||||||
|
person::*,
|
||||||
|
send_verification_email,
|
||||||
|
};
|
||||||
use lemmy_apub::{
|
use lemmy_apub::{
|
||||||
generate_followers_url,
|
generate_followers_url,
|
||||||
generate_inbox_url,
|
generate_inbox_url,
|
||||||
|
@ -34,7 +40,7 @@ use lemmy_utils::{
|
||||||
ConnectionId,
|
ConnectionId,
|
||||||
LemmyError,
|
LemmyError,
|
||||||
};
|
};
|
||||||
use lemmy_websocket::{email::send_verification_email, messages::CheckCaptcha, LemmyContext};
|
use lemmy_websocket::{messages::CheckCaptcha, LemmyContext};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for Register {
|
impl PerformCrud for Register {
|
||||||
|
@ -258,7 +264,8 @@ impl PerformCrud for Register {
|
||||||
// we check at the beginning of this method that email is set
|
// we check at the beginning of this method that email is set
|
||||||
&inserted_local_user.email.expect("email was provided"),
|
&inserted_local_user.email.expect("email was provided"),
|
||||||
&inserted_person.name,
|
&inserted_person.name,
|
||||||
context,
|
context.pool(),
|
||||||
|
&context.settings(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
LoginResponse {
|
LoginResponse {
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
use crate::LemmyContext;
|
|
||||||
use lemmy_api_common::blocking;
|
|
||||||
use lemmy_db_schema::{
|
|
||||||
newtypes::LocalUserId,
|
|
||||||
source::email_verification::{EmailVerification, EmailVerificationForm},
|
|
||||||
traits::Crud,
|
|
||||||
};
|
|
||||||
use lemmy_utils::{email::send_email, utils::generate_random_string, LemmyError};
|
|
||||||
|
|
||||||
pub async fn send_verification_email(
|
|
||||||
local_user_id: LocalUserId,
|
|
||||||
new_email: &str,
|
|
||||||
username: &str,
|
|
||||||
context: &LemmyContext,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
let settings = context.settings();
|
|
||||||
let form = EmailVerificationForm {
|
|
||||||
local_user_id,
|
|
||||||
email: new_email.to_string(),
|
|
||||||
verification_token: generate_random_string(),
|
|
||||||
};
|
|
||||||
// TODO: link should be replaced with a frontend route once that exists
|
|
||||||
let verify_link = format!(
|
|
||||||
"{}/api/v3/user/verify_email?token={}",
|
|
||||||
settings.get_protocol_and_hostname(),
|
|
||||||
&form.verification_token
|
|
||||||
);
|
|
||||||
blocking(context.pool(), move |conn| {
|
|
||||||
EmailVerification::create(conn, &form)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
|
|
||||||
let subject = format!("Verify your email address for {}", settings.hostname);
|
|
||||||
let body = format!(
|
|
||||||
concat!(
|
|
||||||
"Please click the link below to verify your email address ",
|
|
||||||
"for the account @{}@{}. Ignore this email if the account isn't yours.\n\n",
|
|
||||||
"<a href=\"{}\"></a>"
|
|
||||||
),
|
|
||||||
username, settings.hostname, verify_link
|
|
||||||
);
|
|
||||||
send_email(&subject, new_email, username, &body, &context.settings())?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
|
@ -10,7 +10,6 @@ use reqwest::Client;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
pub mod chat_server;
|
pub mod chat_server;
|
||||||
pub mod email;
|
|
||||||
pub mod handlers;
|
pub mod handlers;
|
||||||
pub mod messages;
|
pub mod messages;
|
||||||
pub mod routes;
|
pub mod routes;
|
||||||
|
|
|
@ -10,6 +10,7 @@ use lemmy_api_common::{
|
||||||
community::CommunityResponse,
|
community::CommunityResponse,
|
||||||
person::PrivateMessageResponse,
|
person::PrivateMessageResponse,
|
||||||
post::PostResponse,
|
post::PostResponse,
|
||||||
|
send_email_to_user,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::{CommentId, CommunityId, LocalUserId, PersonId, PostId, PrivateMessageId},
|
newtypes::{CommentId, CommunityId, LocalUserId, PersonId, PostId, PrivateMessageId},
|
||||||
|
@ -28,14 +29,7 @@ use lemmy_db_views::{
|
||||||
private_message_view::PrivateMessageView,
|
private_message_view::PrivateMessageView,
|
||||||
};
|
};
|
||||||
use lemmy_db_views_actor::community_view::CommunityView;
|
use lemmy_db_views_actor::community_view::CommunityView;
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{utils::MentionData, ConnectionId, LemmyError};
|
||||||
email::send_email,
|
|
||||||
settings::structs::Settings,
|
|
||||||
utils::MentionData,
|
|
||||||
ConnectionId,
|
|
||||||
LemmyError,
|
|
||||||
};
|
|
||||||
use tracing::error;
|
|
||||||
|
|
||||||
pub async fn send_post_ws_message<OP: ToString + Send + OperationType + 'static>(
|
pub async fn send_post_ws_message<OP: ToString + Send + OperationType + 'static>(
|
||||||
post_id: PostId,
|
post_id: PostId,
|
||||||
|
@ -296,39 +290,3 @@ pub async fn send_local_notifs(
|
||||||
};
|
};
|
||||||
Ok(recipient_ids)
|
Ok(recipient_ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_email_to_user(
|
|
||||||
local_user_view: &LocalUserView,
|
|
||||||
subject_text: &str,
|
|
||||||
body_text: &str,
|
|
||||||
comment_content: &str,
|
|
||||||
settings: &Settings,
|
|
||||||
) {
|
|
||||||
if local_user_view.person.banned || !local_user_view.local_user.send_notifications_to_email {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(user_email) = &local_user_view.local_user.email {
|
|
||||||
let subject = &format!(
|
|
||||||
"{} - {} {}",
|
|
||||||
subject_text, settings.hostname, local_user_view.person.name,
|
|
||||||
);
|
|
||||||
let html = &format!(
|
|
||||||
"<h1>{}</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
|
|
||||||
body_text,
|
|
||||||
local_user_view.person.name,
|
|
||||||
comment_content,
|
|
||||||
settings.get_protocol_and_hostname()
|
|
||||||
);
|
|
||||||
match send_email(
|
|
||||||
subject,
|
|
||||||
user_email,
|
|
||||||
&local_user_view.person.name,
|
|
||||||
html,
|
|
||||||
settings,
|
|
||||||
) {
|
|
||||||
Ok(_o) => _o,
|
|
||||||
Err(e) => error!("{}", e),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue