在PHP中处理电子邮件解析/解码的最佳方法是什么?

28

目前我正在使用PEAR库中的mimeDecode.php解析传入的电子邮件。它似乎有很多问题,并且无法解码许多消息,因此我想用更好的东西来替换它。

我正在寻找一些能够正确分离消息各个部分(例如收件人、发件人、正文等)的东西。理想情况下,它应该能够处理常见的编码方法,如base64、uuencode、quoted printable等。

在单个电子邮件中包含纯文本和HTML版本的情况下,我希望它知道它们之间的区别,这样我就可以选择显示哪一部分。

我目前不担心附件,但如果将来想要实现它,了解它们会很好。

我看到PHP有一组以imap开头的函数,似乎可以做我想要的事情,但我没有试过,不确定。

目前我正在PHP中进行消息即时解码,这就是为什么我正在寻找PHP替代方案的原因。

是否有任何人有这方面的经验,可以指导我朝着正确的方向前进?我不想开始使用最终不能满足我的需求的东西。

6个回答

13

1
它的附件处理不好-它在HTML正文内包含了base64编码的附件内容。 并且没有getAttachment()这样的函数。 - Slawa
1
感谢您报告错误,Slawa - 我会调查一下。 如果您需要提取附件,我建议您尝试使用 http://code.google.com/p/php-mime-mail-parser/。 - Dan
绝对棒的库 - 对我所需完美无缺。 - ChicagoSky
1
这很棒,但事实证明它无法处理更复杂的邮件结构。我发现一种情况,其中电子邮件具有一个边界值来将附件与文本/HTML正文分开,然后使用不同的边界值拆分文本和HTML正文部分... 这就是无法处理的。 - phoenix

8

我知道这个问题已经四年了...但是我最终需要使用一个邮件解析库,而且我对所有可用的选项都不满意。我想要一些可靠的、符合PSR-2标准的、可以通过composer安装的东西。

composer require zbateson/mail-mime-parser

这是一个自己构建的解析器,从头开始处理其他实现中已知的问题和错误。它经过了广泛的测试并被广泛使用。

该库利用Psr7流,允许您传递任何类型的流。它也不会将所有信息存储在内存中 -- 如果需要,非常大的附件可以作为流而不是字符串返回,因此不会使用内存。同样,整个消息从未直接存储在内存中,只有对流的引用,并且标头保留在内存中。

https://github.com/zbateson/mail-mime-parser

请查看网站以获取指南和API...如果您发现错误/错别字或看到改进,请随时打开问题,或挖掘并通过拉请求做出贡献 :)


这可能需要一些更多的质量保证,但第一印象是:它可以运行。谢谢,@Zaahid - tivnet
2
非常好用!我可以从 AWS SES 收件箱中流式传输 40MB+ 的电子邮件到 S3,而且没有任何问题。这是一款优秀的库。 - bishop
与 https://github.com/php-mime-mail-parser/php-mime-mail-parser 相比有什么反馈? - Aistis

6
有趣的是,我现在正在开发一个简单的通知系统。我刚刚用Zend_Mail完成了弹回管理器。它基本上拥有你所需求的所有功能,可以连接到邮箱(POP3、IMAP、Mbox和Maildir),从中提取消息以及对所有这些消息进行操作。
它处理多部分消息,但是各个部分可能很难处理。我在使用非传送退回通知时很难确定哪个部分是原始邮件的附加部分,但我有一种感觉是我在文档中错过了什么。我不确定它如何处理编码,因为我的使用方式相当简单,但我相信它具有你提到的所有编码的规定。请查看文档并浏览API。

你知道是否可以在没有存储连接器的情况下使用Zend_Mail吗?我想将一个传入的消息作为字符串传递,并且能够在其上使用与消息相关联的方法,而不需要它来自存储位置。 - Sgraffite
2
我确定有一种方法,因为同一个类也被用于使用mailer / transport类发送消息,在那种情况下,您将始终从字符串/文件构造消息。如果我回忆起来,它看起来像 $m = new Zend_Mail_Message(array('raw' => $stringMessage)); 请查看实际类和构造函数的文档注释以进行验证。 - prodigitalson
1
这最终对我起了作用。Zend 做了一些事情,我不明白为什么。当 Zend 无法识别标头时,它会抛出异常。在我的情况下,我不关心未被识别的标头,所以我注释掉了那个异常。此外,有一个函数,在其中 Zend 对 $parts 进行 foreach(),但有时它尝试对其进行 foreach 的变量是 null,因此我添加了一个 null 检查,并在那里返回 $res 如果它是 null。 - Sgraffite
1
最后,当它检查 MIME 边界时,如果找不到结束边界,它会抛出异常。在我的情况下,这是一个格式错误的消息,但正文仍然可读,所以我最终注释掉了那个异常。我宁愿给用户一个格式错误的正文,也不要什么都没有。 - Sgraffite
总共有11.2k条消息,其中只有3条消息实际上引发了该异常,因此可能并不常见。 - Sgraffite
显示剩余6条评论

4
我fork了php-mime-mail-parser并修复了所有问题:php-mime-mail-parser的分支 超过52个测试和764个断言 代码覆盖率:100%行,100%函数和方法,100%类和特性
您需要PECL包MailParse才能使用它,但是封装器没有问题且经过充分测试。

2

并非始终有效,我有一些示例它无法处理电子邮件。 - behz4d

1

我目前正在寻找一个易于使用、强大的MIME电子邮件解析库,目前正在认真研究eZ Components的Mail组件。但是,如果你正在寻找像我一样可以轻松地使用echo $email->text;echo $email->html;这样的东西,那么你会感到失望。实际上,现在我认为这种简化甚至不可能,因为MIME的工作方式。但在PHP世界中,它似乎是最好的选择。

我开始使用Zend_Mail组件来开发我的当前项目,但当需要深入了解这些电子邮件部分和编码头时,Zend_Mail基本上让你自己摸索。你需要自己进行大部分解码,这一点一点也不有趣。

关于 IMAP PHP 扩展,它的作用是从您的邮箱中检索邮件,而不是解码 MIME。虽然它确实有一些方便的解码函数,但您可能需要使用Mailparse PECL 扩展来处理这个问题集。另一方面,我还没有尝试过它,但似乎您需要编写大量代码才能真正获得所需的数据。

从文档上看起来还不错。我已经花了很多时间来实现和测试Zend_Mail库,它似乎运行得相当不错。老实说,我不能在工作中再花更多的时间来研究一个新的库。不过还是谢谢你的回复 :) - Sgraffite

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接