ARTICLE DETAIL

资讯详情

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

himalaya 收件人参数支持 RFC 5322 地址列表:`--to`/`--cc`/`--bcc` 从“按逗号切分“到“整表解析“的升级

himalaya 收件人参数支持 RFC 5322 地址列表:`--to`/`--cc`/`--bcc` 从“按逗号切分“到“整表解析“的升级 CLI【免费下载链接】himalayaCLI to manage emails项目地址https://gitcode.com/gh_mirrors/hi/himalaya点击查看免费下载本篇技术指南讲解 himalaya 命令行邮件客户端在 2026-09-26 落地的一项行为修正message compose、reply、forward三个命令的--to、--cc、--bcc收件人参数不再由 CLI 自行按逗号切分而是把每个参数值整体当作一个 RFC 5322 地址列表交给解析器完整保留其中每一个邮箱及显示名。读完本文你将理解该变更的背景、底层解析实现、测试验证方式以及在实际命令行中如何正确书写带显示名尤其是显示名内含逗号的收件人。变更背景两次回归一条主线本次变更cairn 日志 2026-09-26-compose-recipient-address-list.md是前一天变更compose-recipient-display-name见 2026-09-26-compose-recipient-display-name.md的后续修复两者解决的是同一个问题的两个层面显示名被错误塞进尖括号此前message compose、reply、forward把每个--to/--cc/--bcc值当作裸地址直接交给 MIME 构造器于是--to Alice aliceexample.org会生成To: Alice aliceexample.org——这种畸形头没有任何 SMTP 服务器会接受。该问题最初在发送方--from上报并修复issue #727随后收件人侧也统一接入同样的邮箱解析逻辑。CLI 预切分把带逗号的显示名劈成两半修复显示名之后暴露出的下一个问题——CLI 在把参数交给解析器之前先用逗号把--to/--cc/--bcc的值拆开。于是Doe, Alice aliceexample.org显示名中含逗号会被劈成Doe和Alice aliceexample.org两个残缺片段解析自然失败。两次修复的原则一致格式问题交给专门的地址解析器处理CLI 层不做字符串级猜测。变更说明中特别标注 Spec unchanged即命令行规范没有变化这是一次纯实现层面的修正。核心变更每个值整体按 RFC 5322 地址列表解析变更后的规则可以概括为三点--to、--cc、--bcc不再自行按逗号切分值每个值被当作一个完整的 RFC 5322 地址列表来解析值中携带的每一个邮箱mailbox都会被保留无论它出现在列表的哪个位置因此两种既有写法都继续有效重复使用 flag--to ax --to by与单个值内逗号分隔--to ax, by。换句话说分隔收件人这件事从CLI 替你做变成了解析器按标准做——只有参数值之间的区分是 flag 重复值内部的多个邮箱则由 RFC 5322 语法负责。三个命令的参数定义--to/--cc/--bcc在三个命令中都是可重复的VecString参数名与含义完全一致参数简写含义--to ADDR-t主要收件人flag 可重复或携带逗号分隔列表--cc ADDR—抄送收件人--bcc ADDR—密送收件人具体定义见 compose.rs、reply.rs 和 forward.rs 中pub to: VecString、pub cc: VecString、pub bcc: VecString的#[arg(long, value_name ADDR)]声明。三个命令最终把各自的VecString原样塞进共享的BuilderArgs见 builder.rs 的to、cc、bcc字段由同一个builder::build函数处理因此修复一处三个命令同时生效。底层实现parse_mailboxes与addresses两级解析真正的解析逻辑位于共享构造器 builder.rs包含两个关键函数。第一级parse_mailboxes—— 单个值的地址列表解析parse_mailboxes(value)负责把一个字符串值解析成(OptionString, String)列表显示名 邮箱// NOTE: the header parser flushes its last token on the // terminating newline, which a bare address, unlike one closed by // a , does not otherwise carry. let header format!({value}\n); let parsed MessageStream::new(header.as_bytes()).parse_address(); let mailboxes: Vec_ match parsed { HeaderValue::Address(ParserAddress::List(list)) list.iter().collect(), HeaderValue::Address(ParserAddress::Group(groups)) groups .iter() .flat_map(|group| group.addresses.iter()) .collect(), _ Vec::new(), }; if mailboxes.is_empty() { bail!(Could not parse address {value}); }几个值得注意的实现细节末尾补\nmail-parser 的地址解析器在遇到终止换行时才冲刷最后一个 token。裸地址没有收尾不会自带换行补一个\n才能保证它被完整解析同时处理 List 与 GroupHeaderValue::Address既有普通地址列表List也有 RFC 5322 的地址组Group形如GroupName: ax, by;群组内的地址会被flat_map展开每个 mailbox 拆出 name 和 addressmailbox.address缺失即值中没有邮箱时返回明确的错误Address{value}has no email而不是默默生成非法头。第二级addresses—— 跨值汇总成一个地址列表addresses(values)把用户传入的多个值串成一个mail_builder::headers::address::Address列表fn addresses(values: [String]) - ResultAddressstatic { let mut list Vec::new(); for value in values { for (name, address) in parse_mailboxes(value)? { list.push(Address::new_address(name, address)); } } Ok(Address::new_list(list)) }外层for value in values对应flag 可重复的写法内层for (name, address) in parse_mailboxes(value)对应单值内逗号分隔的写法。两层循环的结果合并成一个列表交给mail_builder这就是重复 flag 与ax, by两种写法都仍然工作的代码依据。build()中对三个头分别调用见 builder.rsif !args.to.is_empty() { builder builder.to(addresses(args.to)?); } if !args.cc.is_empty() { builder builder.cc(addresses(args.cc)?); } if !args.bcc.is_empty() { builder builder.bcc(addresses(args.bcc)?); }与--from的同一套解析发送方--from走的是同一个parse_mailboxes只是取第一个邮箱parse_mailboxes(from)?.remove(0)显示名拆出后与账户配置的display-name合并传给mail_builder的Address::new_address。也就是说从本次变更起收件人与发件人共用同一套 RFC 5322 地址解析规则行为完全对齐。命令行实战显示名内含逗号怎么写核心问题场景是显示名本身含逗号西方姓, 名写法很常见如Doe, Alice。RFC 5322 规定这类显示名必须用引号包裹变更后的解析器能正确处理# 带引号的显示名含逗号单值内多个收件人 himalaya message compose \ --to Doe, Alice aliceexample.org, bobexample.org \ --cc carolexample.org # 重复 flag 与逗号列表混用效果等同 himalaya message compose \ --to Doe, Alice aliceexample.org \ --to bobexample.org, carolexample.org两种写法最终都会生成合法的To:头例如To: Doe, Alice aliceexample.org, bobexample.org, carolexample.org注意不要在引号包裹的显示名外加反斜杠或额外转义引号本身即是 RFC 5322 的合法语法也不要在引号外再用逗号手动切分显示名。非 ASCII 显示名同样支持——解析器能识别 RFC 2047 编码如?utf-8?B?QWxpY2U? aliceexample.org见下文测试用例。测试验证源码级证据builder.rs 的测试模块直接对应本次变更可作为行为契约compose_to_keeps_every_mailbox_of_every_value输入\Doe, Alice\ aliceexample.org, bobexample.org与carolexample.org两个值断言最终To:包含 3 个收件人且Doe, Alice的显示名与aliceexample.org地址完整保留——这正是每个值解析为地址列表、每个 mailbox 都保留的回归测试compose_to_keeps_a_spelled_out_display_name_apart断言输出中不会出现Alice aliceexample.org这种畸形嵌套回归的是显示名修复那一层parse_mailboxes_splits_name_and_address覆盖纯地址、Alice aliceexample.org、带引号逗号显示名、RFC 2047 编码显示名、单值多邮箱以及not-an-address与空字符串被拒绝的错误分支。边界与兼容性结论无效输入报错更清晰某个值解析不出任何邮箱如not-an-address或邮箱缺失时命令直接报Could not parse address .../... has no email不再产出不可发送的畸形头reply的自动收件人不受影响当--to为空时reply仍会从源邮件的Reply-To没有则From自动推导收件人见 builder.rs 的reply_recipients显式--to优先覆盖对已存在脚本完全向后兼容既有的重复 flag 写法与单值逗号分隔写法输出不变唯一的行为变化是带逗号显示名的值从报错/生成畸形头变为正确解析仅涉及三个共享命令compose、reply、forward共用同一个构造器本次修复自动覆盖全部三个命令命令行规范Spec未做任何改动。如果你想查看本次变更的完整上下文可以继续阅读同日的姊妹日志 compose-recipient-display-name.md以及共享构造器源码 builder.rs 中parse_mailboxes、addresses两个函数及其测试用例。赞分享CLI【免费下载链接】himalayaCLI to manage emails项目地址https://gitcode.com/gh_mirrors/hi/himalaya点击查看免费下载相关推荐himalaya 共享 Envelope 的 In-Reply-To 支持让邮件列表一次 FETCH 就能配对回复与父邮件himalaya 共享 Envelope 的 In Reply To 支持让邮件列表一次 FETCH 就能配对回复与父邮件 In Reply To 是 RFCCLIHimalaya 的 imap fetch --body基于 BODY.PEEK[] 的单会话批量拉取整封邮件RFC 5322 原始字节Himalaya 的 imap fetch body 基于 BODY.PEEK 的单会话批量拉取整封邮件RFC 5322 原始字节 本篇技术指南以 HimCLIAttu项目登录页增强支持Milvus地址选择列表功能解析Attu项目登录页增强支持Milvus地址选择列表功能解析 在分布式向量数据库管理领域Attu作为Milvus的官方可视化工具近期针对多实例管理场景进行了上一篇WindowResizer免费强制修改窗口尺寸3分钟搞定拖不动的窗口下一篇艾尔登法环单角色存档迁移5分钟搞定用EldenRingSaveCopier安全移植一个角色创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表