Skip to content

Commit 1e992ba

Browse files
committed
feat: [#802] new functions to send reset password to user
1 parent ecb15e6 commit 1e992ba

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

src/mailer.rs

+67
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,29 @@ impl Service {
151151

152152
format!("{base_url}/{API_VERSION_URL_PREFIX}/user/email/verify/{token}")
153153
}
154+
155+
/// Send reset password email.
156+
///
157+
/// # Errors
158+
///
159+
/// This function will return an error if unable to send an email.
160+
///
161+
/// # Panics
162+
///
163+
/// This function will panic if the multipart builder had an error.
164+
pub async fn send_reset_password_mail(&self, to: &str, username: &str, password: &str) -> Result<(), ServiceError> {
165+
let builder = self.get_builder(to).await;
166+
167+
let mail = build_letter(&password, username, builder)?;
168+
169+
match self.mailer.send(mail).await {
170+
Ok(_res) => Ok(()),
171+
Err(e) => {
172+
eprintln!("Failed to send email: {e}");
173+
Err(ServiceError::FailedToSendVerificationEmail)
174+
}
175+
}
176+
}
154177
}
155178

156179
fn build_letter(verification_url: &str, username: &str, builder: MessageBuilder) -> Result<Message, ServiceError> {
@@ -195,6 +218,50 @@ fn build_content(verification_url: &str, username: &str) -> Result<(String, Stri
195218
Ok((plain_body, html_body))
196219
}
197220

221+
fn build_reset_password_letter(password: &str, username: &str, builder: MessageBuilder) -> Result<Message, ServiceError> {
222+
let (plain_body, html_body) = build_reset_password_content(password, username).map_err(|e| {
223+
tracing::error!("{e}");
224+
ServiceError::InternalServerError
225+
})?;
226+
227+
Ok(builder
228+
.subject("Torrust - Password reset")
229+
.multipart(
230+
MultiPart::alternative()
231+
.singlepart(
232+
SinglePart::builder()
233+
.header(lettre::message::header::ContentType::TEXT_PLAIN)
234+
.body(plain_body),
235+
)
236+
.singlepart(
237+
SinglePart::builder()
238+
.header(lettre::message::header::ContentType::TEXT_HTML)
239+
.body(html_body),
240+
),
241+
)
242+
.expect("the `multipart` builder had an error"))
243+
}
244+
245+
fn build_reset_password_content(password: &str, username: &str) -> Result<(String, String), tera::Error> {
246+
let plain_body = format!(
247+
"
248+
Hello, {username}!
249+
250+
Your password has been reset.
251+
252+
Find below your new password:
253+
{password}
254+
255+
We recommend replacing it as soon as possible with a new and strong password of your own.
256+
"
257+
);
258+
let mut context = Context::new();
259+
context.insert("password", &password);
260+
context.insert("username", &username);
261+
let html_body = TEMPLATES.render("html_reset_password", &context)?;
262+
Ok((plain_body, html_body))
263+
}
264+
198265
pub type Mailer = AsyncSmtpTransport<Tokio1Executor>;
199266

200267
#[cfg(test)]

0 commit comments

Comments
 (0)