From 8d40ed8b1993f7540d976dbaca01fe9cd58017c2 Mon Sep 17 00:00:00 2001 From: Zichao Lin Date: Sat, 11 Jul 2026 22:38:07 +0800 Subject: [PATCH] fix: use BODY.PEEK for large emails to prevent server auto-marking as read on timeout --- src/email_client.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/email_client.py b/src/email_client.py index e76f5d5..8ad9092 100644 --- a/src/email_client.py +++ b/src/email_client.py @@ -116,7 +116,20 @@ def fetch_unseen_emails(account: EmailAccount) -> list[Email]: for uid in uids: try: - _, msg_data = conn.uid("FETCH", uid, "RFC822") + # 先查大小,大邮件用 PEEK 避免长时间阻塞导致连接断开被标已读 + _, size_data = conn.uid("FETCH", uid, "(RFC822.SIZE)") + size = 0 + if size_data[0]: + m = re.search(rb"RFC822\.SIZE (\d+)", size_data[0]) + if m: + size = int(m.group(1)) + large = size > 200_000 + if large: + logger.info("UID %s 大邮件 (%d bytes),用 PEEK 截断处理", uid, size) + + # 大邮件用 PEEK 拉取,不触发服务器标记已读;小邮件正常拉 + fetch_cmd = "BODY.PEEK[]" if large else "RFC822" + _, msg_data = conn.uid("FETCH", uid, fetch_cmd) if msg_data[0] is None: logger.warning("UID %s FETCH 返回空,跳过", uid) continue @@ -129,6 +142,8 @@ def fetch_unseen_emails(account: EmailAccount) -> list[Email]: reply_to = _decode_address_header(msg.get("Reply-To", "")) date_str = msg.get("Date", "") body = _get_text_from_msg(msg) + if large: + body = body[:4000] + "\n...(邮件过长已截断)" body_len = len(body) logger.info(" 邮件: [%s] from=%s to=%s reply-to=%s (%d 字符)", subject, sender, recipient, reply_to, body_len)