Readable white-on-white mail; forwards carry the original's header

A message written in a dark-mode mail app (or pasted from a dark page) can
set all its text white with no background — invisible on the reading pane's
white page. After a message renders, text whose colour is practically the
colour behind it gets the pane's normal text colour, when a good part of the
message (30% of its text) is invisible. Text hidden on purpose — a help
desk's white ticket reference, a newsletter's hidden preview line — stays
hidden; white on dark, coloured or pictured backgrounds is left as designed
(lib/readability.ts, with tests). The check runs before the quote is folded.

A forward quoted the original under the reply's one line ("On …, Name
wrote:"), without the sender's address. It now opens with the usual block:
Forwarded message, From (name and address), Date, Subject, To, Cc.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 21:36:47 +02:00
co-authored by Claude Opus 5.5
parent 5bf8fc81f6
commit f44c7b9e7c
5 changed files with 155 additions and 3 deletions
+27 -1
View File
@@ -61,6 +61,32 @@ function attributionFor(msg: MessageEnvelope): string {
return `On ${date}, at ${time}, ${who} wrote:`;
}
/** The header block above a forwarded message, as mail programs write it:
* who sent it (name and address), when, its subject and recipients. */
function forwardHeaderFor(msg: MessageEnvelope, subject: string): string {
const d = new Date(msg.date);
const date = d.toLocaleString(getDateLocale(), {
weekday: "short",
year: "numeric",
month: "short",
day: "numeric",
hour: "numeric",
minute: "2-digit",
hour12: getHour12(),
});
const person = (a: { name: string; email: string }) =>
a.name && a.name !== a.email ? `${a.name} <${a.email}>` : a.email;
const lines = [
"---------- Forwarded message ---------",
`From: ${msg.from_addr.map(person).join(", ")}`,
`Date: ${date}`,
`Subject: ${msg.subject || subject}`,
];
if (msg.to_addr.length) lines.push(`To: ${msg.to_addr.map(person).join(", ")}`);
if (msg.cc_addr.length) lines.push(`Cc: ${msg.cc_addr.map(person).join(", ")}`);
return lines.join("\n");
}
function buildReplyInit(
subject: string,
msg: MessageEnvelope,
@@ -76,7 +102,7 @@ function buildReplyInit(
replyToMessageId: msg.id,
kind,
subject: `Fwd: ${norm}`,
quote,
quote: { attribution: forwardHeaderFor(msg, subject), messageId: msg.id },
forwardFrom: msg.id,
};
}