Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/email.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ fn take_firstname_lastname_pair(attrs: &mut Vec<(String, String)>) -> Option<Str
/// HTML-only-plus-remote-image spam signal flagged in postguard#197.
const LOGO_PNG: &[u8] = include_bytes!("../templates/email/pg_logo.png");

/// Inline checkmark glyph used inside the signer-verified circle in the
/// HTML email, referenced via `cid:pg-check`. Replaces the previous
/// unicode `&#10003;` so the mark renders consistently across clients.
const CHECK_PNG: &[u8] = include_bytes!("../templates/email/check.png");

use serde::{Deserialize, Serialize};
use url::Url;

Expand Down Expand Up @@ -207,10 +212,13 @@ struct EmailTextTemplate<'a> {
fn build_body(html: String, text: String) -> Result<MultiPart, Box<dyn std::error::Error>> {
let logo = Attachment::new_inline("pg-logo".to_string())
.body(LOGO_PNG.to_vec(), "image/png".parse::<ContentType>()?);
let check = Attachment::new_inline("pg-check".to_string())
.body(CHECK_PNG.to_vec(), "image/png".parse::<ContentType>()?);

let related = MultiPart::related()
.singlepart(SinglePart::html(html))
.singlepart(logo);
.singlepart(logo)
.singlepart(check);

Ok(MultiPart::alternative()
.singlepart(SinglePart::plain(text))
Expand Down
Binary file added templates/email/check.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion templates/email/email.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@
{% if sender_email != "" %}
<div style="margin-top:40px;padding-top:30px;border-top:1px solid #C6E2F6;text-align:center;">
<div style="margin-bottom:12px;">
<span style="display:inline-block;width:32px;height:32px;line-height:32px;border-radius:50%;border:2px solid #5F7381;text-align:center;font-size:16px;color:#5F7381;box-sizing:border-box;">&#10003;</span>
<span style="display:inline-block;width:32px;height:32px;line-height:32px;border-radius:50%;border:2px solid #5F7381;text-align:center;box-sizing:border-box;">
<img src="cid:pg-check" alt="" width="16" height="13" style="display:inline-block;vertical-align:middle;" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Code review] [Rule: wcag-aa-compliance] alt="" makes the checkmark decorative; the previous &#10003; was announced as "check mark" by some screen readers. Consider alt="verified" to preserve the signer-verified signal. Defensible as-is since the surrounding copy carries the meaning.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Code review] Source PNG is 128×107 (~1.196) but rendered at 16×13 (~1.231) — minor horizontal stretch. Either render at 16×14 or crop the source. Sub-pixel at display size, likely imperceptible.

</span>
</div>
<p style="font-size:13px;color:#5F7381;margin:0 0 6px 0;">{{files_from}}</p>
<p style="font-size:15px;font-weight:700;color:#030E17;margin:0 0 12px 0;">{{sender_email}}</p>
Expand Down