Я хотел бы проанализировать список адресов электронной почты (например, один в заголовке 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);