Php 解析TO头中符合RFC 822的地址

Php 解析TO头中符合RFC 822的地址,php,regex,Php,Regex,我想用preg_match_all解析一个电子邮件地址列表(如to标题中的列表),以获取用户名(如果存在)和电子邮件。类似于Pear中的mailparse\u rfc822\u parse\u addresses或Mail\u rfc822::parseAddressList(),但使用普通PHP 输入: "DOE, John \(ACME\)" <john.doe@somewhere.com>, "DOE, Jane" <jane.doe@somewhere.com>

我想用preg_match_all解析一个电子邮件地址列表(如to标题中的列表),以获取用户名(如果存在)和电子邮件。类似于Pear中的mailparse\u rfc822\u parse\u addresses或Mail\u rfc822::parseAddressList(),但使用普通PHP

输入:

"DOE, John \(ACME\)" <john.doe@somewhere.com>, "DOE, Jane" <jane.doe@somewhere.com>
不需要支持奇怪的电子邮件格式(/[a-z0-9.%-]+@[a-z0-9.-]+.[a-z]{2,4}/i用于电子邮件部分是可以的)

我不能使用explode,因为名称中可能会出现逗号。str_getcsv不起作用,因为我可以:

DOE, John \(ACME\) <john.doe@somewhere.com> 
DOE,John\(ACME\)
作为输入

更新:

目前,我有以下几点:

public static function parseAddressList($addressList)
{
    $pattern = '/^(?:"?([^<"]+)"?\s)?<?([^>]+@[^>]+)>?$/';
    if (preg_match($pattern, $addressList, $matches)) {
        return array(
            array(
                'name' => stripcslashes($matches[1]),
                'email' => $matches[2]
            )
        );
    } else {
        $parts = str_getcsv($addressList);
        $result = array();
        foreach($parts as $part) {
            if (preg_match($pattern, $part, $matches)) {
                $result[] = array(
                    'name' => stripcslashes($matches[1]),
                    'email' => $matches[2]
                );
            }
        }
        return $result;
    }
}
公共静态函数parseAddressList($addressList)
{

$pattern='/^(?:“?([^我不知道该RFC,但如果格式始终如您所示,那么您可以尝试以下方法:

preg_match_all("/\"([^\"]*)\"\\s+<([^<>]*)>/", $string, $matches);
print_r($matches);
preg\u match\u all(“/\”([^\”]*)\“\\s+/”,$string,$matches);
打印(匹配项);
最后我做到了:

public static function parseAddressList($addressList)
{
    $pattern = '/^(?:"?((?:[^"\\\\]|\\\\.)+)"?\s)?<?([a-z0-9._%-]+@[a-z0-9.-]+\\.[a-z]{2,4})>?$/i';
    if (($addressList[0] != '<') and preg_match($pattern, $addressList, $matches)) {
        return array(
            array(
                'name' => stripcslashes($matches[1]),
                'email' => $matches[2]
            )
        );
    } else {
        $parts = str_getcsv($addressList);
        $result = array();
        foreach($parts as $part) {
            if (preg_match($pattern, $part, $matches)) {
                $item = array();
                if ($matches[1] != '') $item['name'] = stripcslashes($matches[1]);
                $item['email'] =  $matches[2];
                $result[] = $item;
            }
        }
        return $result;
    }
}
公共静态函数parseAddressList($addressList)
{

$pattern='/^(?:((?:[^“\\\]\\\\\)+)“?\s”)不起作用,因为双引号不是必需的。但还是要感谢。如果电子邮件地址在@之前有一个-,这个正则表达式会给我带来一些问题,这为我修复了它(即在正则表达式中转义-in
$pattern='/^(?(?:[^“\\\\\\\]\\\\\\\\\\)+)”?\s)?如果是普通的旧电子邮件地址而没有名称部分,也会失败…需要
trim()
每个“部分”
Bob,notparsed@sad.com
每个
$part
都需要修剪,因为前导空格
preg_match_all("/\"([^\"]*)\"\\s+<([^<>]*)>/", $string, $matches);
print_r($matches);
public static function parseAddressList($addressList)
{
    $pattern = '/^(?:"?((?:[^"\\\\]|\\\\.)+)"?\s)?<?([a-z0-9._%-]+@[a-z0-9.-]+\\.[a-z]{2,4})>?$/i';
    if (($addressList[0] != '<') and preg_match($pattern, $addressList, $matches)) {
        return array(
            array(
                'name' => stripcslashes($matches[1]),
                'email' => $matches[2]
            )
        );
    } else {
        $parts = str_getcsv($addressList);
        $result = array();
        foreach($parts as $part) {
            if (preg_match($pattern, $part, $matches)) {
                $item = array();
                if ($matches[1] != '') $item['name'] = stripcslashes($matches[1]);
                $item['email'] =  $matches[2];
                $result[] = $item;
            }
        }
        return $result;
    }
}