Skip to content

Commit 2f8600a

Browse files
committed
emails: Implement template inheritance system for consistent branding
1 parent 18f5c83 commit 2f8600a

File tree

40 files changed

+289
-15
lines changed

40 files changed

+289
-15
lines changed

src/controllers/krate/snapshots/crates_io__controllers__krate__delete__tests__happy_path_new_crate-3.snap

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,15 @@ Subject: crates.io: Successfully published foo@1.0.0
88
Content-Type: text/plain; charset=utf-8
99
Content-Transfer-Encoding: quoted-printable
1010

11+
1112
Hello foo!
1213

1314
A new version of the package foo (1.0.0) was published by your account (https://crates.io/users/foo) at [0000-00-00T00:00:00Z].
1415

1516
If you have questions or security concerns, you can contact us at help@crates.io. If you would like to stop receiving these security notifications, you can disable them in your account settings.
17+
18+
--
19+
The crates.io Team
1620
----------------------------------------
1721

1822
To: foo@example.com
@@ -21,8 +25,12 @@ Subject: crates.io: Deleted "foo" crate
2125
Content-Type: text/plain; charset=utf-8
2226
Content-Transfer-Encoding: quoted-printable
2327

28+
2429
Hi foo,
2530

2631
Your "foo" crate has been deleted, per your request.
2732

2833
If you did not initiate this deletion, your account may have been compromised. Please contact us at help@crates.io.
34+
35+
--
36+
The crates.io Team

src/controllers/krate/snapshots/crates_io__controllers__krate__delete__tests__happy_path_old_crate-3.snap

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,15 @@ Subject: crates.io: Successfully published foo@1.0.0
88
Content-Type: text/plain; charset=utf-8
99
Content-Transfer-Encoding: quoted-printable
1010

11+
1112
Hello foo!
1213

1314
A new version of the package foo (1.0.0) was published by your account (https://crates.io/users/foo) at [0000-00-00T00:00:00Z].
1415

1516
If you have questions or security concerns, you can contact us at help@crates.io. If you would like to stop receiving these security notifications, you can disable them in your account settings.
17+
18+
--
19+
The crates.io Team
1620
----------------------------------------
1721

1822
To: foo@example.com
@@ -21,8 +25,12 @@ Subject: crates.io: Deleted "foo" crate
2125
Content-Type: text/plain; charset=utf-8
2226
Content-Transfer-Encoding: quoted-printable
2327

28+
2429
Hi foo,
2530

2631
Your "foo" crate has been deleted, per your request.
2732

2833
If you did not initiate this deletion, your account may have been compromised. Please contact us at help@crates.io.
34+
35+
--
36+
The crates.io Team

src/controllers/krate/snapshots/crates_io__controllers__krate__delete__tests__happy_path_really_old_crate-3.snap

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,15 @@ Subject: crates.io: Successfully published foo@1.0.0
88
Content-Type: text/plain; charset=utf-8
99
Content-Transfer-Encoding: quoted-printable
1010

11+
1112
Hello foo!
1213

1314
A new version of the package foo (1.0.0) was published by your account (https://crates.io/users/foo) at [0000-00-00T00:00:00Z].
1415

1516
If you have questions or security concerns, you can contact us at help@crates.io. If you would like to stop receiving these security notifications, you can disable them in your account settings.
17+
18+
--
19+
The crates.io Team
1620
----------------------------------------
1721

1822
To: foo@example.com
@@ -21,8 +25,12 @@ Subject: crates.io: Deleted "foo" crate
2125
Content-Type: text/plain; charset=utf-8
2226
Content-Transfer-Encoding: quoted-printable
2327

28+
2429
Hi foo,
2530

2631
Your "foo" crate has been deleted, per your request.
2732

2833
If you did not initiate this deletion, your account may have been compromised. Please contact us at help@crates.io.
34+
35+
--
36+
The crates.io Team

src/controllers/trustpub/github_configs/create/snapshots/crates_io__controllers__trustpub__github_configs__create__tests__happy_path-3.snap

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Subject: crates.io: Trusted Publishing configuration added to foo
88
Content-Type: text/plain; charset=utf-8
99
Content-Transfer-Encoding: quoted-printable
1010

11+
1112
Hello foo!
1213

1314
crates.io user foo added a new "Trusted Publishing" configuration for GitHub Actions to a crate that you manage ("foo"). Trusted publishers act as trusted users and can publish new versions of the crate automatically.
@@ -22,3 +23,6 @@ Trusted Publishing configuration:
2223
If you did not make this change and you think it was made maliciously, you can remove the configuration from the crate via the "Settings" tab on the crate's page.
2324

2425
If you are unable to revert the change and need to do so, you can email help@crates.io for assistance.
26+
27+
--
28+
The crates.io Team

src/controllers/trustpub/github_configs/delete/snapshots/crates_io__controllers__trustpub__github_configs__delete__tests__happy_path-2.snap

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Subject: crates.io: Trusted Publishing configuration removed from foo
88
Content-Type: text/plain; charset=utf-8
99
Content-Transfer-Encoding: quoted-printable
1010

11+
1112
Hello foo!
1213

1314
crates.io user foo removed a "Trusted Publishing" configuration for GitHub Actions from a crate that you manage ("foo").
@@ -20,3 +21,6 @@ Trusted Publishing configuration:
2021
- Environment: (not set)
2122

2223
If you did not make this change and you think it was made maliciously, you can email help@crates.io for assistance.
24+
25+
--
26+
The crates.io Team

src/controllers/user/snapshots/crates_io__controllers__user__email_verification__tests__happy_path-3.snap

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ Subject: crates.io: Please confirm your email address
88
Content-Type: text/plain; charset=utf-8
99
Content-Transfer-Encoding: quoted-printable
1010

11+
1112
Hello foo!
1213

1314
Welcome to crates.io. Please click the link below to verify your email address:
1415

1516
https://crates.io/confirm/[confirm-token]
1617

1718
Thank you!
19+
20+
--
21+
The crates.io Team

src/email.rs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,40 @@ use std::sync::LazyLock;
1616
static EMAIL_ENV: LazyLock<Environment<'static>> = LazyLock::new(|| {
1717
let mut env = Environment::new();
1818

19-
// Load templates from each email directory
19+
// Load templates from the templates directory
2020
let entries = std::fs::read_dir("src/email/templates");
2121
let entries = entries.expect("Failed to read email templates directory");
2222

2323
for entry in entries {
2424
let entry = entry.expect("Failed to read directory entry");
2525

26+
let path = entry.path();
2627
let file_type = entry.file_type().expect("Failed to get file type");
28+
29+
// Handle base template files
30+
if file_type.is_file() && path.extension().and_then(|s| s.to_str()) == Some("j2") {
31+
let template_name = entry.file_name();
32+
let template_name = template_name.to_str();
33+
let template_name = template_name.expect("Invalid UTF-8 in template filename");
34+
35+
let template_contents = std::fs::read_to_string(&path)
36+
.unwrap_or_else(|error| panic!("Failed to read template {template_name}: {error}"));
37+
38+
env.add_template_owned(template_name.to_string(), template_contents)
39+
.expect("Failed to add template");
40+
}
41+
2742
if !file_type.is_dir() {
2843
continue;
2944
}
3045

46+
// Handle email template directories
3147
let dir_name = entry.file_name();
3248
let email_name = dir_name.to_str();
3349
let email_name = email_name.expect("Invalid UTF-8 in email template directory name");
3450

3551
// Load subject.txt.j2 file
36-
let subject_path = entry.path().join("subject.txt.j2");
52+
let subject_path = path.join("subject.txt.j2");
3753
let subject_contents = std::fs::read_to_string(&subject_path).unwrap_or_else(|error| {
3854
panic!("Failed to read subject template for {email_name}: {error}")
3955
});
@@ -42,7 +58,7 @@ static EMAIL_ENV: LazyLock<Environment<'static>> = LazyLock::new(|| {
4258
.expect("Failed to add subject template");
4359

4460
// Load body.txt.j2 file
45-
let body_path = entry.path().join("body.txt.j2");
61+
let body_path = path.join("body.txt.j2");
4662
let body_contents = std::fs::read_to_string(&body_path).unwrap_or_else(|error| {
4763
panic!("Failed to read body template for {email_name}: {error}")
4864
});
@@ -234,6 +250,35 @@ pub struct StoredEmail {
234250
mod tests {
235251
use super::*;
236252
use claims::{assert_err, assert_ok};
253+
use minijinja::context;
254+
255+
#[test]
256+
fn test_user_confirm_template_inheritance() {
257+
// Test that the `user_confirm` template inherits properly from the base template
258+
let result = render_template(
259+
"user_confirm/body.txt.j2",
260+
context! {
261+
domain => "crates.io",
262+
user_name => "testuser",
263+
token => "abc123"
264+
},
265+
);
266+
assert_ok!(&result);
267+
268+
let content = result.unwrap();
269+
insta::assert_snapshot!(content, @r"
270+
Hello testuser!
271+
272+
Welcome to crates.io. Please click the link below to verify your email address:
273+
274+
https://crates.io/confirm/abc123
275+
276+
Thank you!
277+
278+
--
279+
The crates.io Team
280+
");
281+
}
237282

238283
#[tokio::test]
239284
async fn sending_to_invalid_email_fails() {

src/email/templates/admin_account/body.txt.j2

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
{% extends "base.txt.j2" %}
2+
3+
{% block content %}
14
{% if added_admins -%}
25
Granted admin access:
36

@@ -10,4 +13,5 @@ Revoked admin access:
1013
{% for admin in removed_admins -%}
1114
- {{ admin }}
1215
{% endfor -%}
13-
{% endif %}
16+
{% endif %}
17+
{% endblock %}

src/email/templates/base.txt.j2

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{% block content %}{% endblock %}
2+
--
3+
The crates.io Team

src/email/templates/config_created/body.txt.j2

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
{% extends "base.txt.j2" %}
2+
3+
{% block content %}
14
Hello {{ recipient }}!
25

36
crates.io user {{ user }} added a new "Trusted Publishing" configuration for GitHub Actions to a crate that you manage ("{{ krate }}"). Trusted publishers act as trusted users and can publish new versions of the crate automatically.
@@ -12,3 +15,4 @@ Trusted Publishing configuration:
1215
If you did not make this change and you think it was made maliciously, you can remove the configuration from the crate via the "Settings" tab on the crate's page.
1316

1417
If you are unable to revert the change and need to do so, you can email help@crates.io for assistance.
18+
{% endblock %}

0 commit comments

Comments
 (0)