我几个月前刚刚处理了这个问题。 我为我所工作的产品添加了电子邮件功能,包括发送和接收。 第一部分是向用户发送提醒,但我们不想为我们的客户管理员管理反弹消息,因此我们决定拥有一个消息收件箱,管理员可以在没有我们的情况下查看反弹和回复,并且管理员可以调整电子邮件地址,如果需要的话。
因此,我们接受所有发送到我们监视的收件箱的电子邮件。 我们使用
VERP将电子邮件与用户关联,并将整个电子邮件存储在数据库中。 然后,当管理员请求查看电子邮件时,我们必须解析电子邮件。
我的第一次尝试与早期答案非常相似。如果其中一个部分是html,则显示它。如果是文本,则显示它。否则,显示原始的、未经处理的电子邮件。但这在几封不是由sendmail生成的电子邮件中很快崩溃了。Outlook、Exchange和其他几个电子邮件系统不会这样做,它们使用多部分来发送电子邮件。经过大量挖掘和咒骂,我发现问题似乎没有被很好地记录下来。通过查看MHonArc并阅读RFC(RFC2045和RFC2046),我最终选择了下面的解决方案。我决定不使用MHonArc,因为我无法轻松地重用解析和显示功能。我不会说这是完美的,但它已经足够好,我们使用它。
首先,取得消息并使用Email::MIME进行解析。然后使用Email::MIME给出的parts()数组调用名为get_part的函数。
对于每个传递的部分,get_part解码内容类型,在哈希表中查找它,如果存在,则调用与该内容类型相关联的函数。如果解码器能够给我们一些东西,则将其放入结果数组中。
这个解码器数组是拼图的最后一块。基本上,它定义了我可以处理的内容类型:
- text/html
- text/plain
- message/delivery-status(实际上也是纯文本)
- multipart/mixed
- multipart/related
- multipart/alternative
对于非多部分的节,我原样返回。对于混合、相关和替代,我只需在该 MIME 节点上调用 get_parts 并返回结果。因为替代很特殊,所以在调用 get_parts 后还有一些额外的代码。如果它有一个 HTML 部分,它将仅返回 html,或者如果它有一个文本部分,它将仅返回文本部分。如果两者都没有,它将不会返回任何有效内容。
使用有效内容类型的哈希表的优点是,我可以根据需要轻松添加更多部分的逻辑。并且在完成 get_parts 时,您应该拥有所有感兴趣的内容的数组。
还有一件事需要提到的是,作为其中的一部分,我们创建了一个单独的域来提供这些消息。管理员工作的主要域将拒绝提供该消息并将浏览器重定向到我们的用户内容域。第二个域仅提供用户内容。这是为了帮助浏览器将内容正确地隔离在我们的主域之外。请参阅同源策略(http://en.wikipedia.org/wiki/Same_origin_policy)。