资讯动态

himalaya JMAP 后端在 Fastmail 上的共享命令测试报告:v2.0.0-alpha.1 实测结论与源码级解读

发布时间:2026/10/5 2:10:29 来源:尧图企业网站定制
CLI【免费下载链接】himalayaCLI to manage emails项目地址https://gitcode.com/gh_mirrors/hi/himalaya点击查看免费下载本篇技术指南以 himalaya 仓库内真实的 provider 测试报告 cairn/spec/testing/jmap-fastmail.md 为主体完整解读「跨协议共享命令」在 JMAP 后端、Fastmail 真实账号上的逐命令实测结果环境与夹具、结果总览、J1/J2/J3 三项关键发现含envelope search选项粘连、copy/move 计数语义、JMAP 发送配置自动发现、日期过滤语义与索引最终一致性。同时对照 src/jmap/backend.rs、src/jmap/client.rs 等源码把命令行操作落到Email/query、Email/set、Blob/download、EmailSubmission/set的调用链上并给出 config.sample.toml 中的完整 JMAP 配置参考。读完本文你既能复现这套针对 Fastmail 的 JMAP 端到端测试方法也能理解 himalaya 共享层如何在 JMAP 上完成「按名字寻址邮箱、按语义映射日期、最小配置发送邮件」这三个核心机制。一、测试背景为什么需要一份「真实账号」上的共享命令报告himalaya 的单元测试只把每个io-*crate 隔离起来运行但搜索语义、日期处理、错误表面、标记渲染、MIME 往返这类行为只有在与真实服务器端到端交互时才会暴露。因此测试规范 cairn/spec/testing/provider-test-plan.md 规定对每个(backend, provider)组合用一次性假邮箱逐命令、逐 flag 手工跑一遍产出一份报告。JMAP 报告对应的被测对象是共享跨协议命令——即mailbox、envelope、flag、message、attachment这一层对所有后端统一暴露的 CLI区别于himalaya jmap …原始方法面后者见配套报告 cairn/spec/testing/jmap-specific-fastmail.md。被测环境来自报告头部项值himalaya 版本v2.0.0-alpha.1 jmap rustls-ring工作树含共享层 JMAP 的 name→id、blob 下载、CRLF、F1/F2/F3 修复账号fastmail-jmapjmap.server api.fastmail.combearer token测试日期2026-07-17夹具5 封邮件Alpha…Epsilon发送者/主题/日期/flag 各不相同另含一封multipart/mixed带note.txt附件方法两个一次性 JMAP 邮箱Himalaya-Jmap-A/-B内手工执行全部命令×flag黄金规则摘自 provider-test-plan只用假邮箱每次运行创建一次性邮箱并在其中操作绝不碰既有数据部分账号是共享测试收件箱另一些放着真实邮件。两个假邮箱copy/move需要独立的源与目标。清理结束时删除假邮箱SMTPsend将邮件发给自己再从收件箱移入 Trash。不泄露凭据凭据一律走配置中的passwd.command/token.command不回显。二、结果总览共享命令在 JMAP 上全部通过报告核心是一张逐命令结果表覆盖共享层在 JMAP 上的全部命令面。原文表格完整继承如下命令测试变体结果mailbox listbase、--counts内联、--json✅envelope listbase、分页、-r、--has-attachment、--json、按名字和不透明 id、空邮箱✅envelope searchfrom/to/subject/body/flag/not、date/after、and/or/分组、order by … asc/desc、--json✅见 J1message add内联转义、内联 LF、stdin、--json、-f空输入 →Message is empty✅message readpretty、multipart、--raw、--json、错误 id✅blob 下载正常flag add/set/remove多 flag、set 替换、remove✅message copy/move按名字、F2 计数、无效 id✅见 J2attachment list/downloadlist、-i、-d✅message composefrom/to/cc/bcc/subject/body/body-file/attach/signature/--save✅message reply/forward--save线程、Re:/Fwd:、引用✅message send/compose --sendJMAP submission 路径✅自动发现 identity drafts见 J3同时报告确认此前所有共享层 JMAP bug——把名字当inMailbox用、按名字 import、message read的 302 重定向——均已修复且保持不回归所有命令按邮箱显示名寻址透明地解析为不透明 id其机制见下文第四节。三、三项关键发现行为与配置非 bugJ1 —envelope search粘连短选项落入查询串envelope search -m A -s20 order by date asc会以cannot parse search emails query \-s20失败原因是该命令带一个**尾部位置参数**[QUERY]...它把粘连的-s20吞进了查询串。而空格形式的-s 20与长选项--page-size 20均正常envelope list没有尾部位置参数-s20 就没有这个问题。从源码看这正是 CLI 定义层的取舍src/shared/envelope/search.rs 中查询参数被声明为#[arg(value_name QUERY)]、allow_hyphen_values true、trailing_var_arg true即从第一个以连字符开头的 token 起全部归入查询——-s20因此被当作查询文本。该命令的parse_queryL125-L144再把词串拼接后交给SearchEmailsQuery解析于是报出查询解析错误。报告结论是这不是 JMAP/逻辑 bug空格形式下排序与分页均正常而是一个 CLI 易用性瑕疵候选的 clap 调整方向是让短选项在trailing_var_arg下不被查询吞掉目前已在文档中标注。J2 — copy/move 计数与无效 idJMAP 比 IMAP 更严格在 JMAP 上Email/set.updated驱动 F2 计数1 message successfully copied等输出正常。但对无效 id行为与 IMAP 不同——IMAP 是静默 no-opJMAP 则直接报错Email/set failed for: id该错误消息来自 src/jmap/backend.rs 的bail_on_not_updated任何Email/set只要notUpdated非空就立即失败并把失败 id 拼进消息。copy_messagesL261-L271与move_messagesL275-L286都在调用后先取updated.len()作为计数、再bail_on_not_updated所以「计数正确 失败即报错」两者兼得。报告评价比 IMAP 的静默 no-op 更严格且是合理的。J3 — JMAP 发送配置自动发现已修复这是本次测试最实质的修复。此前message send/compose --send在只配置了servertoken的最小账号上会失败JMAP identity_id is required to send修复后JMAP 后端在配置缺省时自动回退identity取账号默认身份Identity/get返回的第一个drafts 邮箱取带drafts角色的邮箱Mailbox/get只有在需要固定到特定对象时才显式设置identity_id/drafts_mailbox_id。源码印证在 src/jmap/backend.rs 的send_messageL312-L370上传 blob → 以$draft关键字 import 进 drafts →EmailSubmission/set提交同时用onSuccessUpdateEmail让服务器在发送成功后自动把邮件移入 sent 邮箱、去掉$draft、加上$seenRFC 8621 §7.5。身份与邮箱的解析分别在resolve_identity_idL375-L389与resolve_send_mailbox_idsL398-L425前者在未配置时读Identity/get取首个后者在配置缺失时用一次Mailbox/get扫描drafts/sent角色邮箱drafts 是必需的找不到则明确报错sent 缺省则邮件留在原地。报告验证结论最小server token账号无需额外配置即可message send与compose --send真实投递若账号确实没有 identity 或没有drafts角色邮箱仍会抛出清晰错误。配套原始 API 报告 jmap-specific-fastmail.md 也用jmap submission create --identity-id 178831439 --mail-from … --rcpt-to …实测了真实投递pimalayafastmail.org状态final邮件到达收件箱。日期语义线路上过滤receivedAt客户端再按sentAt复核共享 DSL 的date/after语义是按Date:头sentAt过滤但 JMAP 的Email/query日期条件只能作用于receivedAt二者会差一天。后端的处理是线路上过近似、客户端严格复核src/jmap/backend.rs 的convert_filter把date t翻译成after: 当天 00:00Zutc_midnight、把after t翻译成after: 次日 00:00Z同时各自压入一个PostFilter查询返回后post_match 用 envelope 的sentAt逐条复核date要求sentAt的日期等于目标日after要求大于目标日随后再在客户端做分页裁剪paginateL736-L751。报告用夹具验证了这一语义Gamma 在 16 号date 2026-07-16命中、after 2026-07-16排除——结果跟随Date:头而非服务器到达时间。跨后端一致性还体现在envelope_propertiesL496-L509显式请求SentAt作为信封日期字段。查询索引最终一致性报告还记录了一个观察大批 import 后立即跑纯排序查询曾有一次返回陈旧空结果随后自愈稳定后无法复现。这是 JMAP 服务器查询索引的最终一致性特征并非 himalaya bug。四、源码印证共享命令在 JMAP 上的三条主线1. 按名字寻址邮箱resolve_mailbox_id与邮箱索引缓存共享层所有 JMAP 命令的-m/-f都接受邮箱显示名最终落到不透明 id。机制在 src/jmap/client.rsresolve_mailbox_id通过懒加载的MailboxIndexmailbox_indexL68-L75首次调用时用一次list_mailboxes拉全量并缓存到客户端生命周期把 id/名字/角色统一映射为 id。因此后端所有方法只消费纯 id名字解析被隔离在共享客户端层——这正是报告中「所有命令按名字寻址、透明解析」的源码级答案。2. 信封列表/搜索Email/query链上Email/get一次往返list_envelopesL67-L89与search_envelopesL97-L133都是把Email/query带inMailbox/过滤/排序/positionlimit与Email/get仅取信封属性链在一次往返中完成分页由compute_position_limitL512-L519把共享层 1 起始的(page, page_size)换算成 JMAP 0 起始的(position, limit)。共享查询 DSL 的 from/to/subject/body/flag/and/or/not 在convert_filter中被逐节点翻译成JmapEmailFilter树排序键 date/from/to/subject 映射到SentAt/From/To/Subjectconvert_sorterL718-L734默认排序为sentAt降序。3. 读信与附件Blob/download与跨主机会话get_messageL174-L216先用Email/get拿blobId再用 session 的下载 URL 模板替换{accountId}/{blobId}/{type}/{name}构造 URL 并download_blob。由于下载端点可能与 API 端点不同主机src/jmap/client.rs 会先比较 authority同主机复用现有会话异主机则用同一份认证配置另开一个客户端会话——这解释了报告中「message read302 重定向修复」与 blob 下载全部通过的原因。flag 操作则映射为 RFC 8621 关键字$seen/$answered/$flagged/$draft…见keyword_fromL477-L492其中store_flagsL137-L170按 Add/Remove/Set 三种操作分别调用set_keyword/unset_keyword/replace_keywords。五、关联原始jmap …API 面配套报告摘要原始报告明确指向配套的 jmap-specific-fastmail.md后者覆盖himalaya jmap …原始方法面query/mailbox/email/thread/identity/submission/vacation-response命令结构见 src/jmap/cli.rs。其三项发现与本文直接相关K1已修复jmap mailbox query曾默认发isSubscribed: true导致未订阅的假邮箱查不到由于原生Mailbox/query不应用订阅过滤默认已翻转为列出全部邮箱--subscribed才显式过滤。源码见 src/jmap/mailbox/query.rs 与过滤构造 L72-L88。K2Fastmail 侧行为Fastmail 不保留EmailSubmission对象——submission create成功投递后稍后在独立会话get/query返回空cancel报notFound且cancel需要undoStatus: pending发送撤销窗口Fastmail 的即时发送从不提供。himalaya 以Email/set failed for: …风格干净地呈现。K3Fastmail 侧行为VacationResponse/get返回 HTTP 403Fastmail 未向该 token 授予urn:ietf:params:jmap:vacationresponse能力himalaya 报Vacation response is not supported by the server未泄漏原始 403。该报告还留下一则运维提醒identity/mailbox 创建类测试必须自清理——测试账号上曾累积 32 个遗留测试身份已删除。六、配置参考最小账号如何配置 JMAP 发送J3 修复后JMAP 账号的最小配置只需server 认证。完整可选字段在 config.sample.toml 与 src/config.rsJmapConfig中定义# JMAP 服务器裸 authority 会走 GET /.well-known/jmap 发现 # 完整 URL 直达 session 端点。 jmap.server https://api.fastmail.com/jmap/session # 或 jmap.server fastmail.com # TLS镜像 imap.tls 块 #jmap.tls.provider rustls #jmap.tls.rustls.crypto ring #jmap.tls.cert /path/to/custom/cert.pem # ALPN默认 [http/1.1]JMAP 走 HTTP/1.1空列表跳过 ALPN #jmap.alpn [http/1.1] # 认证三选一exactly one of header / bearer / basic jmap.auth.bearer.token.command [ortie, token, show, -a, fastmail] #jmap.auth.header.raw Bearer eyJhbGciOiJ... #jmap.auth.basic.username userexample.com #jmap.auth.basic.password.command pass show fastmail # 发送相关均可不设J3 自动发现 # 提交所用的 identity缺省取 himalaya jmap identity get 的第一个 #jmap.identity-id I0123abc # 发送前暂存邮箱缺省取 drafts 角色邮箱jmap mailbox query --role drafts #jmap.drafts-mailbox-id M0123abc # 发送后归档邮箱缺省取 sent 角色邮箱无 sent 角色时邮件留在 drafts #jmap.sent-mailbox-id M4567def源码侧对应parse_server_urlsrc/jmap/client.rs接受完整http(s)://URL、裸host:port或裸host后两者默认https://jmap_http_authL169-L188把Header/Bearer/Basic三种认证统一转成Authorization头凭据经SecretResolver解析同一命令在多个配置块出现时只执行一次。七、结论报告的 Verdict 是共享命令在 JMAP 上「solid and release-ready」——每个命令与 flag 都可用邮箱按名字经 id 解析器寻址表格 JSON 输出正确错误干净无功能性阻塞。三项发现中J1 是 CLI 易用性小瑕疵已留档候选 clap 调整J3 是实质性修复——JMAP 发送现可在最小 server token 账号上通过自动发现 identity 与 drafts 邮箱完成。若要在自己的 Fastmail 账号上复现这套验证可按 provider-test-plan.md 的清单逐命令执行假邮箱、双邮箱、留唯一主题标记、测后清理并对照本文第五节关联的原始 API 报告覆盖himalaya jmap …方法面更完整的后端状态概览见 cairn/spec/testing/README.md。赞分享CLI【免费下载链接】himalayaCLI to manage emails项目地址https://gitcode.com/gh_mirrors/hi/himalaya点击查看免费下载相关推荐Himalaya CLI 在 Fastmail 上的 JMAP 特定 API 实测报告raw himalaya jmap … 全命令面验证Himalaya CLI 在 Fastmail 上的 JMAP 特定 API 实测报告raw himalaya jmap … 全命令面验证 本篇技术指南基于CLIHimalaya CLI 的 Microsoft Graph 后端实战共享命令与 msgraph 原始 API 的 Outlook 测试报告解读Himalaya CLI 的 Microsoft Graph 后端实战共享命令与 msgraph 原始 API 的 Outlook 测试报告解读 导读 本文基CLIDataGrip 连接 StarRocks 完整指南JDBC 驱动与 MySQL 驱动两种接法DataGrip 连接 StarRocks 完整指南JDBC 驱动与 MySQL 驱动两种接法 在 DataGrip 里接入 StarRocks 之后你能直CLI上一篇NHSE终极指南5步掌握动物森友会存档编辑的艺术下一篇动物森友会存档编辑器终极指南NHSE让你的岛屿创意无限创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑