Is your feature request related to a problem? Please describe.
Meeting invites that arrive as a bare text/calendar part — most commonly an Outlook "forward meeting", which ships no text/html or text/plain alternative — render as raw VCALENDAR source in the message pane. The user sees pages of BEGIN:VEVENT, folded ICS lines, and escaped \n\, text instead of the meeting details, with the Teams/Zoom join link buried in the noise. Cause: walkStructure only collects html/plain parts, so a calendar-only message falls through to the single-part fallback, which serves the raw part as plain text.
Describe the solution you'd like
When a message has no ordinary body but does have a text/calendar part, render a readable invite instead:
- A summary card: method label (invitation / cancellation / response), SUMMARY, When (formatted DTSTART–DTEND with the TZID label preserved, UTC flagged), Where, and Organizer.
- The event description below it — preferring Outlook's
X-ALT-DESC;FMTTYPE=text/html form when present (it carries the full HTML with working join links), falling back to the plain DESCRIPTION with RFC 5545 unfolding/unescaping applied and line breaks preserved.
The generated HTML flows through the existing email sanitizer path like any message body. Multipart invites that already have an html/plain alternative are untouched, and this is display-only — no RSVP actions, no new dependencies (the ICS parsing needed is ~100 lines: line unfolding, TEXT unescaping, first-VEVENT property extraction).
Describe alternatives you've considered
- Treating the calendar part as a downloadable .ics attachment: preserves the data but still shows an empty/raw body, and most users just want to read what/when/where.
- A full calendar/RSVP feature (accept/decline via METHOD:REPLY): far larger scope; the render-only card doesn't preclude it later.
- Pulling in an ical parsing library: overkill for read-only display of one VEVENT, and adds a dependency to the ingest path.
Additional context
Implemented and running in production on my instance, with unit tests built from a real-world Outlook forward (folded lines with tab continuations, quoted TZIDs containing spaces, escaped commas/newlines, X-ALT-DESC). Happy to submit the PR if this direction works for you. Same contributor as #394–398 / #410 / #411 / #414.
🤖 Generated with Claude Code
Is your feature request related to a problem? Please describe.
Meeting invites that arrive as a bare
text/calendarpart — most commonly an Outlook "forward meeting", which ships notext/htmlortext/plainalternative — render as raw VCALENDAR source in the message pane. The user sees pages ofBEGIN:VEVENT, folded ICS lines, and escaped\n\,text instead of the meeting details, with the Teams/Zoom join link buried in the noise. Cause:walkStructureonly collects html/plain parts, so a calendar-only message falls through to the single-part fallback, which serves the raw part as plain text.Describe the solution you'd like
When a message has no ordinary body but does have a
text/calendarpart, render a readable invite instead:X-ALT-DESC;FMTTYPE=text/htmlform when present (it carries the full HTML with working join links), falling back to the plain DESCRIPTION with RFC 5545 unfolding/unescaping applied and line breaks preserved.The generated HTML flows through the existing email sanitizer path like any message body. Multipart invites that already have an html/plain alternative are untouched, and this is display-only — no RSVP actions, no new dependencies (the ICS parsing needed is ~100 lines: line unfolding, TEXT unescaping, first-VEVENT property extraction).
Describe alternatives you've considered
Additional context
Implemented and running in production on my instance, with unit tests built from a real-world Outlook forward (folded lines with tab continuations, quoted TZIDs containing spaces, escaped commas/newlines, X-ALT-DESC). Happy to submit the PR if this direction works for you. Same contributor as #394–398 / #410 / #411 / #414.
🤖 Generated with Claude Code