在电子邮件开发与自动化处理领域,一个长期困扰程序员的技术细节再度引发热议:当我们需要从HTML邮件正文中自动移除被回复或引用的历史内容时,正则表达式(regex)能否胜任跨客户端的“清洁工作”?日前,一封标题为《Stripping quoted/replied content from HTML email bodies across clients with regex. which markers am I missing and where will it break?》的技术讨论帖在开发者社区引起广泛关注。该问题直击邮件解析工具的核心痛点——不同邮件客户端对引用内容采用了迥异的标记方式,导致通用的正则匹配策略频频失效。

背景:为何要剥离引用内容?

在邮件自动化、客服系统、归档分析或内容抓取等场景中,程序需要获取邮件正文的“最新”部分,而自动剥离用户回复时携带的原始邮件引用(quoted/replied content)是第一步。例如,一个客服工单系统若将整个对话历史都存入标题字段,不仅会淹没关键问题,还会影响搜索与统计。然而,现实中的邮件正文往往是多轮往复的嵌套引用,格式从纯文本的“>”前缀,到HTML的块级元素包裹(如<blockquote><div class="gmail_quote">),再到Outlook特有的MIME标记,其混乱程度远超想象。

挑战:各客户端“各怀鬼胎”

发起该讨论的开发者坦言,他目前的正则表达式已经能够覆盖Gmail、Yahoo Mail、Outlook Web App中常见的引用标记,包括:

  • Gmail:<div class="gmail_quote">及后续的<blockquote>嵌套;
  • Outlook桌面版:使用MIME结构中的<div class="OutlookMessageHeader"><hr>分隔线;
  • Apple Mail:采用<blockquote type="cite">
  • 纯文本引用:以“>”或“|”开头的行。

但问题在于:漏网之鱼太多。例如:

  • 微软Outlook 365:新版本开始使用<div class="x_gmail_quote">等动态类名,无法通过固定类名匹配;
  • Thunderbird:允许用户自定义引用前缀,常规regex无法预判;
  • 移动端邮件应用:如iOS Mail有时不插入HTML标记,仅通过换行与灰色背景区分;
  • 非英文环境:法语的“Le ... a écrit :”、日语的“--- 元のメッセージ ---”等语言变体,regex根本无法硬编码所有语言。

痛点:正则的边界在哪里?

资深邮件协议工程师李光(化名)表示,正则表达式适合处理结构化、模式稳定的文本,但跨客户端的邮件引用正是典型的“非结构化”数据。“你不可能用一行regex同时匹配<div class="gmail_quote">和来自Samsung电子邮件客户端的<div style="padding-left:5px; border-left:solid 2px #cccccc;">——前者是类名,后者是内联样式。”他补充道,更棘手的是不同地域、不同版本的邮件客户端会穿插使用<style>标签定义引用块,甚至将引用内容隐藏在<!-- -->注释中,导致regex彻底失效。

该讨论帖下,多位开发者分享了各自的“翻车”经历:有人因为忽略了对<div>标签递归深度的限制,导致正则误删了正文中的<blockquote>引用(如用于引述名人名言);有人则因点号(.)默认不匹配换行符,错过了多行引用头;还有人发现,某些邮件服务商会将引用内容以纯文本base64编码的形式嵌入,根本无法肉眼识别。

业界方案:正则并非终点

面对这一困境,业界已有一些相对成熟的应对策略。知名PHP邮件处理库EmailReplyParser(源于GitHub的Markdown引擎)采用分层解析:先通过MIME结构分离HTML与纯文本部分,再结合启发式规则(如检测缩进深度、查找“On ... wrote:”等常见模式)进行剥离。类似的思路在Python的mail-parser、Node.js的node-email-reply-parser中也有体现。

但即便如此,这些库仍然无法保证100%准确。邮件客户端迭代速度太快,Google在2021年将Gmail引用块的<div class="gmail_quote">改为<div data-smartmail="gmail_quote">,导致旧版库集体失效。有开发者调侃:“每当你认为自己写了一个足够健壮的正则,某个邮件客户端就会出一个新特性来打脸。”

展望:AI能否破局?

随着自然语言处理技术的发展,部分团队开始尝试使用机器学习模型来判断哪一部分属于“新”内容。例如,通过训练一个序列分类器,对邮件正文的每一个段落或句子打上“original”或“quoted”标签。但这种方法需要大量标注数据,且因隐私问题难以收集,目前仍停留在实验室阶段。

对于大多数开发者而言,当下最务实的做法依然是:维护一个可扩展的、由多个正则组成的规则列表,并结合常见客户端的用户代理(User-Agent)做针对性预处理。同时,在重要场景下应保留人工校验接口——毕竟,机器永远无法完全理解一封邮件中“引用”与“正文”的模糊边界。

正如该讨论帖作者在结尾所言:“如果你发现一个正则能够完美处理所有邮件,请务必告诉我——我会把它加入我的墓碑铭文。”在这场与邮件引用格式的持久战中,正则或许只是初级武器,但也是每个开发者不得不拿起的“瑞士军刀”。