ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

himalaya Maildir 自定义关键词读取指南:dovecot-keywords 与 X-Keywords / X-Label 的配置与实现原理

himalaya Maildir 自定义关键词读取指南:dovecot-keywords 与 X-Keywords / X-Label 的配置与实现原理 CLI【免费下载链接】himalayaCLI to manage emails项目地址https://gitcode.com/gh_mirrors/hi/himalaya点击查看免费下载himalaya 的 Maildir 后端在 v0.8 引入了maildir.keywords.dovecot与maildir.keywords.header两个按账户配置项用于在读取邮件时把 dovecot、mbsync、OfflineIMAP、mutt、notmuch 等工具写入的自定义非 IANA关键词解析为 flag使envelope list flag NonJunk这类搜索在 Maildir 上与 IMAP、JMAP、Graph 后端行为一致。本文以 cairn/changes/maildir-custom-keywords/delta.md 为骨架结合 proposal.md、tasks.md 与仓库源码说明配置方法、两种关键词约定的差异、读写不对称的边界行为以及 io-maildir 库在其中承担的角色。背景Maildir 上自定义关键词为何静默不可见Maildir 的文件名本身只承载六个标准 IANA 信息位Draft、Flagged、Passed、Replied、Seen、Trashed而 dovecot、mbsync、OfflineIMAP 等工具会把自定义关键词以小写字母 slot 的形式追加在 info-section 中例如NonJunk落在某个小写字母上其含义由一个旁挂文件或正文头部另行定义。此前的 himalaya 读取路径只映射六个标准字母、丢弃其余字符导致envelope list flag NonJunk在 IMAP、JMAP 和 Graph 上都能命中在 Maildir 上却静默匹配为空——即使关键词确实在邮箱里。关键在于共享数据模型一直有能力携带自定义关键词Flag以iana: None保留原始拼写其余每个后端都通过Flag::from_raw把它们读回来见 src/email/flag.rs。Maildir 是唯一一个经由封闭表过滤、把六个标准字母之外的小写 slot 字母全部丢弃的后端。为什么必须显式命名而不是自动推断Maildir 没有一个统一的关键词约定因此无法靠猜测解析slot 字母约定关键词存放在邮箱自己的dovecot-keywords文件中把一个小写字母映射到一个关键词名没有这个 sidecar单独的 slot 字母毫无意义。头部约定关键词内联在正文头部中X-Keywords逗号分隔OfflineIMAP、mbsync 使用或X-Label空格分隔mutt、notmuch 使用。由于猜头部可能发明出不存在的 flag两种机制都必须显式开启并指名opt-in and named。这正是 proposal.md 中所述的核心设计约束并最终固化为 delta.md 中的需求maildir.keywords.dovecotSHALL resolve the lowercase info-section slot letters through the resolved mailboxs owndovecot-keywordsfile, andmaildir.keywords.headerSHALL read keywords fromX-Keywords(comma-separated) orX-Label(space-separated). Both default to off, and with both off the flag set SHALL be exactly the six standard info-section letters as before.配置项maildir.keywords.dovecot 与 maildir.keywords.header两个选项都位于账户的[maildir]配置块之下默认全部关闭。仓库自带的 config.sample.toml 给出了完整示例# The Maildir root, one subdirectory per mailbox below it. #maildir.root ~/Mail/example # Resolve custom keywords through each mailboxs own dovecot-keywords file, # which maps a lowercase info-section letter to a keyword. Off by default, # leaving those letters unread. #maildir.keywords.dovecot true # Read custom keywords from a body header instead: x-keywords is the # comma-separated OfflineIMAP and mbsync convention, x-label the # space-separated mutt and notmuch one. Unset by default, reading neither. #maildir.keywords.header x-keywords #maildir.keywords.header x-label # Reading keywords is not a round trip: no command can name a custom keyword, so # flag set replaces the whole set and drops the ones the message carried.配置语义在源码中的定义如下src/config.rsMaildirKeywordHeaderConfigkebab-case 反序列化两个变体——XKeywords对应配置值x-keywords逗号分隔OfflineIMAP/mbsync 约定与XLabel对应x-label空格分隔mutt/notmuch 约定。它刻意在 himalaya 侧保留一个本地镜像使配置 schema 不依赖任何后端 crate从而在任意 feature 子集下都能编译。MaildirKeywordsConfigdovecot: bool是否通过邮箱自己的dovecot-keywords文件解析小写 slot 字母默认false与header: OptionMaildirKeywordHeaderConfig从哪个正文头部读取未设置则不读取。MaildirConfig.keywords使用#[serde(default)]整个块可省略MaildirKeywordsConfig上带deny_unknown_fields拼错键名会直接报错而不是被静默忽略。生效后两个选项会一路下传到 io-maildir 的内部客户端src/maildir/client.rs 在构建MaildirClient时执行两行赋值inner.dovecot_keywords config.keywords.dovecot; inner.keywords_header config.keywords.header.map(Into::into);本地MaildirKeywordHeaderConfig到 io-maildirKeywordHeader的转换由 src/maildir/client.rs 的From实现完成。由于MaildirClient对外 deref 到内部客户端src/maildir/client.rsCLI 与共享构造路径一次性全部覆盖。解析归属io-maildir 负责存储语义himalaya 只保留配置表面这个改动刻意没有把 Maildir 文件名的解析逻辑搬进 himalaya。原因有二格式归属Maildir 文件名含义属于存储语义按贡献指南应由拥有该格式的库io-maildir决定此前 himalaya 在本地实现的parse_filename_flags与flag_from_char是格式逻辑的重复拷贝存在与库漂移的风险本次被删除。复用的需要neverest 与 replica 工作都需要同一份解析结果不可能从一个躺在 himalaya 里的副本获得。io-maildir 的客户端原本就在 store 时持有dovecot_keywords与keywords_header并予以尊重只是读取路径两者都忽略——这正是它看起来像 himalaya 功能的原因。上游补全了读取半边所有读取路径read_entry、read_entries、read_entries_par、get现在都接收条目来自哪个 Maildir作为参数并返回 flag 已解析好的条目结果挂在MaildirFullEntry::flags上组合过程是一个无 I/O 的MaildirFlags::with_keywords客户端为每次调用加载一次映射表见 tasks.md 的任务清单。himalaya 这边剩下的工作是 src/maildir/backend.rs 里的双向映射/// Maps a shared [Flag] to a [MaildirFlag]; non-IANA keywords go /// through [MaildirFlag::Keyword] for the dovecot-keywords sidecar. fn flag_to_maildir(flag: Flag) - MaildirFlag { match flag.iana() { Some(IanaFlag::Seen) MaildirFlag::Seen, Some(IanaFlag::Answered) MaildirFlag::Replied, Some(IanaFlag::Flagged) MaildirFlag::Flagged, Some(IanaFlag::Draft) MaildirFlag::Draft, Some(IanaFlag::Deleted) MaildirFlag::Trashed, Some(IanaFlag::Forwarded) MaildirFlag::Passed, Some(_) | None MaildirFlag::Keyword(flag.raw().to_string()), } } /// Maps a [MaildirFlag] to a shared [Flag]; the inverse of /// [flag_to_maildir]. fn flag_from_maildir(flag: MaildirFlag) - Flag { match flag { MaildirFlag::Seen Flag::from_iana(IanaFlag::Seen), MaildirFlag::Replied Flag::from_iana(IanaFlag::Answered), MaildirFlag::Flagged Flag::from_iana(IanaFlag::Flagged), MaildirFlag::Draft Flag::from_iana(IanaFlag::Draft), MaildirFlag::Trashed Flag::from_iana(IanaFlag::Deleted), MaildirFlag::Passed Flag::from_iana(IanaFlag::Forwarded), MaildirFlag::Keyword(keyword) Flag::from_raw(keyword), } }读取方向中六个标准位回射到 IANA flagMaildirFlag::Keyword则经Flag::from_raw保留原始拼写进入共享模型写入方向反之非 IANA 关键词统一走MaildirFlag::Keyword交给 sidecar。枚举读取时后端直接从MaildirFullEntry::flags取值而不是再解析一遍文件名src/maildir/backend.rs 等处调用self.read_entries(maildir, entries)后经envelope_from_entry构造信封。读取不是往返flag set 会替换整个集合自定义关键词读取存在一个刻意保留的不对称read parity而非 round trip没有任何命令能指名一个自定义关键词——FlagArg是封闭的四变体ValueEnum在任何后端上都无法通过命令行参数写出一个关键词。因此FlagOp::Set的存储会替换整个 flag 集合并丢弃邮件携带的关键词delta.md 明确a FlagOp::Set store SHALL replace the whole set and drop any keyword the message carried。该行为被如实记录进 config.sample.toml 的注释与 CHANGELOG.md而不是试图修复——因为修它需要先扩大 flag 参数的取值面那是另一个跨后端的独立问题明确列入本次非目标。此外头部路径还有一个细节maildir.keywords.header只读且仅在 store 时追加io-maildir 会在解析头部之前排空旧关键词drain。边界行为sidecar 缺失、不可读或禁用不报错规范特别强调了容错语义delta.md 与 cairn/spec/backends.md 一致A sidecar that is absent, unreadable or disabled SHALL yield no keywords rather than fail the listing, since a mailbox without one is the normal case rather than an error.没有dovecot-keywords文件、文件不可读、或对应选项未开启都是该邮箱没有关键词这一正常情况而不是错误——列目录必须照常成功只是不产出任何关键词。依赖与版本前提io-maildir 0.3 与 [patch.crates-io]两个半边的解析能力都是 io-maildir 尚未发布的成果因此存在明确的版本前提proposal.md 的 Upstream prerequisite 一节读取 API 是 0.3 新增的Cargo.toml因此声明io-maildir { version 0.3, default-features false, optional true }Cargo.toml并暂以[patch.crates-io]块指向本地 checkout待 0.3 发布后移除。另一半是上游仓库中已合并但未打 tag 的改动在 0.2.1 上每个 flag store 背后的条目定位逻辑都会在重命名前丢弃 slot 字母导致一次 flag 操作会剥离它从未触碰的关键词——message read --seen也不例外因为它走同一条标记已读的路径。这也是他拉雅 TUIhimalaya-tui需要通过同一 API 读取条目、需要同步升级的原因。maildirfeature 同时启用io-maildir/client与io-maildir/parser两个子 featureCargo.toml自定义关键词解析正是在 client 子 feature 中提供。验证与测试覆盖落地日志cairn/log/2026-08-16-maildir-custom-keywords.md记录了完整的验证情况himalaya 侧build、fmt、clippy 干净112 个测试通过七个原本在测 io-maildir 的测试随解析逻辑一起上移。上游侧io-maildir 80 个单元测试新增 6 个、15 个集成测试新增 7 个位于tests/keyword_reads.rs及 15 个文档测试通过。himalaya 保留的测试聚焦于双向 flag 映射、信封携带读取到的 flag关键词解析本身归上游测试。三个精简 feature 构建通过——它们专门用来捕获后端 crate 泄漏进配置 schema这类问题而MaildirKeywordHeaderConfig本地镜像正是为此存在。端到端验证该改动作为 pimalaya/himalaya#735 提交对一个一次性 Maildir 的实测中envelope search flag NonJunk从零命中变为一个命中未对真实 dovecot 写入的邮箱做二次验证也未在重构后重跑。小结配置三步走要让 Maildir 上的自定义关键词可被flag name搜索命中只需在账户配置中按所用约定开启对应选项dovecot 系slot 字母 dovecot-keywordssidecarmaildir.keywords.dovecot trueOfflineIMAP / mbsyncX-Keywords逗号分隔maildir.keywords.header x-keywordsmutt / notmuchX-Label空格分隔maildir.keywords.header x-label。两者可同时开启、也可都保持默认关闭此时 flag 集合与旧行为完全一致。需注意这只是一次读取能力写入关键词、以及让flag set保留已有关键词均不在本次范围内。相关文档与源码需求变更 cairn/changes/maildir-custom-keywords/delta.md设计提案 cairn/changes/maildir-custom-keywords/proposal.md任务追踪 cairn/changes/maildir-custom-keywords/tasks.md落地日志 cairn/log/2026-08-16-maildir-custom-keywords.md后端规范Maildir 关键词需求 cairn/spec/backends.md配置定义 src/config.rs配置下发 src/maildir/client.rs双向 flag 映射 src/maildir/backend.rs配置示例 config.sample.toml变更日志 CHANGELOG.md赞分享CLI【免费下载链接】himalayaCLI to manage emails项目地址https://gitcode.com/gh_mirrors/hi/himalaya点击查看免费下载相关推荐pandas 窗口操作Windowing Operations完全指南Rolling / Expanding / EWM 窗口函数与自定义索引器 API 详解pandas 窗口操作Windowing Operations完全指南Rolling / Expanding / EWM 窗口函数与自定义索引器 APICLIAutoGPT 中的 DataForSEO Related Keywords Block语义关键词发现与 SEO 指标提取实战指南AutoGPT 中的 DataForSEO Related Keywords Block语义关键词发现与 SEO 指标提取实战指南 导读 本文基于 relat人工智能AI Agent自主智能体Agent 工作流工作流自动化后端前端Builder.io 可视化CMS集成踩坑实录6个报错的完整排查路径Builder.io 可视化CMS集成踩坑实录6个报错的完整排查路径 启动即白屏控制台闪过的唯一红字是 Missing environment variabCLI上一篇开源项目dnsjava快速指南与常见问题解答下一篇终极指南3步将闲置电视盒子变身高性能ARM服务器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表