撰写电子邮件回复是一项相当大的挑战,尤其是在您不知道从哪里开始的一开始。
最近我不得不撰写此类电子邮件并以编程方式发送它们。我首先做的是看看电子邮件客户端是如何做到这一点的,比如 Thunderbird。不过,这需要一些实验和耐心。
我使用的消息的整体结构很大程度上基于这个 Stack Overflow 答案:https://stackoverflow.com/a/23853079/1368043
1。 HTML部分
请注意,您几乎没有选择:编写 HTML 片段(典型 <body> 标记的内容)或整个 HTML 文档(带有 <html>、<head> 和 <body> 标记)。我看了一下 Thunderbird 是如何做到的。结果它创建了整个文档,大致如下生成:
- 创建 HTML 文档
- 在
<head> 部分添加元信息<meta content="text/html; charset=utf-8" http-equiv="Content-Type">(将字符集替换为您喜欢的字符集)
- 在
<body> 部分添加您编写的HTML 片段,添加引用的标题(如:“<div>Few days ago, John Smith wrote: </div>”)并在其后添加<blockquote> 块:<blockquote cite="mid:originalmessagemid@example.com" type="cite">。请注意,有一个原始消息的消息 ID。
这是我不太喜欢 Thunderbird 的部分:
- 复制原始邮件的 HTML 内容并将其粘贴到
<blockquote> 块中。
Thunderbird 并不真正检查复制的 HTML 是片段还是文档。但是,如果它是一个文档,它会去除 <html> 和 <head> 标记......同时保留它们的内容。结果,您可以从位于新消息的<body> 标记中的原始消息的<head> 部分看到<style> 和<title> 标记。太乱了。
此外,Thunderbird 无法处理全局样式。您可以使用全局样式而不是内联样式轻松撰写一封棘手的邮件,并且当邮件的收件人开始撰写回复时,样式会覆盖整个邮件。
你可以做同样的事情。它并没有真正伤害任何人,它们是典型的邮件通常不会观察到的怪癖。另外这很容易。或者你可以走得更远一点,收拾这个烂摊子。
首先,您必须让自己获得任何 HTML 解析器。我用的是Nokogiri,我的使用方式是这样的:
- 它会自动将任何片段转换为 HTML 文档,因此无需单独分析片段和文档
- 在文档中找到
<body>标签并复制其内容
- 删除您找到的任何
<style> 标签
- 将结果复制到需要的地方
大概是这样的:
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 实体(
&gt; 等)。如果不是 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 可能很有用。
干杯