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

Posted

技术标签:

【中文标题】从字符串中检索完整的电子邮件地址【英文标题】:Retrieve full email address from string 【发布时间】:2017-04-03 04:47:17 【问题描述】:

我目前正在使用 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 提供的字符串中获取电子邮件地址的更好方法吗?

【问题讨论】:

如果str总是这样,也可以试试preg_match('/mailto:\K[^|>]+/', $str, $out) 【参考方案1】:

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

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

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

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

echo $addresses[0];

【讨论】:

只需添加以下内容进行验证:foreach ($addresses as $value) if (filter_var($value, FILTER_VALIDATE_EMAIL)) echo "Valid Email: " . $value . "&lt;br&gt;"; 这与@Kitson88 的一个小调整相结合,效果很好。谢谢你们! @bcmcfc,看来你是 laravel 大师了。我需要你帮忙。看这里:***.com/questions/41887504/…【参考方案2】:

这种方法可以完成这项工作,您可以避免使用正则表达式。并确保返回的电子邮件是一个真实的电子邮件地址,方法是使用 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

【讨论】:

【参考方案3】:

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

另外一个困难是,电子邮件地址的本地部分也可能包含管道字符,但域可能不包含;请参阅以下问题。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,因为您不是在查找所有匹配项,而是查找第一个匹配项。

【讨论】:

+1 从来不知道电子邮件可以包含管道。虽然看起来很疯狂,想象一下试图通过电话向某人解释您的电子邮件具有管道字符。有时让人们理解个人领域已经够难的了!出于好奇,我刚刚测试了 gmail,他们只支持规范的一个子集:“请仅使用字母 (a-z)、数字和句点。” @bcmcfc 每个域都可以设置自己的规则,只要它们不违反规范。但他们不必实施完整的规范。换句话说,GMail 不必允许bc|mc|fc@gmail.com,但他们应该允许向bc|mc|fc$@someotherdomain.com发送电子邮件。 @SQB,看来你掌握了 laravel。我需要你帮忙。看这里:***.com/questions/41047583/…

以上是关于从字符串中检索完整的电子邮件地址的主要内容,如果未能解决你的问题,请参考以下文章

电子邮件传输的协议是啥?

从 IMAP 服务器检索邮件?

php imap 从电子邮件地址获取

使用 Powershell 查找 Lotus Notes 互联网电子邮件地址

如何从 API 请求中检索错误消息 [重复]

Laravel 仅检索数据库中用户表的电子邮件地址列