将完整的电子邮件地址分成名称和电子邮

时间:2013-05-22 07:01:59

标签: php email-validation

To:和From:原始电子邮件标题中似乎有许多可接受的电子邮件地址格式......

person@place.com
person <person@place.com>
person
Another Person <person@place.com>
'Another Person' <person@place.com>
"Another Person" <person@place.com>

在找不到任何有效的PHP函数来分割出名称和地址之后,我编写了以下代码。

您可以 DEMO IT ON CODEPAD 查看输出...

// validate email address
function validate_email( $email ){
    return (filter_var($email, FILTER_VALIDATE_EMAIL)) ? true : false;
}

// split email into name / address
function email_split( $str ){
    $name = $email = '';
    if (substr($str,0,1)=='<') {
        // first character = <
        $email = str_replace( array('<','>'), '', $str );
    } else if (strpos($str,' <') !== false) {
        // possibly = name <email>
        list($name,$email) = explode(' <',$str);
        $email = str_replace('>','',$email);
        if (!validate_email($email)) $email = '';
        $name = str_replace(array('"',"'"),'',$name);
    } else if (validate_email($str)) {
        // just the email
        $email = $str;
    } else {
        // unknown
        $name = $str;
    }
    return array( 'name'=>trim($name), 'email'=>trim($email) );
}

// test it
$tests = array(
    'person@place.com',
    'monarch <themonarch@tgoci.com>',
    'blahblah',
    "'doc venture' <doc@venture.com>"
    );

foreach ($tests as $test){
    echo print_r( email_split($test), true );
}

我在这里遗漏了什么?任何人都可以推荐更好的方式吗?

4 个答案:

答案 0 :(得分:3)

我已经设法为你的测试用例制作了一个正则表达式:

person@place.com
person <person@place.com>
person
Another Person <person@place.com>
'Another Person' <person@place.com>
"Another Person" <person@place.com>

使用preg_match这个正则表达式肯定会帮助你。

function email_split( $str ){
$sPattern = "/([\w\s\'\"]+[\s]+)?(<)?(([\w-\.]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4}))?(>)?/g";
preg_match($sPattern,$str,$aMatch);

if(isset($aMatch[1]))
{
echo $aMatch[1] //this is name;
}

if(isset($aMatch[3]))
{
echo $aMatch[3] //this is EmailAddress;
}
}

注意:我刚注意到单个“人”,即你的第三个测试用例可以被这个正则表达式丢弃(只是因为正则表达式中的空间限制)所以,在你的email_split函数的第一行,附加空格在你的字符串的最后一个地方。

然后就会瞄准目标。

谢谢,希望这有帮助。

我试过的代码:

<?php

// validate email address
function validate_email($email) {
   return (filter_var($email, FILTER_VALIDATE_EMAIL)) ? true : false;
}

// split email into name / address
function email_split($str) {
   $str .=" ";
   $sPattern = '/([\w\s\'\"]+[\s]+)?(<)?(([\w-\.]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4}))?(>)?/';
   preg_match($sPattern, $str, $aMatch);
   //echo "string";
   //print_r($aMatch);
   $name = (isset($aMatch[1])) ? $aMatch[1] : '';
   $email = (isset($aMatch[3])) ? $aMatch[3] : '';
   return array('name' => trim($name), 'email' => trim($email));
}

// test it
$tests = array(
   'person@place.com',
   'monarch <themonarch@tgoci.com>',
   'blahblah',
   "'doc venture' <doc@venture.com>"
);

foreach ($tests as $test) {
   echo "<pre>";
   echo print_r(email_split($test), true);
   echo "</pre>";
}

我得到的输出:

Array
(
   [name] => 
   [email] => person@place.com
)

Array
(
   [name] => monarch
   [email] => themonarch@tgoci.com
)

Array
(
   [name] => blahblah
   [email] => 
)

Array
(
   [name] => 'doc venture'
   [email] => doc@venture.com
)

答案 1 :(得分:1)

这个怎么样:

function email_split($str) {
    $parts = explode(' ', trim($str));
    $email = trim(array_pop($parts), "<> \t\n\r\0\x0B");
    $name = trim(implode(' ', $parts), "\"\' \t\n\r\0\x0B");
    if ($name == "" && strpos($email, "@") === false) {             // only single string - did not contain '@'
        $name = $email;
        $email = "";
    }
    return array('name' => $name, 'email' => $email);
}

看起来这大约是正则表达式解决方案的两倍。

注意:不需要OPs第三个测试用例(出于我的目的)。但为了回答OP,我添加了if stmt以产生OP预期结果。这可以通过其他方式完成(检查'@'的$ parts的最后一个元素。)

答案 2 :(得分:0)

在php中使用preg_match,http://php.net/manual/en/function.preg-match.php

或者在我看来,你可以创建自己的功能(比如 get_email_address ),它会捕获 @ 字符,然后从中获取'rest-left-string' @ 直到'&lt;'字符和来自 @ 的'rest-right-string'直到'&gt;'字符。

例如,字符串monarch <themonarch@tgoci.com>将返回'rest-left-string'= themonarch和'rest-right-string'= tgoci.com。最后,您的函数 get_email_address 将返回 themonarch@tgoci.com

希望它有所帮助.. :)

答案 3 :(得分:0)

不幸的是,正则表达式在全名的几种情况下失败:

  • 非字母数字字符(例如“ Amazon.it”)
  • 不可打印的字符
  • emojs

我以此方式调整了表情

$sPattern = '/([^<]*)?(<)?(([\w-\.]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4}))?(>)?/';

现在所有字符都可以正确识别和分割。

经过

测试

$address = "Test User @ `` . !! ? <test@email.com";

7年后,希望对您有所帮助:)