mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-08 13:12:08 +00:00
fix(email): harden adapter against malformed IMAP responses
Salvage of #2794 by @CharmingGroot, ported to the relocated plugins/platforms/email/adapter.py: - Guard raw_email = msg_data[0][1] against IndexError/TypeError and non-bytes payloads. UIDs are added to _seen_uids before fetch, so an exception mid-batch permanently skipped every remaining message in the batch — now the bad message is logged and skipped instead. - Message-ID domain generation falls back to 'localhost' when EMAIL_ADDRESS lacks '@' (now via a shared _message_id_domain() helper covering all 3 send paths; the PR fixed 2 of 3).
This commit is contained in:
parent
c43aa6301d
commit
88bd1c01e1
3 changed files with 142 additions and 4 deletions
|
|
@ -673,7 +673,25 @@ class EmailAdapter(BasePlatformAdapter):
|
|||
if status != "OK":
|
||||
continue
|
||||
|
||||
raw_email = msg_data[0][1]
|
||||
# IMAP fetch can return unexpected structures (e.g. a
|
||||
# single bytes item instead of a list of tuples). Guard
|
||||
# against IndexError / TypeError so one malformed response
|
||||
# doesn't abort the batch — the UID is already in
|
||||
# _seen_uids, so an abort would permanently skip the
|
||||
# remaining messages in this batch.
|
||||
try:
|
||||
raw_email = msg_data[0][1]
|
||||
except (IndexError, TypeError):
|
||||
logger.warning(
|
||||
"[Email] Unexpected IMAP response structure for UID %s, skipping",
|
||||
uid,
|
||||
)
|
||||
continue
|
||||
if not isinstance(raw_email, (bytes, bytearray)):
|
||||
logger.warning(
|
||||
"[Email] Non-bytes IMAP payload for UID %s, skipping", uid
|
||||
)
|
||||
continue
|
||||
msg = email_lib.message_from_bytes(raw_email)
|
||||
|
||||
sender_raw = msg.get("From", "")
|
||||
|
|
@ -890,6 +908,16 @@ class EmailAdapter(BasePlatformAdapter):
|
|||
logger.error("[Email] Send failed to %s: %s", chat_id, e)
|
||||
return SendResult(success=False, error=str(e))
|
||||
|
||||
def _message_id_domain(self) -> str:
|
||||
"""Domain part for generated Message-IDs.
|
||||
|
||||
EMAIL_ADDRESS may lack an ``@`` (misconfiguration); fall back to
|
||||
``localhost`` instead of crashing send with an IndexError.
|
||||
"""
|
||||
if "@" in self._address:
|
||||
return self._address.rsplit("@", 1)[-1] or "localhost"
|
||||
return "localhost"
|
||||
|
||||
def _send_email(
|
||||
self,
|
||||
to_addr: str,
|
||||
|
|
@ -915,7 +943,7 @@ class EmailAdapter(BasePlatformAdapter):
|
|||
msg["References"] = original_msg_id
|
||||
|
||||
msg["Date"] = formatdate(localtime=True)
|
||||
msg_id = f"<hermes-{uuid.uuid4().hex[:12]}@{self._address.split('@')[1]}>"
|
||||
msg_id = f"<hermes-{uuid.uuid4().hex[:12]}@{self._message_id_domain()}>"
|
||||
msg["Message-ID"] = msg_id
|
||||
|
||||
msg.attach(MIMEText(body, "plain", "utf-8"))
|
||||
|
|
@ -1028,7 +1056,7 @@ class EmailAdapter(BasePlatformAdapter):
|
|||
msg["References"] = original_msg_id
|
||||
|
||||
msg["Date"] = formatdate(localtime=True)
|
||||
msg_id = f"<hermes-{uuid.uuid4().hex[:12]}@{self._address.split('@')[1]}>"
|
||||
msg_id = f"<hermes-{uuid.uuid4().hex[:12]}@{self._message_id_domain()}>"
|
||||
msg["Message-ID"] = msg_id
|
||||
|
||||
if body:
|
||||
|
|
@ -1108,7 +1136,7 @@ class EmailAdapter(BasePlatformAdapter):
|
|||
msg["References"] = original_msg_id
|
||||
|
||||
msg["Date"] = formatdate(localtime=True)
|
||||
msg_id = f"<hermes-{uuid.uuid4().hex[:12]}@{self._address.split('@')[1]}>"
|
||||
msg_id = f"<hermes-{uuid.uuid4().hex[:12]}@{self._message_id_domain()}>"
|
||||
msg["Message-ID"] = msg_id
|
||||
|
||||
if body:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue