···133133 return s
134134}
135135136136-// ReactionBody builds the plain text body for an emoji reaction.
137137-// Returns markdown format (for HTML rendering) and plain text format (for text/plain part).
138138-// Markdown version includes syntax for italics and links.
139139-// Plain text version is clean without markdown symbols.
140140-func ReactionBody(emoji, fromName, originalFrom, originalBody string) (markdown, plainText string) {
136136+// ReactionBody builds the markdown body for an emoji reaction.
137137+// Returns markdown that will be used for both text/plain and text/html parts (same as regular replies).
138138+// Includes the quoted original message using the same quoting logic as regular replies.
139139+func ReactionBody(emoji, fromName, originalFrom, originalBody string) string {
141140 quoted := buildQuotedReply(originalFrom, originalBody)
142142-143143- // Markdown version (will be rendered to HTML)
144144- markdown = fmt.Sprintf("%s\n\n_%s reacted via [neomd](https://neomd.ssp.sh)_\n\n%s", emoji, fromName, quoted)
145145-146146- // Plain text version (no markdown syntax)
147147- plainQuoted := fmt.Sprintf("---\n\n%s wrote:\n\n%s\n\n---\n\n", originalFrom, quoteLines(originalBody))
148148- plainText = fmt.Sprintf("%s\n\n%s reacted via neomd (https://neomd.ssp.sh)\n\n%s", emoji, fromName, plainQuoted)
149149-150150- return markdown, plainText
141141+ return fmt.Sprintf("%s\n\n_%s reacted via [neomd](https://neomd.ssp.sh)_\n\n%s", emoji, fromName, quoted)
151142}
152143153144// ParseHeaders scans raw editor content for # [neomd: key: value] lines and
+4-5
internal/smtp/sender.go
···292292293293// BuildReactionMessage constructs a minimal reaction email with threading headers.
294294// Used for emoji reactions sent as replies to emails.
295295-// plainTextBody contains the reaction for plain text email clients (no markdown syntax).
296296-// markdownBody contains the reaction text with markdown syntax for HTML rendering.
295295+// markdownBody is used for both text/plain and text/html parts (same as BuildMessageWithThreading).
297296// inReplyTo is the Message-ID of the original email.
298297// references is the References chain from the original email (may be empty).
299299-func BuildReactionMessage(from, to, cc, subject, plainTextBody, markdownBody, inReplyTo, references string) ([]byte, error) {
298298+func BuildReactionMessage(from, to, cc, subject, markdownBody, inReplyTo, references string) ([]byte, error) {
300299 // Convert markdown to HTML (same as regular replies)
301300 htmlBody, err := render.ToHTML(markdownBody)
302301 if err != nil {
···313312 }
314313 }
315314 // No attachments for reactions
316316- // Use plainTextBody for text/plain part (no markdown syntax), htmlBody for text/html part
317317- return buildMessageWithBCC(from, to, cc, "", subject, plainTextBody, htmlBody, nil, inReplyTo, refChain)
315315+ // Use markdown for text/plain part, rendered HTML for text/html part (same as regular replies)
316316+ return buildMessageWithBCC(from, to, cc, "", subject, markdownBody, htmlBody, nil, inReplyTo, refChain)
318317}
319318320319// inlineImage holds a local image path and its assigned Content-ID.
+6-8
internal/smtp/sender_test.go
···687687 }
688688}
689689func TestBuildReactionMessage_ThreadingHeaders(t *testing.T) {
690690- plainText := "👍\n\nSimon reacted via neomd (https://neomd.ssp.sh)\n\n---\n\nJohn wrote:\n\n> Hello"
691690 markdown := "👍\n\n_Simon reacted via [neomd](https://neomd.ssp.sh)_\n\n---\n\n> **John** wrote:\n>\n> Hello"
692691 inReplyTo := "<original@example.com>"
693692 references := "<first@example.com> <second@example.com>"
···697696 "john@example.com",
698697 "",
699698 "Re: Test",
700700- plainText,
701699 markdown,
702700 inReplyTo,
703701 references,
···750748 if strings.Contains(ct, "text/plain") {
751749 foundPlainText = true
752750 bodyStr := string(body)
753753- // Plain text should not have markdown syntax
754754- if strings.Contains(bodyStr, "_") || strings.Contains(bodyStr, "[neomd]") {
755755- t.Errorf("text/plain part contains markdown syntax: %s", bodyStr)
751751+ // Plain text contains markdown syntax (same as regular replies)
752752+ if !strings.Contains(bodyStr, "_Simon reacted via [neomd]") {
753753+ t.Errorf("text/plain missing markdown footer, got: %s", bodyStr)
756754 }
757757- // Should contain plain text version
758758- if !strings.Contains(bodyStr, "Simon reacted via neomd") {
759759- t.Errorf("text/plain missing footer, got: %s", bodyStr)
755755+ // Should contain quoted reply
756756+ if !strings.Contains(bodyStr, "> **John** wrote:") {
757757+ t.Errorf("text/plain missing quoted reply, got: %s", bodyStr)
760758 }
761759 }
762760 if strings.Contains(ct, "text/html") {
+6-6
internal/ui/model.go
···809809 fromName = extractEmailAddr(from)
810810 }
811811812812- // Build reaction bodies: markdown (for HTML rendering) and plain text (for text/plain part)
813813- bodyMarkdown, bodyPlainText := editor.ReactionBody(emoji.emoji, fromName, e.From, m.openBody)
812812+ // Build reaction body in markdown (used for both text/plain and text/html parts, same as regular replies)
813813+ bodyMarkdown := editor.ReactionBody(emoji.emoji, fromName, e.From, m.openBody)
814814815815 // Get SMTP account
816816 smtpAcct := m.activeAccount()
···833833834834 return m, tea.Batch(
835835 m.spinner.Tick,
836836- m.sendReactionCmd(smtpAcct, from, to, subject, bodyMarkdown, bodyPlainText, e),
836836+ m.sendReactionCmd(smtpAcct, from, to, subject, bodyMarkdown, e),
837837 )
838838}
839839840840-func (m Model) sendReactionCmd(smtpAcct config.AccountConfig, from, to, subject, bodyMarkdown, bodyPlainText string, originalEmail *imap.Email) tea.Cmd {
840840+func (m Model) sendReactionCmd(smtpAcct config.AccountConfig, from, to, subject, bodyMarkdown string, originalEmail *imap.Email) tea.Cmd {
841841 h, p := splitAddr(smtpAcct.SMTP)
842842 cfg := smtp.Config{
843843 Host: h,
···861861 }
862862863863 // Build reaction message with threading headers
864864- // markdown will be converted to HTML, plainText used for text/plain part
864864+ // markdown used for both text/plain and text/html parts (same as regular replies)
865865 raw, err := smtp.BuildReactionMessage(
866866 from, to, "", subject,
867867- bodyPlainText, bodyMarkdown,
867867+ bodyMarkdown,
868868 originalEmail.MessageID,
869869 references,
870870 )