Verified finding(s) from the 2026-07-09 whole-repo multi-agent review (independent finder, then adversarial verifier; verdict CONFIRMED).
Triage: above the cut — fix dispatched immediately; this issue tracks the fix to Done.
app/src/main/kotlin/org/libremail/data/ReplyBuilder.kt:49 — high
Replies always target the original From address; the Reply-To header is never used (ReplyContext built in ImapClient doesn't even carry it), so replies to any sender that sets Reply-To are prefilled to the wrong address.
Failure scenario: User replies to a message from a support desk, newsletter, or mailing list that sets 'From: noreply@corp.example' + 'Reply-To: support@corp.example'. reply() sets to = context.fromEmail = noreply@corp.example; ImapClient.ReplyContext (ImapClient.kt:519) reads only message.from, ignoring message.replyTo. The reply is sent to the unmonitored From address and never reaches the intended recipient — the RFC 5322 reply-addressing contract is broken for a very common class of mail. Reply-All is similarly wrong (Reply-To never enters the recipient set).
Verifier justification (CONFIRMED): ReplyContext (app/src/main/kotlin/org/libremail/mail/ImapClient.kt:92-100) carries no Reply-To field; fetchForReply builds it from val from = message.from?.firstOrNull() as? InternetAddress and fromEmail = from?.address.orEmpty() (lines 517-520), never calling message.getReplyTo(). ReplyBuilder.reply then sets to = context.fromEmail (ReplyBuilder.kt:49), and replyAllCc only merges toRecipients+ccRecipients, so Reply-To never enters any recipient set for REPLY or REPLY_ALL. Grep over app/src/main confirms 'replyTo' appears nowhere in the mail/compose path (only in the unrelated DebugReport feature). Concrete trigger: reply to any message with 'From: noreply@corp.example' + 'Reply-To: support@corp.example' — the compose To is prefilled with noreply@corp.example and, if sent unedited, the reply goes to an unmonitored address, violating RFC 5322 reply addressing. No known-intentional design covers this. Rated high (not critical): mail goes to the message's visible From address, which the user sees prefilled and can edit — a user-visible malfunction / likely-missed mail, not silent delivery to an unrelated third party.
Defective line:to = context.fromEmail,
Fix hint: Add a replyToEmails: List (or replyToEmail) field to ReplyContext and populate it in ImapClient.fetchForReply from message.getReplyTo() (Jakarta Mail already falls back to From when the header is absent); in ReplyBuilder use it for the reply To and exclude those addresses (alongside fromEmail) in replyAllCc. Mirror the same in any Outlook/Graph reply-context builder if one exists.
Verified finding(s) from the 2026-07-09 whole-repo multi-agent review (independent finder, then adversarial verifier; verdict **CONFIRMED**).
**Triage: above the cut — fix dispatched immediately; this issue tracks the fix to Done.**
## `app/src/main/kotlin/org/libremail/data/ReplyBuilder.kt:49` — high
Replies always target the original From address; the Reply-To header is never used (ReplyContext built in ImapClient doesn't even carry it), so replies to any sender that sets Reply-To are prefilled to the wrong address.
**Failure scenario:** User replies to a message from a support desk, newsletter, or mailing list that sets 'From: noreply@corp.example' + 'Reply-To: support@corp.example'. reply() sets to = context.fromEmail = noreply@corp.example; ImapClient.ReplyContext (ImapClient.kt:519) reads only message.from, ignoring message.replyTo. The reply is sent to the unmonitored From address and never reaches the intended recipient — the RFC 5322 reply-addressing contract is broken for a very common class of mail. Reply-All is similarly wrong (Reply-To never enters the recipient set).
**Verifier justification (CONFIRMED):** ReplyContext (app/src/main/kotlin/org/libremail/mail/ImapClient.kt:92-100) carries no Reply-To field; fetchForReply builds it from `val from = message.from?.firstOrNull() as? InternetAddress` and `fromEmail = from?.address.orEmpty()` (lines 517-520), never calling message.getReplyTo(). ReplyBuilder.reply then sets `to = context.fromEmail` (ReplyBuilder.kt:49), and replyAllCc only merges toRecipients+ccRecipients, so Reply-To never enters any recipient set for REPLY or REPLY_ALL. Grep over app/src/main confirms 'replyTo' appears nowhere in the mail/compose path (only in the unrelated DebugReport feature). Concrete trigger: reply to any message with 'From: noreply@corp.example' + 'Reply-To: support@corp.example' — the compose To is prefilled with noreply@corp.example and, if sent unedited, the reply goes to an unmonitored address, violating RFC 5322 reply addressing. No known-intentional design covers this. Rated high (not critical): mail goes to the message's visible From address, which the user sees prefilled and can edit — a user-visible malfunction / likely-missed mail, not silent delivery to an unrelated third party.
**Defective line:** `to = context.fromEmail,`
**Fix hint:** Add a replyToEmails: List<String> (or replyToEmail) field to ReplyContext and populate it in ImapClient.fetchForReply from message.getReplyTo() (Jakarta Mail already falls back to From when the header is absent); in ReplyBuilder use it for the reply To and exclude those addresses (alongside fromEmail) in replyAllCc. Mirror the same in any Outlook/Graph reply-context builder if one exists.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Verified finding(s) from the 2026-07-09 whole-repo multi-agent review (independent finder, then adversarial verifier; verdict CONFIRMED).
Triage: above the cut — fix dispatched immediately; this issue tracks the fix to Done.
app/src/main/kotlin/org/libremail/data/ReplyBuilder.kt:49— highReplies always target the original From address; the Reply-To header is never used (ReplyContext built in ImapClient doesn't even carry it), so replies to any sender that sets Reply-To are prefilled to the wrong address.
Failure scenario: User replies to a message from a support desk, newsletter, or mailing list that sets 'From: noreply@corp.example' + 'Reply-To: support@corp.example'. reply() sets to = context.fromEmail = noreply@corp.example; ImapClient.ReplyContext (ImapClient.kt:519) reads only message.from, ignoring message.replyTo. The reply is sent to the unmonitored From address and never reaches the intended recipient — the RFC 5322 reply-addressing contract is broken for a very common class of mail. Reply-All is similarly wrong (Reply-To never enters the recipient set).
Verifier justification (CONFIRMED): ReplyContext (app/src/main/kotlin/org/libremail/mail/ImapClient.kt:92-100) carries no Reply-To field; fetchForReply builds it from
val from = message.from?.firstOrNull() as? InternetAddressandfromEmail = from?.address.orEmpty()(lines 517-520), never calling message.getReplyTo(). ReplyBuilder.reply then setsto = context.fromEmail(ReplyBuilder.kt:49), and replyAllCc only merges toRecipients+ccRecipients, so Reply-To never enters any recipient set for REPLY or REPLY_ALL. Grep over app/src/main confirms 'replyTo' appears nowhere in the mail/compose path (only in the unrelated DebugReport feature). Concrete trigger: reply to any message with 'From: noreply@corp.example' + 'Reply-To: support@corp.example' — the compose To is prefilled with noreply@corp.example and, if sent unedited, the reply goes to an unmonitored address, violating RFC 5322 reply addressing. No known-intentional design covers this. Rated high (not critical): mail goes to the message's visible From address, which the user sees prefilled and can edit — a user-visible malfunction / likely-missed mail, not silent delivery to an unrelated third party.Defective line:
to = context.fromEmail,Fix hint: Add a replyToEmails: List (or replyToEmail) field to ReplyContext and populate it in ImapClient.fetchForReply from message.getReplyTo() (Jakarta Mail already falls back to From when the header is absent); in ReplyBuilder use it for the reply To and exclude those addresses (alongside fromEmail) in replyAllCc. Mirror the same in any Outlook/Graph reply-context builder if one exists.