Fetch full messages with BODY.PEEK[] so read_email works on iCloud IMAP (#1961) (#1963)

read_email, reply_to_email and download_attachment fetched the full message with
the legacy bare RFC822 item (UID FETCH <uid> (RFC822)). iCloud's IMAP server
silently ignores it — the fetch returns status OK but only (UID <uid>) with no
body tuple, so the parse reports 'Email not found with UID' even though the
message exists and list_emails (which uses RFC822.HEADER) shows it. Gmail honours
(RFC822), which is why it only reproduced on iCloud.

Switch the three full-message fetches to (BODY.PEEK[]), which iCloud and Gmail
both honour and which doesn't set \Seen. Response shape is unchanged (raw bytes
still at msg_data[0][1]), so parsing is unaffected; the RFC822.HEADER (listing)
and (UID) probe fetches are left as-is.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
lekt8
2026-06-04 10:53:14 +08:00
committed by GitHub
parent a38df08a31
commit ceb62385f1
2 changed files with 44 additions and 3 deletions

View File

@@ -666,7 +666,7 @@ def _read_email(uid=None, message_id=None, folder="INBOX", account=None):
conn.logout()
return {"error": "No UID or Message-ID provided"}
status, msg_data = conn.uid("FETCH", _b(uid), "(RFC822)")
status, msg_data = conn.uid("FETCH", _b(uid), "(BODY.PEEK[])")
if status != "OK":
conn.logout()
return {"error": f"Failed to fetch email UID {uid}"}
@@ -855,7 +855,7 @@ def _reply_to_email(uid, body, folder="INBOX", reply_all=False, account=None):
"""Reply to an existing email by UID. Threads via In-Reply-To/References."""
conn = _imap_connect(account)
conn.select(folder, readonly=True)
status, msg_data = conn.uid("FETCH", _b(uid), "(RFC822)")
status, msg_data = conn.uid("FETCH", _b(uid), "(BODY.PEEK[])")
conn.logout()
if status != "OK" or not msg_data or not msg_data[0]:
return {"error": f"Failed to fetch email UID {uid}"}
@@ -1033,7 +1033,7 @@ def _download_attachment(uid, index, folder="INBOX", account=None):
"""Extract a specific attachment to disk and return its local path."""
conn = _imap_connect(account)
conn.select(folder, readonly=True)
status, msg_data = conn.uid("FETCH", _b(uid), "(RFC822)")
status, msg_data = conn.uid("FETCH", _b(uid), "(BODY.PEEK[])")
conn.logout()
if status != "OK":
return {"error": f"Failed to fetch email UID {uid}"}