email: HTML templates and multipart messages
Emails now render an HTML template from templates/email with a plaintext fallback, sent as multipart/alternative. A configurable brand name shows in the template. Reset and confirmation mails share one styled base.
This commit is contained in:
parent
fbcf0eaac7
commit
06e9da4dc8
10 changed files with 139 additions and 25 deletions
56
src/email.rs
Normal file
56
src/email.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
// Email content: renders the HTML templates in ../templates/email and pairs each
|
||||
// with a plaintext fallback. The link layer sends both as multipart/alternative.
|
||||
|
||||
pub struct Mail {
|
||||
pub subject: String,
|
||||
pub text: String,
|
||||
pub html: String,
|
||||
}
|
||||
|
||||
const BASE: &str = include_str!("../templates/email/base.html");
|
||||
|
||||
fn render(brand: &str, title: &str, message: &str, code: &str, note: &str) -> String {
|
||||
BASE.replace("{{brand}}", &escape(brand))
|
||||
.replace("{{title}}", &escape(title))
|
||||
.replace("{{message}}", &escape(message))
|
||||
.replace("{{code}}", &escape(code))
|
||||
.replace("{{note}}", &escape(note))
|
||||
}
|
||||
|
||||
pub fn reset(brand: &str, account: &str, code: &str) -> Mail {
|
||||
Mail {
|
||||
subject: format!("Password reset for {account}"),
|
||||
text: format!(
|
||||
"Your password reset code for {account} is: {code}\nIt expires in 15 minutes.\nReset with:\n /msg NickServ RESETPASS {account} {code} <newpassword>\n"
|
||||
),
|
||||
html: render(
|
||||
brand,
|
||||
"Password reset",
|
||||
&format!("Use this code to reset the password for your account {account}."),
|
||||
code,
|
||||
"This code expires in 15 minutes.",
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn confirm(brand: &str, account: &str, code: &str) -> Mail {
|
||||
Mail {
|
||||
subject: format!("Confirm your {account} registration"),
|
||||
text: format!(
|
||||
"Confirm your account {account} with:\n /msg NickServ CONFIRM {code}\nThe code expires in 15 minutes.\n"
|
||||
),
|
||||
html: render(
|
||||
brand,
|
||||
"Confirm your account",
|
||||
&format!("Welcome! Confirm the email for your account {account} with the code below."),
|
||||
code,
|
||||
"This code expires in 15 minutes.",
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// Escape the few characters that matter inside HTML text so a value can't break
|
||||
// out of the template.
|
||||
fn escape(s: &str) -> String {
|
||||
s.replace('&', "&").replace('<', "<").replace('>', ">")
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue