Skip to content

feat(signature): add HTML signature support#10876

Open
joshua-grimmett wants to merge 1 commit intothunderbird:mainfrom
joshua-grimmett:feat/8841/html-signature
Open

feat(signature): add HTML signature support#10876
joshua-grimmett wants to merge 1 commit intothunderbird:mainfrom
joshua-grimmett:feat/8841/html-signature

Conversation

@joshua-grimmett
Copy link
Copy Markdown

Summary

Adds a per-identity "Format signature as HTML" toggle so users can write rich-text signatures and have them sent as HTML in outgoing mail. Refs #8841.

When the flag is on, the signature is embedded verbatim in outgoing HTML messages (no text-to-HTML conversion), converted via Jsoup for outgoing plain-text messages, and rendered as a live WebView preview in the compose screen so drafts and new composes show the rendered result instead of raw tags.

Scope (vs #8841)

In scope ✅

  • Users can input signatures as HTML tags
  • HTML signatures sent with outgoing email

Stretch (not in this PR)

  • Import HTML from file — can follow up in a separate PR if desired

Out of scope per #8841

  • Full visual / WYSIWYG editor
  • Attaching vCards as signatures

Changes

  • Data model: Identity.signatureIsHtml: Boolean added, persisted via LegacyAccountStorageHandler under key signatureIsHtml.$ident. IdentitySettingsDescriptions registers the new setting at version 111.
  • UI: "Format signature as HTML" checkbox added to both the Edit Identity screen and the Composition defaults screen, with a summary line explaining the sanitisation behaviour.
  • Outgoing mail: TextBodyBuilder.getSignatureHtml() short-circuits HtmlConverter.textToHtmlFragment() when the flag is set. For plain-text messages, TextBodyBuilder.getSignature() runs the HTML signature through HtmlConverter.htmlToText() to produce a plain-text fallback.
  • Sanitisation: HtmlSignatureSanitizer wraps Jsoup.clean() with a Safelist.relaxed() baseline that strips <script>, event handler attributes, javascript: URLs, <iframe>, <object>, and <embed> elements.
  • Compose preview: MessageCompose renders the HTML signature in a MessageWebView (reusing the component already used for quoted HTML) instead of showing raw tags in the plain EditText. Remote images and natural device-size rendering are enabled since the signature is the user's own content.
  • Draft reload: When an existing draft is reopened, account.findIdentity(email) looks up the matching account identity and inherits its signatureIsHtml value, preserving the flag across drafts for multi-identity accounts.

Tests

  • New HtmlSignatureSanitizerTest — 10 cases covering sanitisation (preserves basic formatting, strips scripts/event handlers / javascript: URLs / iframes, passes plain text unchanged).
  • New TextBodyBuilderHtmlSignatureTest — 4 cases covering the HTML short-circuit in both the HTML and plain-text body paths.
  • Existing TextBodyBuilderTest, MessageBuilderTest, ReplyToPresenterTest, IdentityHeaderBuilderTest updated for the new Identity field and continue to pass.
  • ./gradlew spotlessCheck detekt pass locally.

Screenshots

Edit Identity screen — new HTML checkbox:

pr-edit-identity

Compose screen — rendered HTML signature preview:

pr-compose

Test plan

  • Set HTML signature in Edit Identity → compose new message → recipient sees rendered HTML
  • Save message as draft → reopen draft → signature renders correctly
  • Multi-identity: drafts preserve per-identity HTML flag correctly
  • Sanitiser strips <script> / onclick / javascript: URLs
  • Unchecking HTML flag → compose falls back to plain-text signature EditText
  • Sending plain-text message with HTML signature produces a text/plain fallback via HtmlConverter.htmlToText()

Add a per-identity "Format signature as HTML" toggle so users can set
rich-text signatures and have them sent as HTML in outgoing mail,
addressing issue thunderbird#8841.

- Identity.signatureIsHtml persisted alongside the existing signature
  fields; LegacyAccountStorageHandler reads/writes/deletes the new key;
  IdentitySettingsDescriptions bumps to settings version 111.
- Edit Identity and Account Composition defaults screens gain a
  "Format signature as HTML" checkbox.
- TextBodyBuilder short-circuits HtmlConverter.textToHtmlFragment when
  the flag is set, and runs the signature through HtmlConverter.htmlToText
  for the plain-text message path.
- HtmlSignatureSanitizer sanitizes user HTML via a Jsoup Safelist.relaxed
  baseline, stripping scripts, event handlers, and javascript: URLs.
- MessageCompose renders the HTML signature in a MessageWebView preview
  instead of raw text, so drafts and new composes show the rendered
  result. Remote images and natural device-size rendering are enabled
  for the user's own signature content.
- Draft reload looks up the matching identity by email via
  account.findIdentity() to preserve signatureIsHtml for multi-identity
  accounts, since the X-K9mail-Identity header does not encode the flag.
- Tests: HtmlSignatureSanitizerTest (10 cases) and
  TextBodyBuilderHtmlSignatureTest (4 cases).
@github-actions
Copy link
Copy Markdown
Contributor

Missing report label. Set exactly one of: report: include, report: exclude OR report: highlight.

@Alecaddd Alecaddd added the report: highlight Highlight changes (major feature, breaking, or noticeable to users) in user-facing reports. label Apr 16, 2026
@ryanleesipes
Copy link
Copy Markdown
Contributor

Thank you for this @joshua-grimmett - very cool stuff.

@jbott-tbird
Copy link
Copy Markdown
Collaborator

hey @joshua-grimmett, we haven't forgotten about this and appreciate you doing this (especially since it's one of our main roadmap items this year). @rafaeltonholo was put on some last minute changes for our Thundermail project, but will be back on this in the next week or so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

report: highlight Highlight changes (major feature, breaking, or noticeable to users) in user-facing reports.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants