//! Authentication and account action email templates. use crate::email::EmailClient; use crate::error::Result; impl EmailClient { /// Send a password reset email pub async fn send_password_reset( &self, to_email: &str, to_name: Option<&str>, reset_url: &str, ) -> Result<()> { let subject = "Reset your password"; let body = format!( r#"Hi{name}, You requested to reset your password. Click the link below to set a new password: {url} This link expires in 15 minutes. If you didn't request this, you can ignore this email. - Makenotwork"#, name = crate::email::greeting(to_name), url = reset_url ); self.transport.send_email(to_email, subject, &body).await } /// Send an email verification email pub async fn send_verification( &self, to_email: &str, to_name: Option<&str>, verify_url: &str, ) -> Result<()> { let subject = "Verify your email"; let body = format!( r#"Hi{name}, Please verify your email address by clicking the link below: {url} This link expires in 24 hours. - Makenotwork"#, name = crate::email::greeting(to_name), url = verify_url ); self.transport.send_email(to_email, subject, &body).await } /// Send an account lockout notification pub async fn send_lockout_notification( &self, to_email: &str, to_name: Option<&str>, login_link_url: Option<&str>, ) -> Result<()> { let subject = "Security alert: Account locked"; let body = format!( r#"Hi{name}, Your account has been temporarily locked due to multiple failed login attempts. {login_link} If this wasn't you, please contact support immediately. - Makenotwork"#, name = crate::email::greeting(to_name), login_link = login_link_url .map(|url| format!("Use this link to log in securely:\n\n{}\n\nThis link expires in 15 minutes.", url)) .unwrap_or_else(|| "Your account will unlock automatically in 15 minutes.".to_string()) ); self.transport.send_email(to_email, subject, &body).await } /// Send a one-time login link pub async fn send_login_link( &self, to_email: &str, to_name: Option<&str>, login_url: &str, ) -> Result<()> { let subject = "Your login link"; let body = format!( r#"Hi{name}, Click the link below to log in to your account: {url} This link expires in 15 minutes and can only be used once. If you didn't request this, you can ignore this email. - Makenotwork"#, name = crate::email::greeting(to_name), url = login_url ); self.transport.send_email(to_email, subject, &body).await } /// Send account deletion confirmation email pub async fn send_deletion_confirmation( &self, to_email: &str, to_name: Option<&str>, delete_url: &str, ) -> Result<()> { let subject = "Confirm account deletion"; let body = format!( r#"Hi{name}, You requested to delete your Makenotwork account. IMPORTANT: This action is permanent and cannot be undone. Clicking the link below will immediately and permanently delete: - All your projects and items - All uploaded content (audio, images) - Your profile and account settings - Your custom links Purchases made by your fans will remain accessible to them. To confirm deletion, click this link: {url} This link expires in 1 hour. If you did not request this, do NOT click the link. Your account is safe. - Makenotwork"#, name = crate::email::greeting(to_name), url = delete_url ); self.transport.send_email(to_email, subject, &body).await } /// Send a new-device login notification pub async fn send_new_login_notification( &self, to_email: &str, to_name: Option<&str>, device: Option<&str>, ip: Option<&str>, unsub_url: Option<&str>, ) -> Result<()> { let subject = "New sign-in to your account"; let device_line = device.unwrap_or("Unknown device"); let ip_line = ip.unwrap_or("Unknown"); let body = format!( r#"Hi{name}, Your account was just signed in to from a new device. Device: {device} IP address: {ip} If this was you, no action is needed. If you don't recognize this sign-in, go to your dashboard and revoke the session under Settings > Sessions. - Makenotwork"#, name = crate::email::greeting(to_name), device = device_line, ip = ip_line, ); self.transport.send_email_with_unsub(to_email, subject, &body, unsub_url).await } }