3

在 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 函数来拆分姓名和地址后,我编写了以下代码。

您可以在 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

4 回答 4

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
)
于 2013-05-22T09:51:56.197 回答
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 的最后一个元素是否为 '@')。

于 2015-12-23T20:30:01.050 回答
0

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

或者在我看来,您可以创建自己的函数(比如说get_email_address),它捕获@字符,然后从@直到 '<' 字符和 'rest-right-string' 从@直到'>' 字符。

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

希望它有所帮助.. :)

于 2013-05-22T07:21:50.320 回答
0

不幸的是,正则表达式在全名的几个条件下失败:

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

我这样调整了表达式

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

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

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

7年后,希望这会有所帮助:)

于 2020-03-16T10:28:20.863 回答