刘泉皓

没有最强的法术,只有最强的法师。

php中Mail_mimeDecode无法读取foxmail等eml文件正文问题

23 Feb 2016 » memory

使用cat -A xx.eml文件,发现foxmail的eml文件文件结尾和空行使用的\r\r\n,如:

Received: from WDGTO0MYSBX754J (unknown [106.39.222.102])^M^M$
^Iby smtp10 (Coremail) with SMTP id DsCowABnE2wPf8pW4XqYBw--.24431S2;^M^M$
^IMon, 22 Feb 2016 11:22:56 +0800 (CST)^M^M$
Date: Mon, 22 Feb 2016 11:23:17 +0800^M^M$
From: "postmaster@test.com" <postmaster@test.com>^M^M$
To: postmaster <postmaster@test.com>^M^M$
Subject: ccc^M^M$
X-Priority: 3^M^M$
X-GUID: BF101B77-22A1-4EFA-9ECE-DE1849536DD4^M^M$
X-Has-Attach: no^M^M$
X-Mailer: Foxmail 7, 2, 7, 26[cn]^M^M$
Mime-Version: 1.0^M^M$
Message-ID: <postmaster@test.com>^M^M$
Content-Type: multipart/alternative;^M^M$
^Iboundary="----=_001_NextPart126808224252_=----"^M^M$
X-CM-TRANSID:DsCowABnE2wPf8pW4XqYBw--.24431S2^M^M$
X-Coremail-Antispam: 1Uf129KBjDUn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73^M^M$
^IVFW2AGmfu7bjvjm3AaLaJ3UbIYCTnIWIevJa73UjIFyTuYvjTRVpBfUUUUU^M^M$
X-Originating-IP: [106.39.222.102]^M^M$
X-CM-SenderInfo: 5fqox3ltk6il2tof0z/xtbBDhIXjFQG4BtVJQAAse^M^M$
^M^M$
This is a multi-part message in MIME format.^M^M$
^M^M$
------=_001_NextPart126808224252_=----^M^M$
Content-Type: text/plain;^M^M$
^Icharset="us-ascii"^M^M$
Content-Transfer-Encoding: base64^M^M$
^M^M$
Y2NjDQoNCg==^M^M$
^M^M$
------=_001_NextPart126808224252_=----^M^M$
Content-Type: text/html;^M^M$
^Icharset="us-ascii"^M^M$
Content-Transfer-Encoding: quoted-printable^M^M$
^M^M$
cccc^M^M$
------=_001_NextPart126808224252_=------^M^M$

但是Mail_mimeDecode中用来分段header和body的函数中是

function _splitBodyHeader($input)
{
    if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $input, $match)) {
        return array($match[1], $match[2]);
    }
    // bug #17325 - empty bodies are allowed. - we just check that at least one line 
    // of headers exist..
    if (count(explode("\n",$input))) {
        return array($input, '');
    }
    $this->_error = 'Could not split header and body';
    return false;
}

可以发现其中的正则表达式/^(.*?)\r?\n\r?\n(.*)/s中的\r?无法匹配成功eml文件的空行,它只能匹配0个或1个\r,所以将preg_match中的正则表达式换成

preg_match("/^(.*?)\r*\n\r*\n(.*)/s

用来匹配0个或多个\r即可。


知识共享许可协议    鄂ICP备 15002452号-5    鄂公网安备 42088102000048号