fix: use BODY.PEEK for large emails to prevent server auto-marking as read on timeout

This commit is contained in:
2026-07-11 22:38:07 +08:00
parent 57191ab00e
commit 8d40ed8b19

View File

@@ -116,7 +116,20 @@ def fetch_unseen_emails(account: EmailAccount) -> list[Email]:
for uid in uids: for uid in uids:
try: 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: if msg_data[0] is None:
logger.warning("UID %s FETCH 返回空,跳过", uid) logger.warning("UID %s FETCH 返回空,跳过", uid)
continue continue
@@ -129,6 +142,8 @@ def fetch_unseen_emails(account: EmailAccount) -> list[Email]:
reply_to = _decode_address_header(msg.get("Reply-To", "")) reply_to = _decode_address_header(msg.get("Reply-To", ""))
date_str = msg.get("Date", "") date_str = msg.get("Date", "")
body = _get_text_from_msg(msg) body = _get_text_from_msg(msg)
if large:
body = body[:4000] + "\n...(邮件过长已截断)"
body_len = len(body) body_len = len(body)
logger.info(" 邮件: [%s] from=%s to=%s reply-to=%s (%d 字符)", subject, sender, recipient, reply_to, body_len) logger.info(" 邮件: [%s] from=%s to=%s reply-to=%s (%d 字符)", subject, sender, recipient, reply_to, body_len)