从字符串中检索完整的电子邮件地址
Retrieve full email address from string
我目前正在使用 Laravel 构建一个 Slack 机器人,其中一个功能是它可以接收电子邮件地址并向其发送消息。
问题是电子邮件地址(例如 bob@example.com
)作为 <mailto:bob@example.com|bob@example.com>
来自 Slack。
我目前有一个从中检索电子邮件的功能:
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
作为电子邮件地址。
我不太擅长使用正则表达式,但是我的模式中还有什么可以 use/change 的吗,或者有更好的方法从 Slack 提供的字符串中获取电子邮件地址吗?
如果您知道正则表达式始终采用的格式,则始终可以将正则表达式排除在外:
$testString = '<mailto:bob@example.com|bob@example.com>';
$testString = str_replace(['<mailto:', '>'], '', $testString);
$addresses = explode('|', $testString);
echo $addresses[0];
此方法可以完成工作,您可以避免使用正则表达式。并通过使用 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
您知道包含电子邮件地址的字符串将始终采用 <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
,因为您不是在查找所有匹配项,而是在查找第一个匹配项。
我目前正在使用 Laravel 构建一个 Slack 机器人,其中一个功能是它可以接收电子邮件地址并向其发送消息。
问题是电子邮件地址(例如 bob@example.com
)作为 <mailto:bob@example.com|bob@example.com>
来自 Slack。
我目前有一个从中检索电子邮件的功能:
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
作为电子邮件地址。
我不太擅长使用正则表达式,但是我的模式中还有什么可以 use/change 的吗,或者有更好的方法从 Slack 提供的字符串中获取电子邮件地址吗?
如果您知道正则表达式始终采用的格式,则始终可以将正则表达式排除在外:
$testString = '<mailto:bob@example.com|bob@example.com>';
$testString = str_replace(['<mailto:', '>'], '', $testString);
$addresses = explode('|', $testString);
echo $addresses[0];
此方法可以完成工作,您可以避免使用正则表达式。并通过使用 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
您知道包含电子邮件地址的字符串将始终采用 <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
,因为您不是在查找所有匹配项,而是在查找第一个匹配项。