fix: cap send retries to prevent infinite loop on persistent SMTP failures

linuztx committed Mar 16, 2026 at 09:13 UTC 8596eaf6fec251ecfd3790c9ae38028784bb2cf6
2 files changed +28 -5
plugins/_email_integration/extensions/python/process_chain_end/_55_email_reply.py
+26 -4
@@ -6,6 +6,9 @@ from helpers.print_style import PrintStyle
6 from agent import AgentContext, LoopData, UserMessage
7 from plugins._email_integration.helpers.dispatcher import CTX_EMAIL_HANDLER, CTX_EMAIL_ATTACHMENTS
8
9 +MAX_SEND_RETRIES: int = 2
10 +CTX_SEND_FAILURES: str = "_email_send_failures"
11 +
12
13 class EmailAutoReply(Extension):
14
@@ -31,8 +34,22 @@ class EmailAutoReply(Extension):
34 ):
35 from plugins._email_integration.helpers.handler import send_email_reply
36 error = await send_email_reply(context, response_text, attachments)
34 - if error:
35 - _notify_agent_of_failure(context, error)
37 + if not error:
38 + context.data[CTX_SEND_FAILURES] = 0
39 + return
40 + failures = context.data.get(CTX_SEND_FAILURES, 0) + 1
41 + context.data[CTX_SEND_FAILURES] = failures
42 + if failures <= MAX_SEND_RETRIES:
43 + _notify_agent_of_failure(context, error, failures)
44 + else:
45 + PrintStyle.error(
46 + f"Email send failed {failures} times, giving up: {error}"
47 + )
48 + context.log.log(
49 + type="error",
50 + heading="Email send failed (max retries reached)",
51 + content=error,
52 + )
53
54
55 # ------------------------------------------------------------------
@@ -50,8 +67,13 @@ def _extract_last_response(context: AgentContext) -> str:
67 return ""
68
69
53 -def _notify_agent_of_failure(context: AgentContext, error: str):
70 +def _notify_agent_of_failure(
71 + context: AgentContext, error: str, attempt: int,
72 +):
73 from plugins._email_integration.helpers.handler import _read_fw
55 - msg = _read_fw("fw.email.send_failed.md", error=error)
74 + msg = _read_fw(
75 + "fw.email.send_failed.md", error=error, attempt=str(attempt),
76 + max_retries=str(MAX_SEND_RETRIES),
77 + )
78 context.log.log(type="error", heading="Email send failed", content=error)
79 context.communicate(UserMessage(message="", system_message=[msg]))
plugins/_email_integration/prompts/fw.email.send_failed.md
+2 -1
@@ -1,3 +1,4 @@
1 -email send failed: {{error}}
1 +email send failed (attempt {{attempt}}/{{max_retries}}): {{error}}
2 previous response was NOT delivered to user
3 retry without problematic content or inform user via alternative means
4 +if attachment caused the issue, retry without it