fix: maintain full references chain for thread grouping and append quoted previous message

linuztx committed Mar 18, 2026 at 13:55 UTC f2b8ae44a9432c0762c7f29c9513ce0e2d74176b
2 files changed +30 -2
plugins/_email_integration/helpers/dispatcher.py
+1
@@ -19,6 +19,7 @@ CTX_EMAIL_THREAD_ID = "email_thread_id"
19 CTX_EMAIL_SUBJECT = "email_subject"
20 CTX_EMAIL_MESSAGE_ID = "email_message_id"
21 CTX_EMAIL_REFERENCES = "email_references"
22 +CTX_EMAIL_LAST_BODY = "email_last_body"
23 # Transient — consumed per-reply, not persisted
24 CTX_EMAIL_ATTACHMENTS = "_email_response_attachments"
25
plugins/_email_integration/helpers/handler.py
+29 -2
@@ -269,8 +269,18 @@ async def _start_new_chat(agent: Agent, handler_cfg: dict, msg: InboundMessage):
269 context.data[disp.CTX_EMAIL_SENDER] = msg.sender
270 context.data[disp.CTX_EMAIL_THREAD_ID] = thread_id
271 context.data[disp.CTX_EMAIL_SUBJECT] = msg.subject
272 + context.data[disp.CTX_EMAIL_LAST_BODY] = msg.body
273 context.data[disp.CTX_EMAIL_MESSAGE_ID] = msg.message_id
273 - context.data[disp.CTX_EMAIL_REFERENCES] = msg.references
274 +
275 + refs_list = []
276 + if msg.references:
277 + for r in msg.references.split():
278 + if r not in refs_list:
279 + refs_list.append(r)
280 + if msg.message_id and msg.message_id not in refs_list:
281 + refs_list.append(msg.message_id)
282 +
283 + context.data[disp.CTX_EMAIL_REFERENCES] = " ".join(refs_list)
284
285 project = handler_cfg.get("project", "")
286 if project:
@@ -302,8 +312,20 @@ async def _route_to_chat(
312 return
313
314 context.data[disp.CTX_EMAIL_MESSAGE_ID] = msg.message_id
315 + context.data[disp.CTX_EMAIL_LAST_BODY] = msg.body
316 +
317 + refs = context.data.get(disp.CTX_EMAIL_REFERENCES, "")
318 + refs_list = refs.split() if refs else []
319 +
320 if msg.references:
306 - context.data[disp.CTX_EMAIL_REFERENCES] = msg.references
321 + for r in msg.references.split():
322 + if r not in refs_list:
323 + refs_list.append(r)
324 +
325 + if msg.message_id and msg.message_id not in refs_list:
326 + refs_list.append(msg.message_id)
327 +
328 + context.data[disp.CTX_EMAIL_REFERENCES] = " ".join(refs_list)
329
330 user_msg = _build_user_message(agent, msg, handler_cfg)
331 mq.log_user_message(context, user_msg, msg.attachments or [], source=" (email)")
@@ -423,6 +445,11 @@ async def send_email_reply(
445 # Read attachment files via RFC (they live in the execution runtime)
446 attachment_data = await _read_attachments_via_rfc(attachments)
447
448 + last_body = context.data.get(disp.CTX_EMAIL_LAST_BODY, "").strip()
449 + if last_body:
450 + quoted = "\n> " + "\n> ".join(last_body.splitlines())
451 + response_text = f"{response_text}\n\nOn previous message:\n{quoted}"
452 +
453 return await send_reply(
454 config=smtp_cfg,
455 to=sender,