PHP:如何确定电子邮件附件';什么是MIME类型?

PHP:如何确定电子邮件附件';什么是MIME类型?,php,zend-framework,mime-types,zend-mail,Php,Zend Framework,Mime Types,Zend Mail,我正在使用Zend的Zend_Mail_Storage_Pop3连接到邮件服务器,打开一封电子邮件,并遍历其附件。如果附件是PDF,我需要下载它。在每个消息部分的每次迭代中,我调用getHeaders,并使用正则表达式确定附件的mime类型。在大多数情况下,我会得到这样的结果: ["content-type"]=> string(64) "application/octet-stream; name=abc.pdf" ["content-transfer-encoding"]=> s

我正在使用Zend的
Zend_Mail_Storage_Pop3
连接到邮件服务器,打开一封电子邮件,并遍历其附件。如果附件是PDF,我需要下载它。在每个消息部分的每次迭代中,我调用
getHeaders
,并使用正则表达式确定附件的mime类型。在大多数情况下,我会得到这样的结果:

["content-type"]=> string(64) "application/octet-stream; name=abc.pdf"
["content-transfer-encoding"]=> string(6) "base64"
multipart/mixed; boundary=--boundary_2_1dca5b3b-499e-4109-b074-d8b5f914404a
但在某些情况下,我会得到这样的结果:

["content-type"]=> string(64) "application/octet-stream; name=abc.pdf"
["content-transfer-encoding"]=> string(6) "base64"
multipart/mixed; boundary=--boundary_2_1dca5b3b-499e-4109-b074-d8b5f914404a

如何确定此类附件的mime类型?

这是一个有点复杂的情况。当
内容类型
多部分/混合
时,意味着电子邮件中有多个部分。其中一个或多个可能是附件(除了可能包含html区域或纯文本)

内容类型
多部分/混合
时,也会给出一个边界。您可以使用此正则表达式确定是否正在处理多部分电子邮件:

$contentType = $this->GetHeader('content-type');
$regex = '%multipart.*?boundary\s*=\s*"?(\w+)?"?%is';
$matches = array();

if (preg_match($regex, $contentType, $matches)) {
    $this->isMultiPart = true;
    $this->boundary = $matches[1];
} else {
    $this->isMultiPart = false;
}
(请注意,此示例是处理电子邮件的更大类的一部分)

如果您的邮件是多部分电子邮件,那么下一步就是将所有部分分开。您可以这样做:

$parts = explode("--$this->boundary", $this->fullBody);
根据电子邮件标准,边界始终以
--
开头。然后剩下的唯一一件事就是解析每个单独的部分。
您可能已经有了这样做的代码。每个部分都有您在问题中提到的相同标题:
内容类型
内容传输编码

可能还有其他部分标题,您将希望删除它们(如果我没记错的话,它们都将以前缀
content
开头)。
然后确保如果该部件是base64编码的,那么您可以对此进行说明(您可以检查
内容传输编码
标题以确定这一点。
单个附件的mime类型将存储在部件的
内容类型
头中,就像单个部件消息一样


一个注意事项-这假设您正在处理邮件的原始源。为此,您可以使用
getRawHeader
getRawContent

是否遇到了著名的Microsoft TNEF附件格式?()看起来
Zend\u Mail\u Storage\u Pop3
无法解析电子邮件。您可能需要使用Mailparse扩展名:或Imap扩展名。我发布了一个关于如何解析原始电子邮件以查找部分的相当长的解释,但扩展名可能是一个很好的起点。您可以查看
php mime mailparser
:Pear有一个mime解析器:嗨,Andrew,Zend库公开了一个
isMultipart()
方法。我用它来确定电子邮件是否可能有附件。我开始在第二个
Zend\u Mail\u Message
部分循环(因为我认为附件就是从这里开始的;第一部分是实际的电子邮件)。这是对的吗?
fullBody
是Zend方法吗?我想尝试一下你的解决方案。一般来说,这是一种方法,但在你的案例中,Zend框架似乎出现了某种错误。从你所说的来看,它似乎是
isMultipart()
返回的是
true
,但一旦你看到消息部分,它仍然表示它是多部分的。因此,基本上,返回
多部分/混合的
的内容应该如上所述进行分析,这将(希望如此!)给你单独的部分。我不确定是否有一个完整的方法,但完整的方法实际上只是
getHeaders()。“\n\n”.getRawContent()
(标题,然后是内容的两行分隔符)。再次,我强烈建议检查一个预打包的扩展,它可以做到这一点-我在过去使用过,并取得了一些成功。