从字符串中检索完整的电子邮件地址

时间:2016-11-19 11:15:34

标签: php regex laravel laravel-5.3 slack-api

我目前正在使用Laravel构建Slack机器人,其中一项功能是它可以接收电子邮件地址并向其发送消息。

问题是电子邮件地址(例如bob@example.com)来自Slack的<mailto:bob@example.com|bob@example.com>

我目前有一个功能可以从中检索电子邮件:

public function getEmail($string)
{
    $pattern = '/[a-z0-9_\-\+]+@[a-z0-9\-]+\.([a-z]{2,3})(?:\.[a-z]{2})?/i';
    preg_match_all($pattern, $string, $matches);
    $matches = array_filter($matches);

    return $matches[0][0];
}

这似乎适用于bob@example.com这样的电子邮件地址,但是在使用bob.jones@example.com等电子邮件地址时(例如<mailto:bob.jones@example.com|bob.jones@example.com>),它似乎失败了。 在这些情况下,该函数返回jones@example.com作为电子邮件地址。

我对正则表达式不太满意,但是我的模式中是否有其他我可以使用/更改的内容,或者是从Slack提供的字符串中获取电子邮件地址的更好方法?

3 个答案:

答案 0 :(得分:10)

如果您知道它始终是它所处的格式,那么总是可以将正则表达式排除在等式之外:

$testString = '<mailto:bob@example.com|bob@example.com>';

$testString = str_replace(['<mailto:', '>'], '', $testString);

$addresses = explode('|', $testString);

echo $addresses[0];

答案 1 :(得分:4)

此方法可以完成这项工作,您可以避免使用正则表达式。并通过使用php函数验证,确保返回的电子邮件是真实的电子邮件地址。

function getEmailAddress($string) 
{
    $string = trim($string, '<>');
    $args = explode('|', $string);
    foreach ($args as $_ => $val) {
        if(filter_var($val, FILTER_VALIDATE_EMAIL) !== false) {
            return $val;
        }
    }

    return null;    
}

echo getEmailAddress('<mailto:bob@example.com|bob@example.com>');

<强>输出

bob@example.com

答案 2 :(得分:0)

您知道包含电子邮件地址的字符串将始终采用<mailto:bob@example.com|bob@example.com>的格式,因此请使用该字符串。具体来说,您知道该字符串将以<mailto:开头,将包含|,并以>结尾。

另一个困难是,电子邮件地址的本地部分也可能包含管道字符,但域名可能不包含;看下面的问题。
What characters are allowed in an email address?

public function getEmail($string)
{
    $pattern = '/^<mailto:([^@]+@[^|]+)|(.*)>$/i';
    preg_match_all($pattern, $string, $matches);
    $matches = array_filter($matches);
    return $matches[1][0];
}

这从开始到结束匹配整行,但我们捕获第一组括号内的电子邮件地址。 $matches[1]包含第一个捕获括号中的所有匹配项。您可以使用preg_match代替,因为您不是在寻找所有匹配项,而只是第一个匹配项。