mirror of
				https://github.com/dani-garcia/vaultwarden.git
				synced 2025-10-30 17:58:19 +02:00 
			
		
		
		
	Implement change-email, email-verification, account-recovery, and welcome notifications
This commit is contained in:
		| @@ -1,11 +1,13 @@ | ||||
| use rocket_contrib::json::Json; | ||||
| use chrono::Utc; | ||||
|  | ||||
| use crate::db::models::*; | ||||
| use crate::db::DbConn; | ||||
|  | ||||
| use crate::api::{EmptyResult, JsonResult, JsonUpcase, Notify, NumberOrString, PasswordData, UpdateType}; | ||||
| use crate::auth::{decode_invite, Headers}; | ||||
| use crate::auth::{decode_invite, decode_delete, decode_verify_email, Headers}; | ||||
| use crate::mail; | ||||
| use crate::crypto; | ||||
|  | ||||
| use crate::CONFIG; | ||||
|  | ||||
| @@ -25,6 +27,10 @@ pub fn routes() -> Vec<Route> { | ||||
|         post_sstamp, | ||||
|         post_email_token, | ||||
|         post_email, | ||||
|         post_verify_email, | ||||
|         post_verify_email_token, | ||||
|         post_delete_recover, | ||||
|         post_delete_recover_token, | ||||
|         delete_account, | ||||
|         post_delete_account, | ||||
|         revision_date, | ||||
| @@ -126,6 +132,20 @@ fn register(data: JsonUpcase<RegisterData>, conn: DbConn) -> EmptyResult { | ||||
|         user.public_key = Some(keys.PublicKey); | ||||
|     } | ||||
|  | ||||
|     if CONFIG.mail_enabled() { | ||||
|         if CONFIG.signups_verify() { | ||||
|             if let Err(e) = mail::send_welcome_must_verify(&user.email, &user.uuid) { | ||||
|                 error!("Error sending welcome email: {:#?}", e); | ||||
|             } | ||||
|  | ||||
|             user.last_verifying_at = Some(user.created_at); | ||||
|         } else { | ||||
|             if let Err(e) = mail::send_welcome(&user.email) { | ||||
|                 error!("Error sending welcome email: {:#?}", e); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     user.save(&conn) | ||||
| } | ||||
|  | ||||
| @@ -341,8 +361,9 @@ struct EmailTokenData { | ||||
| #[post("/accounts/email-token", data = "<data>")] | ||||
| fn post_email_token(data: JsonUpcase<EmailTokenData>, headers: Headers, conn: DbConn) -> EmptyResult { | ||||
|     let data: EmailTokenData = data.into_inner().data; | ||||
|     let mut user = headers.user; | ||||
|  | ||||
|     if !headers.user.check_valid_password(&data.MasterPasswordHash) { | ||||
|     if !user.check_valid_password(&data.MasterPasswordHash) { | ||||
|         err!("Invalid password") | ||||
|     } | ||||
|  | ||||
| @@ -350,7 +371,21 @@ fn post_email_token(data: JsonUpcase<EmailTokenData>, headers: Headers, conn: Db | ||||
|         err!("Email already in use"); | ||||
|     } | ||||
|  | ||||
|     Ok(()) | ||||
|     if !CONFIG.signups_allowed() && !CONFIG.can_signup_user(&data.NewEmail) { | ||||
|         err!("Email cannot be changed to this address"); | ||||
|     } | ||||
|  | ||||
|     let token = crypto::generate_token(6)?; | ||||
|  | ||||
|     if CONFIG.mail_enabled() { | ||||
|         if let Err(e) = mail::send_change_email(&data.NewEmail, &token) { | ||||
|             error!("Error sending change-email email: {:#?}", e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     user.email_new = Some(data.NewEmail); | ||||
|     user.email_new_token = Some(token); | ||||
|     user.save(&conn) | ||||
| } | ||||
|  | ||||
| #[derive(Deserialize)] | ||||
| @@ -361,8 +396,7 @@ struct ChangeEmailData { | ||||
|  | ||||
|     Key: String, | ||||
|     NewMasterPasswordHash: String, | ||||
|     #[serde(rename = "Token")] | ||||
|     _Token: NumberOrString, | ||||
|     Token: NumberOrString, | ||||
| } | ||||
|  | ||||
| #[post("/accounts/email", data = "<data>")] | ||||
| @@ -378,7 +412,32 @@ fn post_email(data: JsonUpcase<ChangeEmailData>, headers: Headers, conn: DbConn) | ||||
|         err!("Email already in use"); | ||||
|     } | ||||
|  | ||||
|     match user.email_new { | ||||
|         Some(ref val) => { | ||||
|             if *val != data.NewEmail.to_string() { | ||||
|                 err!("Email change mismatch"); | ||||
|             } | ||||
|         }, | ||||
|         None => err!("No email change pending"), | ||||
|     } | ||||
|  | ||||
|     if CONFIG.mail_enabled() { | ||||
|         // Only check the token if we sent out an email... | ||||
|         match user.email_new_token { | ||||
|             Some(ref val) => | ||||
|                 if *val != data.Token.into_string() { | ||||
|                     err!("Token mismatch"); | ||||
|                 } | ||||
|             None => err!("No email change pending"), | ||||
|         } | ||||
|         user.verified_at = Some(Utc::now().naive_utc()); | ||||
|     } else { | ||||
|         user.verified_at = None; | ||||
|     } | ||||
|  | ||||
|     user.email = data.NewEmail; | ||||
|     user.email_new = None; | ||||
|     user.email_new_token = None; | ||||
|  | ||||
|     user.set_password(&data.NewMasterPasswordHash); | ||||
|     user.akey = data.Key; | ||||
| @@ -386,6 +445,112 @@ fn post_email(data: JsonUpcase<ChangeEmailData>, headers: Headers, conn: DbConn) | ||||
|     user.save(&conn) | ||||
| } | ||||
|  | ||||
| #[post("/accounts/verify-email")] | ||||
| fn post_verify_email(headers: Headers, _conn: DbConn) -> EmptyResult { | ||||
|     let user = headers.user; | ||||
|  | ||||
|     if !CONFIG.mail_enabled() { | ||||
|         err!("Cannot verify email address"); | ||||
|     } | ||||
|  | ||||
|     if let Err(e) = mail::send_verify_email(&user.email, &user.uuid) { | ||||
|         error!("Error sending delete account email: {:#?}", e); | ||||
|     } | ||||
|  | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| #[derive(Deserialize)] | ||||
| #[allow(non_snake_case)] | ||||
| struct VerifyEmailTokenData { | ||||
|     UserId: String, | ||||
|     Token: String, | ||||
| } | ||||
|  | ||||
| #[post("/accounts/verify-email-token", data = "<data>")] | ||||
| fn post_verify_email_token(data: JsonUpcase<VerifyEmailTokenData>, conn: DbConn) -> EmptyResult { | ||||
|     let data: VerifyEmailTokenData = data.into_inner().data; | ||||
|  | ||||
|     let mut user = match User::find_by_uuid(&data.UserId, &conn) { | ||||
|         Some(user) => user, | ||||
|         None => err!("User doesn't exist"), | ||||
|     }; | ||||
|  | ||||
|     let claims = match decode_verify_email(&data.Token) { | ||||
|         Ok(claims) => claims, | ||||
|         Err(_) => err!("Invalid claim"), | ||||
|     }; | ||||
|      | ||||
|     if claims.sub != user.uuid { | ||||
|        err!("Invalid claim"); | ||||
|     } | ||||
|      | ||||
|     user.verified_at = Some(Utc::now().naive_utc()); | ||||
|     user.last_verifying_at = None; | ||||
|     user.login_verify_count = 0; | ||||
|     if let Err(e) = user.save(&conn) { | ||||
|         error!("Error saving email verification: {:#?}", e); | ||||
|     } | ||||
|  | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| #[derive(Deserialize)] | ||||
| #[allow(non_snake_case)] | ||||
| struct DeleteRecoverData { | ||||
|     Email: String, | ||||
| } | ||||
|  | ||||
| #[post("/accounts/delete-recover", data="<data>")] | ||||
| fn post_delete_recover(data: JsonUpcase<DeleteRecoverData>, conn: DbConn) -> EmptyResult { | ||||
|     let data: DeleteRecoverData = data.into_inner().data; | ||||
|  | ||||
|     let user = User::find_by_mail(&data.Email, &conn); | ||||
|  | ||||
|     if CONFIG.mail_enabled() { | ||||
|         if let Some(user) = user { | ||||
|             if let Err(e) = mail::send_delete_account(&user.email, &user.uuid) { | ||||
|                 error!("Error sending delete account email: {:#?}", e); | ||||
|             } | ||||
|         } | ||||
|         Ok(()) | ||||
|     } else { | ||||
|         // We don't support sending emails, but we shouldn't allow anybody | ||||
|         // to delete accounts without at least logging in... And if the user | ||||
|         // cannot remember their password then they will need to contact | ||||
|         // the administrator to delete it... | ||||
|         err!("Please contact the administrator to delete your account"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Deserialize)] | ||||
| #[allow(non_snake_case)] | ||||
| struct DeleteRecoverTokenData { | ||||
|     UserId: String, | ||||
|     Token: String, | ||||
| } | ||||
|  | ||||
| #[post("/accounts/delete-recover-token", data="<data>")] | ||||
| fn post_delete_recover_token(data: JsonUpcase<DeleteRecoverTokenData>, conn: DbConn) -> EmptyResult { | ||||
|     let data: DeleteRecoverTokenData = data.into_inner().data; | ||||
|  | ||||
|     let user = match User::find_by_uuid(&data.UserId, &conn) { | ||||
|         Some(user) => user, | ||||
|         None => err!("User doesn't exist"), | ||||
|     }; | ||||
|  | ||||
|     let claims = match decode_delete(&data.Token) { | ||||
|         Ok(claims) => claims, | ||||
|         Err(_) => err!("Invalid claim"), | ||||
|     }; | ||||
|      | ||||
|     if claims.sub != user.uuid { | ||||
|        err!("Invalid claim"); | ||||
|     } | ||||
|      | ||||
|     user.delete(&conn) | ||||
| } | ||||
|  | ||||
| #[post("/accounts/delete", data = "<data>")] | ||||
| fn post_delete_account(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn) -> EmptyResult { | ||||
|     delete_account(data, headers, conn) | ||||
|   | ||||
| @@ -66,7 +66,7 @@ pub fn send_token(user_uuid: &str, conn: &DbConn) -> EmptyResult { | ||||
|     let type_ = TwoFactorType::Email as i32; | ||||
|     let mut twofactor = TwoFactor::find_by_user_and_type(user_uuid, type_, &conn)?; | ||||
|  | ||||
|     let generated_token = generate_token(CONFIG.email_token_size())?; | ||||
|     let generated_token = crypto::generate_token(CONFIG.email_token_size())?; | ||||
|  | ||||
|     let mut twofactor_data = EmailTokenData::from_json(&twofactor.data)?; | ||||
|     twofactor_data.set_token(generated_token); | ||||
| @@ -109,22 +109,6 @@ struct SendEmailData { | ||||
|     MasterPasswordHash: String, | ||||
| } | ||||
|  | ||||
|  | ||||
| fn generate_token(token_size: u32) -> Result<String, Error> { | ||||
|     if token_size > 19 { | ||||
|         err!("Generating token failed") | ||||
|     } | ||||
|  | ||||
|     // 8 bytes to create an u64 for up to 19 token digits | ||||
|     let bytes = crypto::get_random(vec![0; 8]); | ||||
|     let mut bytes_array = [0u8; 8]; | ||||
|     bytes_array.copy_from_slice(&bytes); | ||||
|  | ||||
|     let number = u64::from_be_bytes(bytes_array) % 10u64.pow(token_size); | ||||
|     let token = format!("{:0size$}", number, size = token_size as usize); | ||||
|     Ok(token) | ||||
| } | ||||
|  | ||||
| /// Send a verification email to the specified email address to check whether it exists/belongs to user. | ||||
| #[post("/two-factor/send-email", data = "<data>")] | ||||
| fn send_email(data: JsonUpcase<SendEmailData>, headers: Headers, conn: DbConn) -> EmptyResult { | ||||
| @@ -145,7 +129,7 @@ fn send_email(data: JsonUpcase<SendEmailData>, headers: Headers, conn: DbConn) - | ||||
|         tf.delete(&conn)?; | ||||
|     } | ||||
|  | ||||
|     let generated_token = generate_token(CONFIG.email_token_size())?; | ||||
|     let generated_token = crypto::generate_token(CONFIG.email_token_size())?; | ||||
|     let twofactor_data = EmailTokenData::new(data.Email, generated_token); | ||||
|  | ||||
|     // Uses EmailVerificationChallenge as type to show that it's not verified yet. | ||||
|   | ||||
| @@ -3,6 +3,7 @@ use rocket::request::{Form, FormItems, FromForm}; | ||||
| use rocket::Route; | ||||
| use rocket_contrib::json::Json; | ||||
| use serde_json::Value; | ||||
| use chrono::Utc; | ||||
|  | ||||
| use crate::api::core::two_factor::email::EmailTokenData; | ||||
| use crate::api::core::two_factor::{duo, email, yubikey}; | ||||
| @@ -96,6 +97,34 @@ fn _password_login(data: ConnectData, conn: DbConn, ip: ClientIp) -> JsonResult | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     if !user.verified_at.is_some() && CONFIG.mail_enabled() && CONFIG.signups_verify() { | ||||
|         let now = Utc::now().naive_utc(); | ||||
|         if user.last_verifying_at.is_none() || now.signed_duration_since(user.last_verifying_at.unwrap()).num_seconds() > CONFIG.signups_verify_resend_time() as i64 { | ||||
|             let resend_limit = CONFIG.signups_verify_resend_limit() as i32; | ||||
|             if resend_limit == 0 || user.login_verify_count < resend_limit { | ||||
|                 // We want to send another email verification if we require signups to verify | ||||
|                 // their email address, and we haven't sent them a reminder in a while... | ||||
|                 let mut user = user; | ||||
|                 user.last_verifying_at = Some(now); | ||||
|                 user.login_verify_count = user.login_verify_count + 1; | ||||
|  | ||||
|                 if let Err(e) = user.save(&conn) { | ||||
|                     error!("Error updating user: {:#?}", e); | ||||
|                 } | ||||
|  | ||||
|                 if let Err(e) = mail::send_verify_email(&user.email, &user.uuid) { | ||||
|                     error!("Error auto-sending email verification email: {:#?}", e); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // We still want the login to fail until they actually verified the email address | ||||
|         err!( | ||||
|             "Please verify your email before trying again.", | ||||
|             format!("IP: {}. Username: {}.", ip.ip, username) | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     let (mut device, new_device) = get_device(&data, &conn, &user); | ||||
|  | ||||
|     let twofactor_token = twofactor_auth(&user.uuid, &data, &mut device, &conn)?; | ||||
|   | ||||
							
								
								
									
										58
									
								
								src/auth.rs
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								src/auth.rs
									
									
									
									
									
								
							| @@ -18,6 +18,8 @@ lazy_static! { | ||||
|     static ref JWT_HEADER: Header = Header::new(JWT_ALGORITHM); | ||||
|     pub static ref JWT_LOGIN_ISSUER: String = format!("{}|login", CONFIG.domain()); | ||||
|     pub static ref JWT_INVITE_ISSUER: String = format!("{}|invite", CONFIG.domain()); | ||||
|     pub static ref JWT_DELETE_ISSUER: String = format!("{}|delete", CONFIG.domain()); | ||||
|     pub static ref JWT_VERIFYEMAIL_ISSUER: String = format!("{}|verifyemail", CONFIG.domain()); | ||||
|     pub static ref JWT_ADMIN_ISSUER: String = format!("{}|admin", CONFIG.domain()); | ||||
|     static ref PRIVATE_RSA_KEY: Vec<u8> = match read_file(&CONFIG.private_rsa_key()) { | ||||
|         Ok(key) => key, | ||||
| @@ -62,6 +64,14 @@ pub fn decode_invite(token: &str) -> Result<InviteJWTClaims, Error> { | ||||
|     decode_jwt(token, JWT_INVITE_ISSUER.to_string()) | ||||
| } | ||||
|  | ||||
| pub fn decode_delete(token: &str) -> Result<DeleteJWTClaims, Error> { | ||||
|     decode_jwt(token, JWT_DELETE_ISSUER.to_string()) | ||||
| } | ||||
|  | ||||
| pub fn decode_verify_email(token: &str) -> Result<VerifyEmailJWTClaims, Error> { | ||||
|     decode_jwt(token, JWT_VERIFYEMAIL_ISSUER.to_string()) | ||||
| } | ||||
|  | ||||
| pub fn decode_admin(token: &str) -> Result<AdminJWTClaims, Error> { | ||||
|     decode_jwt(token, JWT_ADMIN_ISSUER.to_string()) | ||||
| } | ||||
| @@ -134,6 +144,54 @@ pub fn generate_invite_claims( | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Serialize, Deserialize)] | ||||
| pub struct DeleteJWTClaims { | ||||
|     // Not before | ||||
|     pub nbf: i64, | ||||
|     // Expiration time | ||||
|     pub exp: i64, | ||||
|     // Issuer | ||||
|     pub iss: String, | ||||
|     // Subject | ||||
|     pub sub: String, | ||||
| } | ||||
|  | ||||
| pub fn generate_delete_claims( | ||||
|     uuid: String, | ||||
| ) -> DeleteJWTClaims { | ||||
|     let time_now = Utc::now().naive_utc(); | ||||
|     DeleteJWTClaims { | ||||
|         nbf: time_now.timestamp(), | ||||
|         exp: (time_now + Duration::days(5)).timestamp(), | ||||
|         iss: JWT_DELETE_ISSUER.to_string(), | ||||
|         sub: uuid, | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Serialize, Deserialize)] | ||||
| pub struct VerifyEmailJWTClaims { | ||||
|     // Not before | ||||
|     pub nbf: i64, | ||||
|     // Expiration time | ||||
|     pub exp: i64, | ||||
|     // Issuer | ||||
|     pub iss: String, | ||||
|     // Subject | ||||
|     pub sub: String, | ||||
| } | ||||
|  | ||||
| pub fn generate_verify_email_claims( | ||||
|     uuid: String, | ||||
| ) -> DeleteJWTClaims { | ||||
|     let time_now = Utc::now().naive_utc(); | ||||
|     DeleteJWTClaims { | ||||
|         nbf: time_now.timestamp(), | ||||
|         exp: (time_now + Duration::days(5)).timestamp(), | ||||
|         iss: JWT_VERIFYEMAIL_ISSUER.to_string(), | ||||
|         sub: uuid, | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Serialize, Deserialize)] | ||||
| pub struct AdminJWTClaims { | ||||
|     // Not before | ||||
|   | ||||
| @@ -243,6 +243,12 @@ make_config! { | ||||
|         disable_icon_download:  bool,   true,   def,    false; | ||||
|         /// Allow new signups |> Controls if new users can register. Note that while this is disabled, users could still be invited | ||||
|         signups_allowed:        bool,   true,   def,    true; | ||||
|         /// Require email verification on signups. This will prevent logins from succeeding until the address has been verified | ||||
|         signups_verify:         bool,   true,   def,    false; | ||||
|         /// If signups require email verification, automatically re-send verification email if it hasn't been sent for a while (in seconds) | ||||
|         signups_verify_resend_time: u64, true,  def,    3_600; | ||||
|         /// If signups require email verification, limit how many emails are automatically sent when login is attempted (0 means no limit) | ||||
|         signups_verify_resend_limit: u32, true, def,    6; | ||||
|         /// Allow signups only from this list of comma-separated domains | ||||
|         signups_domains_whitelist: String, true, def,   "".to_string(); | ||||
|         /// Allow invitations |> Controls whether users can be invited by organization admins, even when signups are disabled | ||||
| @@ -595,6 +601,8 @@ fn load_templates(path: &str) -> Handlebars { | ||||
|     } | ||||
|  | ||||
|     // First register default templates here | ||||
|     reg!("email/change_email", ".html"); | ||||
|     reg!("email/delete_account", ".html"); | ||||
|     reg!("email/invite_accepted", ".html"); | ||||
|     reg!("email/invite_confirmed", ".html"); | ||||
|     reg!("email/new_device_logged_in", ".html"); | ||||
| @@ -602,6 +610,9 @@ fn load_templates(path: &str) -> Handlebars { | ||||
|     reg!("email/pw_hint_some", ".html"); | ||||
|     reg!("email/send_org_invite", ".html"); | ||||
|     reg!("email/twofactor_email", ".html"); | ||||
|     reg!("email/verify_email", ".html"); | ||||
|     reg!("email/welcome", ".html"); | ||||
|     reg!("email/welcome_must_verify", ".html"); | ||||
|  | ||||
|     reg!("admin/base"); | ||||
|     reg!("admin/login"); | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
|  | ||||
| use ring::{digest, hmac, pbkdf2}; | ||||
| use std::num::NonZeroU32; | ||||
| use crate::error::Error; | ||||
|  | ||||
| static DIGEST_ALG: &digest::Algorithm = &digest::SHA256; | ||||
| const OUTPUT_LEN: usize = digest::SHA256_OUTPUT_LEN; | ||||
| @@ -52,6 +53,21 @@ pub fn get_random(mut array: Vec<u8>) -> Vec<u8> { | ||||
|     array | ||||
| } | ||||
|  | ||||
| pub fn generate_token(token_size: u32) -> Result<String, Error> { | ||||
|     if token_size > 19 { | ||||
|         err!("Generating token failed") | ||||
|     } | ||||
|  | ||||
|     // 8 bytes to create an u64 for up to 19 token digits | ||||
|     let bytes = get_random(vec![0; 8]); | ||||
|     let mut bytes_array = [0u8; 8]; | ||||
|     bytes_array.copy_from_slice(&bytes); | ||||
|  | ||||
|     let number = u64::from_be_bytes(bytes_array) % 10u64.pow(token_size); | ||||
|     let token = format!("{:0size$}", number, size = token_size as usize); | ||||
|     Ok(token) | ||||
| } | ||||
|  | ||||
| // | ||||
| // Constant time compare | ||||
| // | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| use chrono::{NaiveDateTime, Utc}; | ||||
|  | ||||
| use super::User; | ||||
| use crate::CONFIG; | ||||
|  | ||||
| #[derive(Debug, Identifiable, Queryable, Insertable, Associations, AsChangeset)] | ||||
| #[table_name = "devices"] | ||||
| @@ -87,7 +88,7 @@ impl Device { | ||||
|             premium: true, | ||||
|             name: user.name.to_string(), | ||||
|             email: user.email.to_string(), | ||||
|             email_verified: true, | ||||
|             email_verified: !CONFIG.mail_enabled() || user.verified_at.is_some(), | ||||
|  | ||||
|             orgowner, | ||||
|             orgadmin, | ||||
|   | ||||
| @@ -11,8 +11,13 @@ pub struct User { | ||||
|     pub uuid: String, | ||||
|     pub created_at: NaiveDateTime, | ||||
|     pub updated_at: NaiveDateTime, | ||||
|     pub verified_at: Option<NaiveDateTime>, | ||||
|     pub last_verifying_at: Option<NaiveDateTime>, | ||||
|     pub login_verify_count: i32, | ||||
|  | ||||
|     pub email: String, | ||||
|     pub email_new: Option<String>, | ||||
|     pub email_new_token: Option<String>, | ||||
|     pub name: String, | ||||
|  | ||||
|     pub password_hash: Vec<u8>, | ||||
| @@ -56,9 +61,14 @@ impl User { | ||||
|             uuid: crate::util::get_uuid(), | ||||
|             created_at: now, | ||||
|             updated_at: now, | ||||
|             verified_at: None, | ||||
|             last_verifying_at: None, | ||||
|             login_verify_count: 0, | ||||
|             name: email.clone(), | ||||
|             email, | ||||
|             akey: String::new(), | ||||
|             email_new: None, | ||||
|             email_new_token: None, | ||||
|  | ||||
|             password_hash: Vec::new(), | ||||
|             salt: crypto::get_random_64(), | ||||
| @@ -135,7 +145,7 @@ impl User { | ||||
|             "Id": self.uuid, | ||||
|             "Name": self.name, | ||||
|             "Email": self.email, | ||||
|             "EmailVerified": true, | ||||
|             "EmailVerified": !CONFIG.mail_enabled() || self.verified_at.is_some(), | ||||
|             "Premium": true, | ||||
|             "MasterPasswordHint": self.password_hint, | ||||
|             "Culture": "en-US", | ||||
|   | ||||
| @@ -101,7 +101,12 @@ table! { | ||||
|         uuid -> Varchar, | ||||
|         created_at -> Datetime, | ||||
|         updated_at -> Datetime, | ||||
|         verified_at -> Nullable<Datetime>, | ||||
|         last_verifying_at -> Nullable<Datetime>, | ||||
|         login_verify_count -> Integer, | ||||
|         email -> Varchar, | ||||
|         email_new -> Nullable<Varchar>, | ||||
|         email_new_token -> Nullable<Varchar>, | ||||
|         name -> Text, | ||||
|         password_hash -> Blob, | ||||
|         salt -> Blob, | ||||
|   | ||||
| @@ -101,7 +101,12 @@ table! { | ||||
|         uuid -> Text, | ||||
|         created_at -> Timestamp, | ||||
|         updated_at -> Timestamp, | ||||
|         verified_at -> Nullable<Timestamp>, | ||||
|         last_verifying_at -> Nullable<Timestamp>, | ||||
|         login_verify_count -> Integer, | ||||
|         email -> Text, | ||||
|         email_new -> Nullable<Text>, | ||||
|         email_new_token -> Nullable<Text>, | ||||
|         name -> Text, | ||||
|         password_hash -> Binary, | ||||
|         salt -> Binary, | ||||
| @@ -170,4 +175,4 @@ allow_tables_to_appear_in_same_query!( | ||||
|     users, | ||||
|     users_collections, | ||||
|     users_organizations, | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -101,7 +101,12 @@ table! { | ||||
|         uuid -> Text, | ||||
|         created_at -> Timestamp, | ||||
|         updated_at -> Timestamp, | ||||
|         verified_at -> Nullable<Timestamp>, | ||||
|         last_verifying_at -> Nullable<Timestamp>, | ||||
|         login_verify_count -> Integer, | ||||
|         email -> Text, | ||||
|         email_new -> Nullable<Text>, | ||||
|         email_new_token -> Nullable<Text>, | ||||
|         name -> Text, | ||||
|         password_hash -> Binary, | ||||
|         salt -> Binary, | ||||
|   | ||||
							
								
								
									
										81
									
								
								src/mail.rs
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								src/mail.rs
									
									
									
									
									
								
							| @@ -8,7 +8,7 @@ use percent_encoding::{percent_encode, NON_ALPHANUMERIC}; | ||||
| use quoted_printable::encode_to_str; | ||||
|  | ||||
| use crate::api::EmptyResult; | ||||
| use crate::auth::{encode_jwt, generate_invite_claims}; | ||||
| use crate::auth::{encode_jwt, generate_invite_claims, generate_delete_claims, generate_verify_email_claims}; | ||||
| use crate::error::Error; | ||||
| use crate::CONFIG; | ||||
| use chrono::NaiveDateTime; | ||||
| @@ -95,6 +95,73 @@ pub fn send_password_hint(address: &str, hint: Option<String>) -> EmptyResult { | ||||
|     send_email(&address, &subject, &body_html, &body_text) | ||||
| } | ||||
|  | ||||
| pub fn send_delete_account(address: &str, uuid: &str) -> EmptyResult { | ||||
|     let claims = generate_delete_claims( | ||||
|         uuid.to_string(), | ||||
|     ); | ||||
|     let delete_token = encode_jwt(&claims); | ||||
|  | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/delete_account", | ||||
|         json!({ | ||||
|             "url": CONFIG.domain(), | ||||
|             "user_id": uuid, | ||||
|             "email": percent_encode(address.as_bytes(), NON_ALPHANUMERIC).to_string(), | ||||
|             "token": delete_token, | ||||
|         }), | ||||
|     )?; | ||||
|  | ||||
|     send_email(&address, &subject, &body_html, &body_text) | ||||
| } | ||||
|  | ||||
| pub fn send_verify_email(address: &str, uuid: &str) -> EmptyResult { | ||||
|     let claims = generate_verify_email_claims( | ||||
|         uuid.to_string(), | ||||
|     ); | ||||
|     let verify_email_token = encode_jwt(&claims); | ||||
|  | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/verify_email", | ||||
|         json!({ | ||||
|             "url": CONFIG.domain(), | ||||
|             "user_id": uuid, | ||||
|             "email": percent_encode(address.as_bytes(), NON_ALPHANUMERIC).to_string(), | ||||
|             "token": verify_email_token, | ||||
|         }), | ||||
|     )?; | ||||
|  | ||||
|     send_email(&address, &subject, &body_html, &body_text) | ||||
| } | ||||
|  | ||||
| pub fn send_welcome(address: &str) -> EmptyResult { | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/welcome", | ||||
|         json!({ | ||||
|             "url": CONFIG.domain(), | ||||
|         }), | ||||
|     )?; | ||||
|  | ||||
|     send_email(&address, &subject, &body_html, &body_text) | ||||
| } | ||||
|  | ||||
| pub fn send_welcome_must_verify(address: &str, uuid: &str) -> EmptyResult { | ||||
|     let claims = generate_verify_email_claims( | ||||
|         uuid.to_string(), | ||||
|     ); | ||||
|     let verify_email_token = encode_jwt(&claims); | ||||
|  | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/welcome_must_verify", | ||||
|         json!({ | ||||
|             "url": CONFIG.domain(), | ||||
|             "user_id": uuid, | ||||
|             "token": verify_email_token, | ||||
|         }), | ||||
|     )?; | ||||
|  | ||||
|     send_email(&address, &subject, &body_html, &body_text) | ||||
| } | ||||
|  | ||||
| pub fn send_invite( | ||||
|     address: &str, | ||||
|     uuid: &str, | ||||
| @@ -183,6 +250,18 @@ pub fn send_token(address: &str, token: &str) -> EmptyResult { | ||||
|     send_email(&address, &subject, &body_html, &body_text) | ||||
| } | ||||
|  | ||||
| pub fn send_change_email(address: &str, token: &str) -> EmptyResult { | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/change_email", | ||||
|         json!({ | ||||
|             "url": CONFIG.domain(), | ||||
|             "token": token, | ||||
|         }), | ||||
|     )?; | ||||
|  | ||||
|     send_email(&address, &subject, &body_html, &body_text) | ||||
| } | ||||
|  | ||||
| fn send_email(address: &str, subject: &str, body_html: &str, body_text: &str) -> EmptyResult { | ||||
|     let html = PartBuilder::new() | ||||
|         .body(encode_to_str(body_html)) | ||||
|   | ||||
							
								
								
									
										6
									
								
								src/static/templates/email/change_email.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/static/templates/email/change_email.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| Your Email Change | ||||
| <!----------------> | ||||
| <html> | ||||
| <p>To finalize changing your email address enter the following code in web vault: <b>{{token}}</b></p> | ||||
| <p>If you did not try to change an email address, you can safely ignore this email.</p> | ||||
| </html> | ||||
							
								
								
									
										129
									
								
								src/static/templates/email/change_email.html.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								src/static/templates/email/change_email.html.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| Your Email Change | ||||
| <!----------------> | ||||
| <html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|    <head> | ||||
|       <meta name="viewport" content="width=device-width" /> | ||||
|       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
|       <title>Bitwarden_rs</title> | ||||
|    </head> | ||||
|    <body style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; height: 100%; line-height: 25px; width: 100% !important;" bgcolor="#f6f6f6"> | ||||
|       <style type="text/css"> | ||||
|           body { | ||||
|          margin: 0; | ||||
|          font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | ||||
|          box-sizing: border-box; | ||||
|          font-size: 16px; | ||||
|          color: #333; | ||||
|          line-height: 25px; | ||||
|          -webkit-font-smoothing: antialiased; | ||||
|          -webkit-text-size-adjust: none; | ||||
|          } | ||||
|          body * { | ||||
|          margin: 0; | ||||
|          font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | ||||
|          box-sizing: border-box; | ||||
|          font-size: 16px; | ||||
|          color: #333; | ||||
|          line-height: 25px; | ||||
|          -webkit-font-smoothing: antialiased; | ||||
|          -webkit-text-size-adjust: none; | ||||
|          } | ||||
|          img { | ||||
|          max-width: 100%; | ||||
|          border: none; | ||||
|          } | ||||
|          body { | ||||
|          -webkit-font-smoothing: antialiased; | ||||
|          -webkit-text-size-adjust: none; | ||||
|          width: 100% !important; | ||||
|          height: 100%; | ||||
|          line-height: 25px; | ||||
|          } | ||||
|          body { | ||||
|          background-color: #f6f6f6; | ||||
|          } | ||||
|          @media only screen and (max-width: 600px) { | ||||
|          body { | ||||
|          padding: 0 !important; | ||||
|          } | ||||
|          .container { | ||||
|          padding: 0 !important; | ||||
|          width: 100% !important; | ||||
|          } | ||||
|          .container-table { | ||||
|          padding: 0 !important; | ||||
|          width: 100% !important; | ||||
|          } | ||||
|          .content { | ||||
|          padding: 0 0 10px 0 !important; | ||||
|          } | ||||
|          .content-wrap { | ||||
|          padding: 10px !important; | ||||
|          } | ||||
|          .invoice { | ||||
|          width: 100% !important; | ||||
|          } | ||||
|          .main { | ||||
|          border-right: none !important; | ||||
|          border-left: none !important; | ||||
|          border-radius: 0 !important; | ||||
|          } | ||||
|          .logo { | ||||
|          padding-top: 10px !important; | ||||
|          } | ||||
|          .footer { | ||||
|          margin-top: 10px !important; | ||||
|          } | ||||
|          .indented { | ||||
|          padding-left: 10px; | ||||
|          } | ||||
|          } | ||||
|       </style> | ||||
|       <table class="body-wrap" cellpadding="0" cellspacing="0" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; width: 100%;" bgcolor="#f6f6f6"> | ||||
|          <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|             <td valign="middle" class="aligncenter middle logo" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; padding: 20px 0 10px;" align="center"> | ||||
|                 <img src="{{url}}/bwrs_static/logo-gray.png" alt="" width="250" height="39" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; border: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; max-width: 100%;" /> | ||||
|             </td> | ||||
|          </tr> | ||||
|          <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|             <td class="container" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both !important; color: #333; display: block !important; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto; max-width: 600px !important; width: 600px;" valign="top"> | ||||
|                <table cellpadding="0" cellspacing="0" class="container-table" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both !important; color: #333; display: block !important; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto; max-width: 600px !important; width: 600px;"> | ||||
|                   <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|                      <td class="content" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; display: block; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 0; line-height: 0; margin: 0 auto; max-width: 600px; padding-bottom: 20px;" valign="top"> | ||||
|                         <table class="main" width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; margin: 0; -webkit-text-size-adjust: none; border: 1px solid #e9e9e9; border-radius: 3px;" bgcolor="white"> | ||||
|                            <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                               <td class="content-wrap" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 20px; -webkit-text-size-adjust: none;" valign="top"> | ||||
|                                  <table width="100%" cellpadding="0" cellspacing="0" style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center"> | ||||
|                                           To finalize changing your email address enter the following code in web vault: <b style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">{{token}}</b> | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block last" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center"> | ||||
|                                          If you did not try to change an email address, you can safely ignore this email.  | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                  </table> | ||||
|                               </td> | ||||
|                            </tr> | ||||
|                         </table> | ||||
|                         <table class="footer" cellpadding="0" cellspacing="0" width="100%" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; width: 100%;"> | ||||
|                            <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|                               <td class="aligncenter social-icons" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; padding: 15px 0 0 0;" valign="top"> | ||||
|                                  <table cellpadding="0" cellspacing="0" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto;"> | ||||
|                                     <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|                                         <td style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; padding: 0 10px;" valign="top"><a href="https://github.com/dani-garcia/bitwarden_rs" target="_blank" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; text-decoration: underline;"><img src="{{url}}/bwrs_static/mail-github.png" alt="GitHub" width="30" height="30" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; border: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; max-width: 100%;" /></a></td> | ||||
|                                     </tr> | ||||
|                                  </table> | ||||
|                               </td> | ||||
|                            </tr> | ||||
|                         </table> | ||||
|                      </td> | ||||
|                   </tr> | ||||
|                </table> | ||||
|             </td> | ||||
|          </tr> | ||||
|       </table> | ||||
|    </body> | ||||
| </html> | ||||
							
								
								
									
										12
									
								
								src/static/templates/email/delete_account.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/static/templates/email/delete_account.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| Delete Your Account | ||||
| <!----------------> | ||||
| <html> | ||||
| <p> | ||||
| click the link below to delete your account. | ||||
| <br> | ||||
| <br> | ||||
| <a href="{{url}}/#/verify-recover-delete?userId={{user_id}}&token={{token}}&email={{email}}"> | ||||
| Delete Your Account</a> | ||||
| </p> | ||||
| <p>If you did not request this email to delete your account, you can safely ignore this email.</p> | ||||
| </html> | ||||
							
								
								
									
										137
									
								
								src/static/templates/email/delete_account.html.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								src/static/templates/email/delete_account.html.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,137 @@ | ||||
| Delete Your Account | ||||
| <!----------------> | ||||
| <html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|    <head> | ||||
|       <meta name="viewport" content="width=device-width" /> | ||||
|       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
|       <title>Bitwarden_rs</title> | ||||
|    </head> | ||||
|    <body style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; height: 100%; line-height: 25px; width: 100% !important;" bgcolor="#f6f6f6"> | ||||
|       <style type="text/css"> | ||||
|           body { | ||||
|          margin: 0; | ||||
|          font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | ||||
|          box-sizing: border-box; | ||||
|          font-size: 16px; | ||||
|          color: #333; | ||||
|          line-height: 25px; | ||||
|          -webkit-font-smoothing: antialiased; | ||||
|          -webkit-text-size-adjust: none; | ||||
|          } | ||||
|          body * { | ||||
|          margin: 0; | ||||
|          font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | ||||
|          box-sizing: border-box; | ||||
|          font-size: 16px; | ||||
|          color: #333; | ||||
|          line-height: 25px; | ||||
|          -webkit-font-smoothing: antialiased; | ||||
|          -webkit-text-size-adjust: none; | ||||
|          } | ||||
|          img { | ||||
|          max-width: 100%; | ||||
|          border: none; | ||||
|          } | ||||
|          body { | ||||
|          -webkit-font-smoothing: antialiased; | ||||
|          -webkit-text-size-adjust: none; | ||||
|          width: 100% !important; | ||||
|          height: 100%; | ||||
|          line-height: 25px; | ||||
|          } | ||||
|          body { | ||||
|          background-color: #f6f6f6; | ||||
|          } | ||||
|          @media only screen and (max-width: 600px) { | ||||
|          body { | ||||
|          padding: 0 !important; | ||||
|          } | ||||
|          .container { | ||||
|          padding: 0 !important; | ||||
|          width: 100% !important; | ||||
|          } | ||||
|          .container-table { | ||||
|          padding: 0 !important; | ||||
|          width: 100% !important; | ||||
|          } | ||||
|          .content { | ||||
|          padding: 0 0 10px 0 !important; | ||||
|          } | ||||
|          .content-wrap { | ||||
|          padding: 10px !important; | ||||
|          } | ||||
|          .invoice { | ||||
|          width: 100% !important; | ||||
|          } | ||||
|          .main { | ||||
|          border-right: none !important; | ||||
|          border-left: none !important; | ||||
|          border-radius: 0 !important; | ||||
|          } | ||||
|          .logo { | ||||
|          padding-top: 10px !important; | ||||
|          } | ||||
|          .footer { | ||||
|          margin-top: 10px !important; | ||||
|          } | ||||
|          .indented { | ||||
|          padding-left: 10px; | ||||
|          } | ||||
|          } | ||||
|       </style> | ||||
|       <table class="body-wrap" cellpadding="0" cellspacing="0" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; width: 100%;" bgcolor="#f6f6f6"> | ||||
|          <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|             <td valign="middle" class="aligncenter middle logo" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; padding: 20px 0 10px;" align="center"> | ||||
|                 <img src="{{url}}/bwrs_static/logo-gray.png" alt="" width="250" height="39" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; border: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; max-width: 100%;" /> | ||||
|             </td> | ||||
|          </tr> | ||||
|          <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|             <td class="container" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both !important; color: #333; display: block !important; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto; max-width: 600px !important; width: 600px;" valign="top"> | ||||
|                <table cellpadding="0" cellspacing="0" class="container-table" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both !important; color: #333; display: block !important; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto; max-width: 600px !important; width: 600px;"> | ||||
|                   <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|                      <td class="content" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; display: block; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 0; line-height: 0; margin: 0 auto; max-width: 600px; padding-bottom: 20px;" valign="top"> | ||||
|                         <table class="main" width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; margin: 0; -webkit-text-size-adjust: none; border: 1px solid #e9e9e9; border-radius: 3px;" bgcolor="white"> | ||||
|                            <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                               <td class="content-wrap" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 20px; -webkit-text-size-adjust: none;" valign="top"> | ||||
|                                  <table width="100%" cellpadding="0" cellspacing="0" style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center"> | ||||
|                                           click the link below to delete your account. | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center"> | ||||
|                                           <a href="{{url}}/#/verify-recover-delete?userId={{user_id}}&token={{token}}&email={{email}}" | ||||
|                                              clicktracking=off target="_blank" style="color: #ffffff; text-decoration: none; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; background-color: #3c8dbc; border-color: #3c8dbc; border-style: solid; border-width: 10px 20px; margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                           Delete Your Account | ||||
|                                           </a> | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block last" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center"> | ||||
|                                           If you did not request this email to delete your account, you can safely ignore this email. | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                  </table> | ||||
|                               </td> | ||||
|                            </tr> | ||||
|                         </table> | ||||
|                         <table class="footer" cellpadding="0" cellspacing="0" width="100%" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; width: 100%;"> | ||||
|                            <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|                               <td class="aligncenter social-icons" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; padding: 15px 0 0 0;" valign="top"> | ||||
|                                  <table cellpadding="0" cellspacing="0" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto;"> | ||||
|                                     <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|                                         <td style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; padding: 0 10px;" valign="top"><a href="https://github.com/dani-garcia/bitwarden_rs" target="_blank" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; text-decoration: underline;"><img src="{{url}}/bwrs_static/mail-github.png" alt="GitHub" width="30" height="30" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; border: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; max-width: 100%;" /></a></td> | ||||
|                                     </tr> | ||||
|                                  </table> | ||||
|                               </td> | ||||
|                            </tr> | ||||
|                         </table> | ||||
|                      </td> | ||||
|                   </tr> | ||||
|                </table> | ||||
|             </td> | ||||
|          </tr> | ||||
|       </table> | ||||
|    </body> | ||||
| </html> | ||||
| @@ -1,3 +1,7 @@ | ||||
| Sorry, you have no password hint... | ||||
| Your master password hint | ||||
| <!----------------> | ||||
| Sorry, you have not specified any password hint... | ||||
| You (or someone) recently requested your master password hint. Unfortunately, your account does not have a master password hint. | ||||
|  | ||||
| If you cannot remember your master password, there is no way to recover your data. The only option to gain access to your account again is to <a href="{{url}}/#/recover-delete">delete the account</a> so that you can register again and start over. All data associated with your account will be deleted. | ||||
|  | ||||
| If you did not request your master password hint you can safely ignore this email. | ||||
|   | ||||
| @@ -99,6 +99,11 @@ Sorry, you have no password hint... | ||||
|                                           You (or someone) recently requested your master password hint. Unfortunately, your account does not have a master password hint. <br style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;" /> | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block last" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0; -webkit-text-size-adjust: none;" valign="top"> | ||||
|                                           If you cannot remember your master password, there is no way to recover your data. The only option to gain access to your account again is to <a href="{{url}}/#/recover-delete">delete the account</a> so that you can register again and start over. All data associated with your account will be deleted. | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block last" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0; -webkit-text-size-adjust: none;" valign="top"> | ||||
|                                           If you did not request your master password hint you can safely ignore this email. | ||||
|   | ||||
| @@ -5,4 +5,6 @@ You (or someone) recently requested your master password hint. | ||||
| Your hint is: "{{hint}}" | ||||
| Log in: <a href="{{url}}">Web Vault</a> | ||||
|  | ||||
| If you cannot remember your master password, there is no way to recover your data. The only option to gain access to your account again is to <a href="{{url}}/#/recover-delete">delete the account</a> so that you can register again and start over. All data associated with your account will be deleted. | ||||
|  | ||||
| If you did not request your master password hint you can safely ignore this email. | ||||
|   | ||||
| @@ -105,6 +105,11 @@ Your master password hint | ||||
|                                           Log in: <a href="{{url}}">Web Vault</a> | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block last" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0; -webkit-text-size-adjust: none;" valign="top"> | ||||
|                                           If you cannot remember your master password, there is no way to recover your data. The only option to gain access to your account again is to <a href="{{url}}/#/recover-delete">delete the account</a> so that you can register again and start over. All data associated with your account will be deleted. | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block last" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0; -webkit-text-size-adjust: none;" valign="top"> | ||||
|                                           If you did not request your master password hint you can safely ignore this email. | ||||
|   | ||||
							
								
								
									
										12
									
								
								src/static/templates/email/verify_email.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/static/templates/email/verify_email.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| Verify Your Email | ||||
| <!----------------> | ||||
| <html> | ||||
| <p> | ||||
| Verify this email address for your account by clicking the link below. | ||||
| <br> | ||||
| <br> | ||||
| <a href="{{url}}/#/verify-email/?userId={{user_id}}&token={{token}}"> | ||||
| Verify Email Address Now</a> | ||||
| </p> | ||||
| <p>If you did not request to verify your account, you can safely ignore this email.</p> | ||||
| </html> | ||||
							
								
								
									
										137
									
								
								src/static/templates/email/verify_email.html.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								src/static/templates/email/verify_email.html.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,137 @@ | ||||
| Verify Your Email | ||||
| <!----------------> | ||||
| <html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|    <head> | ||||
|       <meta name="viewport" content="width=device-width" /> | ||||
|       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
|       <title>Bitwarden_rs</title> | ||||
|    </head> | ||||
|    <body style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; height: 100%; line-height: 25px; width: 100% !important;" bgcolor="#f6f6f6"> | ||||
|       <style type="text/css"> | ||||
|           body { | ||||
|          margin: 0; | ||||
|          font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | ||||
|          box-sizing: border-box; | ||||
|          font-size: 16px; | ||||
|          color: #333; | ||||
|          line-height: 25px; | ||||
|          -webkit-font-smoothing: antialiased; | ||||
|          -webkit-text-size-adjust: none; | ||||
|          } | ||||
|          body * { | ||||
|          margin: 0; | ||||
|          font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | ||||
|          box-sizing: border-box; | ||||
|          font-size: 16px; | ||||
|          color: #333; | ||||
|          line-height: 25px; | ||||
|          -webkit-font-smoothing: antialiased; | ||||
|          -webkit-text-size-adjust: none; | ||||
|          } | ||||
|          img { | ||||
|          max-width: 100%; | ||||
|          border: none; | ||||
|          } | ||||
|          body { | ||||
|          -webkit-font-smoothing: antialiased; | ||||
|          -webkit-text-size-adjust: none; | ||||
|          width: 100% !important; | ||||
|          height: 100%; | ||||
|          line-height: 25px; | ||||
|          } | ||||
|          body { | ||||
|          background-color: #f6f6f6; | ||||
|          } | ||||
|          @media only screen and (max-width: 600px) { | ||||
|          body { | ||||
|          padding: 0 !important; | ||||
|          } | ||||
|          .container { | ||||
|          padding: 0 !important; | ||||
|          width: 100% !important; | ||||
|          } | ||||
|          .container-table { | ||||
|          padding: 0 !important; | ||||
|          width: 100% !important; | ||||
|          } | ||||
|          .content { | ||||
|          padding: 0 0 10px 0 !important; | ||||
|          } | ||||
|          .content-wrap { | ||||
|          padding: 10px !important; | ||||
|          } | ||||
|          .invoice { | ||||
|          width: 100% !important; | ||||
|          } | ||||
|          .main { | ||||
|          border-right: none !important; | ||||
|          border-left: none !important; | ||||
|          border-radius: 0 !important; | ||||
|          } | ||||
|          .logo { | ||||
|          padding-top: 10px !important; | ||||
|          } | ||||
|          .footer { | ||||
|          margin-top: 10px !important; | ||||
|          } | ||||
|          .indented { | ||||
|          padding-left: 10px; | ||||
|          } | ||||
|          } | ||||
|       </style> | ||||
|       <table class="body-wrap" cellpadding="0" cellspacing="0" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; width: 100%;" bgcolor="#f6f6f6"> | ||||
|          <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|             <td valign="middle" class="aligncenter middle logo" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; padding: 20px 0 10px;" align="center"> | ||||
|                 <img src="{{url}}/bwrs_static/logo-gray.png" alt="" width="250" height="39" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; border: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; max-width: 100%;" /> | ||||
|             </td> | ||||
|          </tr> | ||||
|          <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|             <td class="container" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both !important; color: #333; display: block !important; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto; max-width: 600px !important; width: 600px;" valign="top"> | ||||
|                <table cellpadding="0" cellspacing="0" class="container-table" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both !important; color: #333; display: block !important; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto; max-width: 600px !important; width: 600px;"> | ||||
|                   <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|                      <td class="content" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; display: block; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 0; line-height: 0; margin: 0 auto; max-width: 600px; padding-bottom: 20px;" valign="top"> | ||||
|                         <table class="main" width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; margin: 0; -webkit-text-size-adjust: none; border: 1px solid #e9e9e9; border-radius: 3px;" bgcolor="white"> | ||||
|                            <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                               <td class="content-wrap" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 20px; -webkit-text-size-adjust: none;" valign="top"> | ||||
|                                  <table width="100%" cellpadding="0" cellspacing="0" style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center"> | ||||
|                                           Verify this email address for your account by clicking the link below. | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center"> | ||||
|                                           <a href="{{url}}/#/verify-email/?userId={{user_id}}&token={{token}}" | ||||
|                                              clicktracking=off target="_blank" style="color: #ffffff; text-decoration: none; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; background-color: #3c8dbc; border-color: #3c8dbc; border-style: solid; border-width: 10px 20px; margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                           Verify Email Address Now | ||||
|                                           </a> | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block last" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center"> | ||||
|                                           If you did not request to verify your account, you can safely ignore this email. | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                  </table> | ||||
|                               </td> | ||||
|                            </tr> | ||||
|                         </table> | ||||
|                         <table class="footer" cellpadding="0" cellspacing="0" width="100%" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; width: 100%;"> | ||||
|                            <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|                               <td class="aligncenter social-icons" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; padding: 15px 0 0 0;" valign="top"> | ||||
|                                  <table cellpadding="0" cellspacing="0" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto;"> | ||||
|                                     <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|                                         <td style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; padding: 0 10px;" valign="top"><a href="https://github.com/dani-garcia/bitwarden_rs" target="_blank" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; text-decoration: underline;"><img src="{{url}}/bwrs_static/mail-github.png" alt="GitHub" width="30" height="30" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; border: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; max-width: 100%;" /></a></td> | ||||
|                                     </tr> | ||||
|                                  </table> | ||||
|                               </td> | ||||
|                            </tr> | ||||
|                         </table> | ||||
|                      </td> | ||||
|                   </tr> | ||||
|                </table> | ||||
|             </td> | ||||
|          </tr> | ||||
|       </table> | ||||
|    </body> | ||||
| </html> | ||||
							
								
								
									
										8
									
								
								src/static/templates/email/welcome.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/static/templates/email/welcome.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| Welcome | ||||
| <!----------------> | ||||
| <html> | ||||
| <p> | ||||
| Thank you for creating an account at <a href="{{url}}">{{url}}</a>. You may now log in with your new account. | ||||
| </p> | ||||
| <p>If you did not request to create an account, you can safely ignore this email.</p> | ||||
| </html> | ||||
							
								
								
									
										129
									
								
								src/static/templates/email/welcome.html.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								src/static/templates/email/welcome.html.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| Welcome | ||||
| <!----------------> | ||||
| <html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|    <head> | ||||
|       <meta name="viewport" content="width=device-width" /> | ||||
|       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
|       <title>Bitwarden_rs</title> | ||||
|    </head> | ||||
|    <body style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; height: 100%; line-height: 25px; width: 100% !important;" bgcolor="#f6f6f6"> | ||||
|       <style type="text/css"> | ||||
|           body { | ||||
|          margin: 0; | ||||
|          font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | ||||
|          box-sizing: border-box; | ||||
|          font-size: 16px; | ||||
|          color: #333; | ||||
|          line-height: 25px; | ||||
|          -webkit-font-smoothing: antialiased; | ||||
|          -webkit-text-size-adjust: none; | ||||
|          } | ||||
|          body * { | ||||
|          margin: 0; | ||||
|          font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | ||||
|          box-sizing: border-box; | ||||
|          font-size: 16px; | ||||
|          color: #333; | ||||
|          line-height: 25px; | ||||
|          -webkit-font-smoothing: antialiased; | ||||
|          -webkit-text-size-adjust: none; | ||||
|          } | ||||
|          img { | ||||
|          max-width: 100%; | ||||
|          border: none; | ||||
|          } | ||||
|          body { | ||||
|          -webkit-font-smoothing: antialiased; | ||||
|          -webkit-text-size-adjust: none; | ||||
|          width: 100% !important; | ||||
|          height: 100%; | ||||
|          line-height: 25px; | ||||
|          } | ||||
|          body { | ||||
|          background-color: #f6f6f6; | ||||
|          } | ||||
|          @media only screen and (max-width: 600px) { | ||||
|          body { | ||||
|          padding: 0 !important; | ||||
|          } | ||||
|          .container { | ||||
|          padding: 0 !important; | ||||
|          width: 100% !important; | ||||
|          } | ||||
|          .container-table { | ||||
|          padding: 0 !important; | ||||
|          width: 100% !important; | ||||
|          } | ||||
|          .content { | ||||
|          padding: 0 0 10px 0 !important; | ||||
|          } | ||||
|          .content-wrap { | ||||
|          padding: 10px !important; | ||||
|          } | ||||
|          .invoice { | ||||
|          width: 100% !important; | ||||
|          } | ||||
|          .main { | ||||
|          border-right: none !important; | ||||
|          border-left: none !important; | ||||
|          border-radius: 0 !important; | ||||
|          } | ||||
|          .logo { | ||||
|          padding-top: 10px !important; | ||||
|          } | ||||
|          .footer { | ||||
|          margin-top: 10px !important; | ||||
|          } | ||||
|          .indented { | ||||
|          padding-left: 10px; | ||||
|          } | ||||
|          } | ||||
|       </style> | ||||
|       <table class="body-wrap" cellpadding="0" cellspacing="0" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; width: 100%;" bgcolor="#f6f6f6"> | ||||
|          <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|             <td valign="middle" class="aligncenter middle logo" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; padding: 20px 0 10px;" align="center"> | ||||
|                 <img src="{{url}}/bwrs_static/logo-gray.png" alt="" width="250" height="39" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; border: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; max-width: 100%;" /> | ||||
|             </td> | ||||
|          </tr> | ||||
|          <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|             <td class="container" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both !important; color: #333; display: block !important; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto; max-width: 600px !important; width: 600px;" valign="top"> | ||||
|                <table cellpadding="0" cellspacing="0" class="container-table" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both !important; color: #333; display: block !important; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto; max-width: 600px !important; width: 600px;"> | ||||
|                   <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|                      <td class="content" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; display: block; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 0; line-height: 0; margin: 0 auto; max-width: 600px; padding-bottom: 20px;" valign="top"> | ||||
|                         <table class="main" width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; margin: 0; -webkit-text-size-adjust: none; border: 1px solid #e9e9e9; border-radius: 3px;" bgcolor="white"> | ||||
|                            <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                               <td class="content-wrap" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 20px; -webkit-text-size-adjust: none;" valign="top"> | ||||
|                                  <table width="100%" cellpadding="0" cellspacing="0" style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center"> | ||||
|                                           Thank you for creating an account at <a href="{{url}}">{{url}}</a>. You may now log in with your new account. | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block last" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center"> | ||||
|                                           If you did not request to create an account, you can safely ignore this email. | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                  </table> | ||||
|                               </td> | ||||
|                            </tr> | ||||
|                         </table> | ||||
|                         <table class="footer" cellpadding="0" cellspacing="0" width="100%" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; width: 100%;"> | ||||
|                            <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|                               <td class="aligncenter social-icons" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; padding: 15px 0 0 0;" valign="top"> | ||||
|                                  <table cellpadding="0" cellspacing="0" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto;"> | ||||
|                                     <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|                                         <td style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; padding: 0 10px;" valign="top"><a href="https://github.com/dani-garcia/bitwarden_rs" target="_blank" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; text-decoration: underline;"><img src="{{url}}/bwrs_static/mail-github.png" alt="GitHub" width="30" height="30" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; border: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; max-width: 100%;" /></a></td> | ||||
|                                     </tr> | ||||
|                                  </table> | ||||
|                               </td> | ||||
|                            </tr> | ||||
|                         </table> | ||||
|                      </td> | ||||
|                   </tr> | ||||
|                </table> | ||||
|             </td> | ||||
|          </tr> | ||||
|       </table> | ||||
|    </body> | ||||
| </html> | ||||
							
								
								
									
										12
									
								
								src/static/templates/email/welcome_must_verify.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/static/templates/email/welcome_must_verify.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| Welcome | ||||
| <!----------------> | ||||
| <html> | ||||
| <p> | ||||
| Thank you for creating an account at <a href="{{url}}">{{url}}</a>. Before you can login with your new account, you must verify this email address by clicking the link below. | ||||
| <br> | ||||
| <br> | ||||
| <a href="{{url}}/#/verify-email/?userId={{user_id}}&token={{token}}"> | ||||
| Verify Email Address Now</a> | ||||
| </p> | ||||
| <p>If you did not request to create an account, you can safely ignore this email.</p> | ||||
| </html> | ||||
							
								
								
									
										137
									
								
								src/static/templates/email/welcome_must_verify.html.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								src/static/templates/email/welcome_must_verify.html.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,137 @@ | ||||
| Welcome | ||||
| <!----------------> | ||||
| <html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|    <head> | ||||
|       <meta name="viewport" content="width=device-width" /> | ||||
|       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
|       <title>Bitwarden_rs</title> | ||||
|    </head> | ||||
|    <body style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; height: 100%; line-height: 25px; width: 100% !important;" bgcolor="#f6f6f6"> | ||||
|       <style type="text/css"> | ||||
|           body { | ||||
|          margin: 0; | ||||
|          font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | ||||
|          box-sizing: border-box; | ||||
|          font-size: 16px; | ||||
|          color: #333; | ||||
|          line-height: 25px; | ||||
|          -webkit-font-smoothing: antialiased; | ||||
|          -webkit-text-size-adjust: none; | ||||
|          } | ||||
|          body * { | ||||
|          margin: 0; | ||||
|          font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | ||||
|          box-sizing: border-box; | ||||
|          font-size: 16px; | ||||
|          color: #333; | ||||
|          line-height: 25px; | ||||
|          -webkit-font-smoothing: antialiased; | ||||
|          -webkit-text-size-adjust: none; | ||||
|          } | ||||
|          img { | ||||
|          max-width: 100%; | ||||
|          border: none; | ||||
|          } | ||||
|          body { | ||||
|          -webkit-font-smoothing: antialiased; | ||||
|          -webkit-text-size-adjust: none; | ||||
|          width: 100% !important; | ||||
|          height: 100%; | ||||
|          line-height: 25px; | ||||
|          } | ||||
|          body { | ||||
|          background-color: #f6f6f6; | ||||
|          } | ||||
|          @media only screen and (max-width: 600px) { | ||||
|          body { | ||||
|          padding: 0 !important; | ||||
|          } | ||||
|          .container { | ||||
|          padding: 0 !important; | ||||
|          width: 100% !important; | ||||
|          } | ||||
|          .container-table { | ||||
|          padding: 0 !important; | ||||
|          width: 100% !important; | ||||
|          } | ||||
|          .content { | ||||
|          padding: 0 0 10px 0 !important; | ||||
|          } | ||||
|          .content-wrap { | ||||
|          padding: 10px !important; | ||||
|          } | ||||
|          .invoice { | ||||
|          width: 100% !important; | ||||
|          } | ||||
|          .main { | ||||
|          border-right: none !important; | ||||
|          border-left: none !important; | ||||
|          border-radius: 0 !important; | ||||
|          } | ||||
|          .logo { | ||||
|          padding-top: 10px !important; | ||||
|          } | ||||
|          .footer { | ||||
|          margin-top: 10px !important; | ||||
|          } | ||||
|          .indented { | ||||
|          padding-left: 10px; | ||||
|          } | ||||
|          } | ||||
|       </style> | ||||
|       <table class="body-wrap" cellpadding="0" cellspacing="0" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; width: 100%;" bgcolor="#f6f6f6"> | ||||
|          <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|             <td valign="middle" class="aligncenter middle logo" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; padding: 20px 0 10px;" align="center"> | ||||
|                 <img src="{{url}}/bwrs_static/logo-gray.png" alt="" width="250" height="39" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; border: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; max-width: 100%;" /> | ||||
|             </td> | ||||
|          </tr> | ||||
|          <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|             <td class="container" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both !important; color: #333; display: block !important; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto; max-width: 600px !important; width: 600px;" valign="top"> | ||||
|                <table cellpadding="0" cellspacing="0" class="container-table" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both !important; color: #333; display: block !important; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto; max-width: 600px !important; width: 600px;"> | ||||
|                   <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|                      <td class="content" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; display: block; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 0; line-height: 0; margin: 0 auto; max-width: 600px; padding-bottom: 20px;" valign="top"> | ||||
|                         <table class="main" width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; margin: 0; -webkit-text-size-adjust: none; border: 1px solid #e9e9e9; border-radius: 3px;" bgcolor="white"> | ||||
|                            <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                               <td class="content-wrap" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 20px; -webkit-text-size-adjust: none;" valign="top"> | ||||
|                                  <table width="100%" cellpadding="0" cellspacing="0" style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center"> | ||||
|                                           Thank you for creating an account at <a href="{{url}}">{{url}}</a>. Before you can login with your new account, you must verify this email address by clicking the link below. | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center"> | ||||
|                                           <a href="{{url}}/#/verify-email/?userId={{user_id}}&token={{token}}" | ||||
|                                              clicktracking=off target="_blank" style="color: #ffffff; text-decoration: none; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; background-color: #3c8dbc; border-color: #3c8dbc; border-style: solid; border-width: 10px 20px; margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                           Verify Email Address Now | ||||
|                                           </a> | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                     <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> | ||||
|                                        <td class="content-block last" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center"> | ||||
|                                           If you did not request to create an account, you can safely ignore this email. | ||||
|                                        </td> | ||||
|                                     </tr> | ||||
|                                  </table> | ||||
|                               </td> | ||||
|                            </tr> | ||||
|                         </table> | ||||
|                         <table class="footer" cellpadding="0" cellspacing="0" width="100%" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; width: 100%;"> | ||||
|                            <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|                               <td class="aligncenter social-icons" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; padding: 15px 0 0 0;" valign="top"> | ||||
|                                  <table cellpadding="0" cellspacing="0" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto;"> | ||||
|                                     <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> | ||||
|                                         <td style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; padding: 0 10px;" valign="top"><a href="https://github.com/dani-garcia/bitwarden_rs" target="_blank" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; text-decoration: underline;"><img src="{{url}}/bwrs_static/mail-github.png" alt="GitHub" width="30" height="30" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; border: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; max-width: 100%;" /></a></td> | ||||
|                                     </tr> | ||||
|                                  </table> | ||||
|                               </td> | ||||
|                            </tr> | ||||
|                         </table> | ||||
|                      </td> | ||||
|                   </tr> | ||||
|                </table> | ||||
|             </td> | ||||
|          </tr> | ||||
|       </table> | ||||
|    </body> | ||||
| </html> | ||||
		Reference in New Issue
	
	Block a user