【问题标题】:Format Email Reply in Ruby用 Ruby 格式化电子邮件回复
【发布时间】:2017-01-25 21:38:06
【问题描述】:

我正在用 ruby​​ 制作自己的电子邮件客户端,它目前可以解析/读入消息。它还可以创建对消息的回复、设置标题并将消息发送给原始发件人。

如何将原始引用的消息添加到回复中?

我应该如何格式化回复中的原始消息?是否有最佳实践或格式? MIME/RFC?我知道应该有一个用于 HTML 和文本的字符串。只是不确定如何制作这些字符串。

现在我的回复没有下面的原始消息,并且很难理解。

【问题讨论】:

    标签: ruby-on-rails ruby email actionmailer mime


    【解决方案1】:

    撰写电子邮件回复是一项相当大的挑战,尤其是在您不知道从哪里开始的一开始。

    最近我不得不撰写此类电子邮件并以编程方式发送它们。我首先做的是看看电子邮件客户端是如何做到这一点的,比如 Thunderbird。不过,这需要一些实验和耐心。

    我使用的消息的整体结构很大程度上基于这个 Stack Overflow 答案:https://stackoverflow.com/a/23853079/1368043


    1。 HTML部分

    请注意,您几乎没有选择:编写 HTML 片段(典型 <body> 标记的内容)或整个 HTML 文档(带有 <html><head><body> 标记)。我看了一下 Thunderbird 是如何做到的。结果它创建了整个文档,大致如下生成:

    1. 创建 HTML 文档
    2. <head> 部分添加元信息<meta content="text/html; charset=utf-8" http-equiv="Content-Type">(将字符集替换为您喜欢的字符集)
    3. <body> 部分添加您编写的HTML 片段,添加引用的标题(如:“<div>Few days ago, John Smith wrote: </div>”)并在其后添加<blockquote> 块:<blockquote cite="mid:originalmessagemid@example.com" type="cite">。请注意,有一个原始消息的消息 ID。

    这是我不太喜欢 Thunderbird 的部分:

    1. 复制原始邮件的 HTML 内容并将其粘贴到 <blockquote> 块中。

    Thunderbird 并不真正检查复制的 HTML 是片段还是文档。但是,如果它是一个文档,它会去除 <html><head> 标记......同时保留它们的内容。结果,您可以从位于新消息的<body> 标记中的原始消息的<head> 部分看到<style><title> 标记。太乱了。

    此外,Thunderbird 无法处理全局样式。您可以使用全局样式而不是内联样式轻松撰写一封棘手的邮件,并且当邮件的收件人开始撰写回复时,样式会覆盖整个邮件。


    你可以做同样的事情。它并没有真正伤害任何人,它们是典型的邮件通常不会观察到的怪癖。另外这很容易。或者你可以走得更远一点,收拾这个烂摊子。

    首先,您必须让自己获得任何 HTML 解析器。我用的是Nokogiri,我的使用方式是这样的:

    1. 它会自动将任何片段转换为 HTML 文档,因此无需单独分析片段和文档
    2. 在文档中找到<body>标签并复制其内容
    3. 删除您找到的任何<style> 标签
    4. 将结果复制到需要的地方

    大概是这样的:

    doc = Nokogiri::HTML.parse(strHTML)
    body = doc.css('body')[0]
    body.css('style').each { |node|
        node.unlink
    }
    
    puts body.inner_html
    

    Nokogiri 还有一个好处 - 如果您在 HTML 消息中有任何内嵌图像,您可以轻松找到它们,将 URL 替换为“cid:...”方案并将图像添加为内嵌附件。


    2。纯文本部分

    是的,multipart/alternative 部分中还有邮件的纯文本版本。这里最关键的过程是将任何 HTML 文本转换为纯文本版本的能力。这比编写 HTML 部分还要棘手。毕竟,您必须编写一个简单的渲染引擎(就像任何其他 Web 浏览器一样)。可能有宝石,可惜我当时找不到。

    尽管有几个要点可以帮助您入门:

    • 应将所有换行符(\r\n 或 \n)替换为单个空格
    • 所有多个空格都应减少为一个(除非它们是不间断的)
    • 某些标签会保留内容,而其他标签则不会(例如 <style><script> 标签 vs <b><div>
    • 某些标签后面需要换行符(<br> 和块标签,例如 <p><div>
    • 您必须正确格式化表格。您必须计算列的宽度,考虑colspans 和rowspans,用空格填充单元格的内容以对齐它们等。
    • 你必须为<b><i>、...标签找到替代标记(比如用星号或诸如此类的东西包围它们)
    • 您还可以格式化标题:<h1><h2>、... 通过在它们下方和/或上方添加破折号或星号行
    • 您必须正确格式化 <a> 标签,即将它们转换为以下格式:Stack Overflow site [http://stackoverflow.com]
    • 您必须丢弃 <img> 标记,并可能将它们替换为替代文本(如果存在)
    • 您还必须解码 HTML 实体(> 等)。如果不是 Nokogiri,HTMLEntities gem 可能会在这种情况下有所帮助

    列表可以继续。当然没必要

    互联网上有一些库和项目可以做到这一点,但是它们不是为 Ruby 编写的,并且/或者它们缺少上面列出的一些功能。例如:


    一旦你把它排除在外,text/plain 部分的结构实际上与 HTML 部分相同。一开始就有你的回复。然后是引用标题,然后是引用的消息。它通常被格式化,以便每一行都以'>'字符开头。现在,有一个问题是您应该在其中粘贴什么。

    第一个选项是转换原始消息的 HTML 部分(通过上述方法)并将其粘贴为引用消息。其次是使用原始消息的text/plain 部分(如果存在)并粘贴它而不进行任何转换。后一个选项的好处是,长时间对话中的“>”字符将在一段时间后以树状方式累积。此外,它还保留了发件人可能手动组装的纯文本格式,以使其更准确。


    3。总结

    根据您的实际需求和您想要达到的质量水平,撰写此类邮件的难度可能从简单/棘手到困难不等,尤其是在您必须自己编写所有代码的情况下。如果您碰巧发现任何 Ruby gem 至少可以帮助您完成其中一些任务,请不要犹豫并使用它们。

    编写 HTML 部分可以像复制和粘贴 HTML 片段一样简单,最好预先去除一些标签。编写纯文本部分可以像完全删除几个标签一样简单(<head><script><style>,...),剥离所有标签,同时保留其内容并按顺序解码所有 HTML 实体。

    可以使用正则表达式删除 HTML 标记,但它是 strongly discouraged,被认为是穷人工具箱中的工具。所以我建议为此目的使用 Nokogiri 或类似的东西。

    虽然这不是问题的一部分,但我必须强调编写电子邮件客户端的一个方面。您应该始终记住清理您的 HTML 消息,尤其是您收到的那些。传入邮件中看起来可疑的 iframe 或脚本没有什么好处,如果没有立即被垃圾邮件过滤器阻止/过滤,它们可能是 XSS 攻击的一部分。在这种情况下,Sanitize gem 可能很有用。

    干杯

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-23
      • 1970-01-01
      • 1970-01-01
      • 2020-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多