PostHog / PostHog/posthog

Support: markdown escaping leaks into the text/plain part of outbound email replies

Open
#94,702 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
39.9k
Forks
3.4k
Avg merge
6h 51m
Merged PRs (30d)
232

Description

Outbound email replies from the Support inbox are sent as multipart/alternative. The text/html part renders correctly, but the text/plain part contains markdown escape sequences as literal backslashes.

In products/conversations/backend/tasks.py, the outbound body is built as:

if comment.rich_content:
    html_body = rich_content_to_html(comment.rich_content)
    txt_body = rich_content_to_markdown(comment.rich_content, include_images=False)

text/plain isn't markdown, so escapes intended for a markdown renderer are delivered verbatim. Captured from a live reply — the two parts of the same message:

Content-Type: text/plain; charset="utf-8"

ok\. tell me more

Content-Type: text/html; charset="utf-8"

<p>ok. tell me more</p>

Note the ok\. in the plain-text alternative.

Impact. Anyone reading the text/plain part sees the backslashes: plain-text mail clients, assistive tech falling back to that part, and anything downstream parsing it. Agents typing ordinary prose in the rich editor hit this on every reply — it isn't specific to short messages, and it's invisible to the agent because the composer and the HTML part both look right.

We observed it on a period and haven't characterised which other characters the serializer escapes.

Suggested fix. Generate the text/plain alternative with a plain-text serializer (or unescape after serializing), and keep markdown output for the paths where a markdown renderer actually consumes it.

Debug info

PostHog Cloud (US) · Support email channel, Mailgun transport · observed 2026-09-03

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in products/conversations/backend/tasks.py at the rich_content branch, then trace rich_content_to_markdown and the corresponding HTML serializer. Verify how the multipart email body is assembled and which serializer is intended for plain text. Done means the text/plain part contains no markdown escape sequences while the text/html part remains unchanged; cover the observed period case and any other escaping behavior identified.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.