【问题标题】:Parse and display MIME multipart email on website在网站上解析和显示 MIME 多部分电子邮件
【发布时间】:2011-03-05 09:13:35
【问题描述】:

我有一封原始电子邮件(MIME 多部分),我想在网站上显示它(例如,在 iframe 中,带有 HTML 部分和纯文本部分的选项卡等)。是否有任何 CPAN 模块或 Template::Toolkit 插件可以用来帮助我实现这一目标?

目前,我似乎必须使用 Email::MIME 解析消息,然后遍历所有部分,并为所有不同的 mime 类型编写处理程序。

这是一个漫长的过程,但我想知道是否有人已经完成了这一切?如果我自己尝试编写处理程序,这将是一个漫长且容易出错的过程。

感谢您的帮助。

【问题讨论】:

标签: perl email mime cpan template-toolkit


【解决方案1】:

实际上我几个月前才处理过这个问题。我为我工作的产品添加了电子邮件功能,包括发送和接收。第一部分是向用户发送提醒,但我们不想为客户管理员管理退回邮件,我们决定有一个消息收件箱,管理员可以在没有我们的情况下看到退回邮件和回复,并且管理员可以处理调整电子邮件地址(如果需要)。

因此,我们接受发送到我们查看的收件箱的所有电子邮件。我们使用VERP 将电子邮件与用户相关联,并将整个电子邮件按原样存储在数据库中。然后,当管理员请求查看邮件时,我们必须解析邮件。

我的第一次尝试与之前的答案非常相似。如果其中一个部分是 html,则显示它。如果是文本,请显示它。否则,请显示原始的原始电子邮件。一些不是由 sendmail 生成的电子邮件很快就崩溃了。 Outlook、Exchange 和其他一些电子邮件系统不这样做,它们使用多部分来发送电子邮件。经过大量的挖掘和诅咒,我发现这个问题似乎没有得到很好的记录。在查看 MHonArc 并阅读 RFC(RFC2045 和 RFC2046)的帮助下,我确定了以下解决方案。我决定不使用 MHonArc,因为我不能轻易地重用解析和显示功能。我不会说这是完美的,但我们使用它已经足够好了。

首先,获取消息并使用 Email::MIME 对其进行解析。然后调用一个名为 get_part 的函数,其中包含 Email::MIME 为您提供的部分数组 ->parts()。

get_part,对于它被传递的每个部分,解码内容类型,在哈希中查找它,如果存在,则调用与该内容类型关联的函数。如果解码器能够给我们一些东西,把它放在一个结果数组中。

最后一块拼图是这个解码器数组。基本上,它定义了我可以处理的内容类型:

  • 文本/html
  • 文本/纯文本
  • message/delivery-status,其实也是纯文本
  • 多部分/混合
  • 多部分/相关
  • 多部分/替代

我原样返回的非多部分部分。通过混合、相关和替代,我只需在该 MIME 节点上调用 get_parts 并返回结果。因为alternative 比较特殊,所以在调用get_parts 之后有一些额外的代码。如果它有一个 html 部分,它只会返回 html,或者它只会返回它的文本部分,它有一个文本部分。如果两者都没有,它不会返回任何有效的东西。

有效内容类型散列的优点是我可以根据需要轻松为更多部分添加逻辑。当你 get_parts 完成时,你应该有一个你关心的所有内容的数组。

我应该再提一个项目。作为其中的一部分,我们创建了一个单独的域来实际提供这些消息。管理员工作的主域将拒绝提供消息并将浏览器重定向到我们的用户内容域。第二个域将只提供用户内容。这是为了帮助浏览器正确地将内容从我们的主域中分离出来。查看同源策略 (http://en.wikipedia.org/wiki/Same_origin_policy)

【讨论】:

    【解决方案2】:

    对我来说这听起来并不困难:

    use Email::MIME;
    my $parsed = Email::MIME->new($message);
    my @parts = $parsed->parts; # These will be Email::MIME objects, too.
    print <<EOF;
    <html><head><title>!</title></head><body>
    EOF
    for my $part (@parts) {    
        my $content_type = $parsed->content_type;
        if ($content_type eq "text/plain") {
             print "<pre>", $part->body (), "</pre>\n";
        }
        elsif ($content_type eq "text/html") {
            print $part->body ();
        }        
        # Handle some more cases here
    }
    print <<EOF;
    </body></html>
    EOF
    

    【讨论】:

    • 您需要对其进行消毒。您不想让电子邮件将任意 JS 注入您的网站!
    • 更不用说在文本/纯文本部分编码实体了。
    • 对我来说听起来仍然不是什么大工作。实体如此艰难:s/([&lt;&gt;&amp;])/"&amp;#".ord($1).";"/ge 和 HTML 清理通过 HTML::Scrubber
    • 这就是我打算做的,但我担心的是“在这里处理更多案件”。我对 MIME 多部分和所有不同类型的了解不够多,因此不会搞砸。我想将附件显示为回形针等...但也许我过于偏执...谢谢您的帮助。
    • 很好的答案。代码中有几个小错误。应该是 $content_type = $part->content_type(未解析->content_type)。此外,使用正则表达式匹配 content_type ($content_type =~ m/text\/plain/) 而不是字符串比较,因为可能存在字符集。
    【解决方案3】:

    重复使用现有的完整软件。 MHonArc mail-to-HTML converter 具有出色的 MIME 支持。

    【讨论】:

    • 这可能正是我真正想要的。将调查...谢谢。
    猜你喜欢
    • 2016-10-05
    • 2015-06-09
    • 2011-02-13
    • 2021-01-11
    • 1970-01-01
    • 1970-01-01
    • 2016-06-04
    • 1970-01-01
    • 2014-11-08
    相关资源
    最近更新 更多