mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 00:12:39 +00:00
36 lines
1.6 KiB
TypeScript
36 lines
1.6 KiB
TypeScript
import { Email } from '@/lib/jmap/types';
|
|
import { hasMeaningfulHtmlBody } from '@/lib/signature-utils';
|
|
|
|
/**
|
|
* Pick the HTML body an email should be rendered from, or null when it should be
|
|
* rendered as plain text instead. Shared by the desktop viewer and the mobile
|
|
* thread view so the two cannot drift apart again (#489: the thread view was
|
|
* missing the part-type guard and rendered plain-text-only mail as HTML,
|
|
* collapsing every line break).
|
|
*/
|
|
export function getRenderableHtmlBody(
|
|
email: Pick<Email, 'htmlBody' | 'textBody' | 'bodyValues'>
|
|
): string | null {
|
|
const htmlPart = email.htmlBody?.[0];
|
|
if (!htmlPart?.partId || !email.bodyValues?.[htmlPart.partId]) return null;
|
|
|
|
const htmlContent = email.bodyValues[htmlPart.partId].value;
|
|
if (!htmlContent) return null;
|
|
|
|
// Per RFC 8621, a single-part email exposes the same part in both htmlBody and
|
|
// textBody. That shared part may actually be text/plain (plain-text-only mail);
|
|
// rendering it as HTML collapses newlines and skips linkification, so route by
|
|
// the part's media type rather than by which list it appears in.
|
|
if (htmlPart.type && htmlPart.type.toLowerCase() !== 'text/html') return null;
|
|
|
|
// Prefer textBody when the HTML is an auto-generated minimal wrapper (no rich
|
|
// formatting). Server-generated HTML from text/plain emails often lacks <br>
|
|
// tags, which would collapse newlines just the same.
|
|
const textPartId = email.textBody?.[0]?.partId;
|
|
const hasDistinctTextBody =
|
|
!!textPartId && textPartId !== htmlPart.partId && !!email.bodyValues[textPartId];
|
|
if (hasDistinctTextBody && !hasMeaningfulHtmlBody(htmlContent)) return null;
|
|
|
|
return htmlContent;
|
|
}
|