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

时间:2011-07-07 10:28:41

标签: php regex

我想用preg_match_all解析一个电子邮件地址列表(如TO标题中的那个)以获取用户名(如果存在)和电子邮件。类似于来自Pear的mailparse_rfc822_parse_addresses或Mail_RFC822 :: parseAddressList(),但是在普通的PHP中。

输入:

"DOE, John \(ACME\)" <john.doe@somewhere.com>, "DOE, Jane" <jane.doe@somewhere.com>

输出:

array(
    array(
        'name' => 'DOE, John (ACME)',
        'email' => 'john.doe@somewhere.com'
    ), 
    array(
        'name' => 'DOE, Jane',
        'email' => 'jane.doe@somewhere.com'
    )
)

不需要支持奇怪的电子邮件格式(/[a-z0-9._%-]+@[a-z0-9.-]+.[az]{2,4}/i对于电子邮件部分是好的。)

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

DOE, John \(ACME\) <john.doe@somewhere.com> 

作为输入。

更新

目前,我有这个:

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;
    }
}

但它失败了:

"DOE, \"John\"" <john.doe@somewhere.com>

我需要在后面参考测试\“但我不记得怎么做了。

2 个答案:

答案 0 :(得分:4)

最后我做到了:

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;
    }
}

但我不确定它适用于所有情况。

答案 1 :(得分:0)

我不知道RFC,但如果格式总是如你所示那么你可以尝试类似的东西:

preg_match_all("/\"([^\"]*)\"\\s+<([^<>]*)>/", $string, $matches);
print_r($matches);