Разбирайте адреса RFC 822 в заголовке TO

Я хотел бы проанализировать список адресов электронной почты (например, один в заголовке TO) с preg_match_all, чтобы получить имя пользователя (если существует) и E-mail. Что-то похожее на mailparse_rfc822_parse_addresses или Mail_RFC822 :: parseAddressList () из Pear, но на простой 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> 

Мне нужно протестировать обратную ссылку ", но я не помню, как это сделать.

Наконец я сделал это:

 public static function parseAddressList($addressList) { $pattern = '/^(?:"?((?:[^"\\\\]|\\\\.)+)"?\s)?<?([a-z0-9._%-]+@[a-z0-9.-]+\\.[az]{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; } } 

Но я не уверен, что это работает для всех случаев.

Я не знаю, что RFC, но если формат всегда, как вы показали, вы можете попробовать что-то вроде:

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