[BUG] Outlook 邮件标记已读后,概览显示「(无主题)」、正文变为空白(本地数据被增量同步覆盖清空)
环境
- 版本:v0.1.4(官方 Linux
.deb)
- 系统:Linux x86_64(NixOS)
- 账户类型:Outlook(Microsoft Graph)
打包脚本及说明位于此处:https://github.com/Mooling0602/nix-packages/tree/main/pkgs/by-name/pe/pebble-mail
现象
在 Outlook 账户下将邮件标记为已读后,经过一轮增量同步,该邮件在列表中的主题变为「(无主题)」、摘要消失,点开正文也是空白。未读邮件不受影响,IMAP/Gmail 账户未观察到此问题(未经测试)。
复现步骤
- 添加 Outlook 账户并完成首次同步(邮件主题/正文显示正常)
- 在 Pebble 中打开一封未读邮件(触发
update_message_flags → Graph API PATCH isRead=true)
- 等待/触发下一轮 Outlook 增量同步(delta)
- 该邮件在列表中显示「(无主题)」,正文空白
本地数据库证据
对 ~/.local/share/com.qingj01.pebble/db/pebble.db(SQLite)只读统计:
| 指标 |
数值 |
| 邮件总数 |
112 |
| subject / snippet / body_text / body_html_raw 同时为空 |
21 封 |
| 上述邮件中 is_read=1 |
21 封(全部) |
| 上述邮件中 is_read=0 |
0 封 |
| provider 分布 |
全部为 outlook |
即:被清空的邮件全部是 Outlook 账户的已读邮件,且均为当天增量同步时段被覆盖(updated_at 集中在标记已读之后的同步时间点)。
根因分析(供参考)
完整因果链如下(源码基于 main 分支):
-
标记已读后,Microsoft Graph 在服务端记录了该消息的变更。下一轮 delta 增量同步会返回该消息的薄变更条目——Graph delta 的标准行为是只返回发生变化的属性(此处仅 id + isRead),不包含 subject/body 等未变化字段。
-
crates/pebble-mail/src/provider/outlook.rs 中 GraphMessage 的所有字段均为 Option(约 L44-67),graph_message_to_message(约 L685)对缺失字段一律 unwrap_or_default(),于是薄条目被转换成 subject/snippet/body 全为空字符串的 Message。
-
crates/pebble-mail/src/outlook_sync.rs 的 persist_folder_messages_with_attachment_fetch 中,已存在消息(existing 分支,约 L494-604)仅保留本地 created_at / thread_id,随后调用 replace_message_with_attachments 整行覆盖本地记录,空字符串随之写库,原始 subject/snippet/body 丢失。
-
前端列表以 message.subject || t("inbox.noSubject") 兜底(src/components/MessageItem.tsx L191),故显示「(无主题)」;正文同理空白。
IMAP 账户不受影响的原因:其 reconcile 路径走 fetch_flags + bulk_update_flags,只更新标志位、不整行替换。
修复方向建议
- 在 existing 分支识别「薄 delta 条目」:当服务器条目的 subject 与 body 均缺失时,退化为只更新 flags(可复用
bulk_update_flags),不做整行替换;
- 或在 replace 前用本地已有值回填条目中缺失的字段(仓库中已有类似先例:
preserve_local_state_for_attachment_repair 对 is_read/is_starred/created_at 的保留处理)。
内容由 LLM 生成并可能经过人工修订改正处理,其中提出的建议和解决方案未必真实有效,需根据实际情况处理。
DeepSeek Harness GLM-5.3 Max
[BUG] Outlook 邮件标记已读后,概览显示「(无主题)」、正文变为空白(本地数据被增量同步覆盖清空)
环境
.deb)现象
在 Outlook 账户下将邮件标记为已读后,经过一轮增量同步,该邮件在列表中的主题变为「(无主题)」、摘要消失,点开正文也是空白。未读邮件不受影响,IMAP/Gmail 账户未观察到此问题(未经测试)。
复现步骤
update_message_flags→ Graph APIPATCH isRead=true)本地数据库证据
对
~/.local/share/com.qingj01.pebble/db/pebble.db(SQLite)只读统计:即:被清空的邮件全部是 Outlook 账户的已读邮件,且均为当天增量同步时段被覆盖(
updated_at集中在标记已读之后的同步时间点)。根因分析(供参考)
完整因果链如下(源码基于 main 分支):
标记已读后,Microsoft Graph 在服务端记录了该消息的变更。下一轮 delta 增量同步会返回该消息的薄变更条目——Graph delta 的标准行为是只返回发生变化的属性(此处仅
id+isRead),不包含 subject/body 等未变化字段。crates/pebble-mail/src/provider/outlook.rs中GraphMessage的所有字段均为Option(约 L44-67),graph_message_to_message(约 L685)对缺失字段一律unwrap_or_default(),于是薄条目被转换成 subject/snippet/body 全为空字符串的Message。crates/pebble-mail/src/outlook_sync.rs的persist_folder_messages_with_attachment_fetch中,已存在消息(existing 分支,约 L494-604)仅保留本地created_at/thread_id,随后调用replace_message_with_attachments整行覆盖本地记录,空字符串随之写库,原始 subject/snippet/body 丢失。前端列表以
message.subject || t("inbox.noSubject")兜底(src/components/MessageItem.tsxL191),故显示「(无主题)」;正文同理空白。IMAP 账户不受影响的原因:其 reconcile 路径走
fetch_flags+bulk_update_flags,只更新标志位、不整行替换。修复方向建议
bulk_update_flags),不做整行替换;preserve_local_state_for_attachment_repair对 is_read/is_starred/created_at 的保留处理)。内容由 LLM 生成并可能经过人工修订改正处理,其中提出的建议和解决方案未必真实有效,需根据实际情况处理。