之前的一些答案是错误的,因为一个有效的电子邮件地址实际上可以包含多个 @ 符号,方法是将其包含在点分隔的引用文本中。请参阅以下示例:
$email = 'a."b@c".d@e.f';
echo (filter_var($email, FILTER_VALIDATE_EMAIL) ? 'V' : 'Inv'), 'alid email format.';
有效的电子邮件格式。
可以存在多个分隔的文本块和多个 @ 符号。这两个示例都是有效的电子邮件地址:
$email = 'a."b@c".d."@".e.f@g.h';
$email = '/."@@@@@@"./@a.b';
根据 Michael Berkowski 的爆炸式回答,此电子邮件地址如下所示:
$email = 'a."b@c".d@e.f';
$parts = explode('@', $email);
$user = $parts[0];
$domain = '@' . $parts[1];
用户:a."b"
域:@c".d
使用此解决方案的任何人都应注意潜在的滥用。根据这些输出接受电子邮件地址,然后将 $email 插入数据库可能会产生负面影响。
$email = 'a."b@c".d@INSERT BAD STUFF HERE';
只要先用filter_var进行验证,这些函数的内容才是准确的。
从左到右:
这是一个简单的非正则表达式、非爆炸性解决方案,用于查找不包含在分隔和引用的文本中的第一个 @。根据 filter_var,嵌套的分隔文本被认为是无效的,因此找到正确的 @ 是一个非常简单的搜索。
if(filter_var($email, FILTER_VALIDATE_EMAIL)) {
$a = '"';
$b = '.';
$c = '@';
$d = strlen($email);
$contained = false;
for($i = 0; $i < $d; ++$i) {
if($contained) {
if($email[$i] === $a && $email[$i + 1] === $b) {
$contained = false;
++$i;
}
}
elseif($email[$i] === $c)
break;
elseif($email[$i] === $b && $email[$i + 1] === $a) {
$contained = true;
++$i;
}
}
$local = substr($email, 0, $i);
$domain = substr($email, $i);
}
这是隐藏在函数中的相同代码。
function parse_email($email) {
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
$a = '"';
$b = '.';
$c = '@';
$d = strlen($email);
$contained = false;
for($i = 0; $i < $d; ++$i) {
if($contained) {
if($email[$i] === $a && $email[$i + 1] === $b) {
$contained = false;
++$i;
}
}
elseif($email[$i] === $c)
break;
elseif($email[$i] === $b && $email[$i + 1] === $a) {
$contained = true;
++$i;
}
}
return array('local' => substr($email, 0, $i), 'domain' => substr($email, $i));
}
使用中:
$email = 'a."b@c".x."@".d.e@f.g';
$email = parse_email($email);
if($email !== false)
print_r($email);
else
echo 'Bad email address.';
数组([本地] => a."b@c".x."@".d.e [域] => @f.g)
$email = 'a."b@c".x."@".d.e@f.g@';
$email = parse_email($email);
if($email !== false)
print_r($email);
else
echo 'Bad email address.';
错误的电子邮件地址。
从右边:
在对 filter_var 进行了一些测试并研究了可以接受的有效域名(Hostnames 由点分隔)之后,我创建了这个函数以获得更好的性能。在有效的电子邮件地址中,最后一个 @ 应该是真正的 @,因为 @ 符号不应出现在有效电子邮件地址的域中。
if(filter_var($email, FILTER_VALIDATE_EMAIL)) {
$domain = strrpos($email, '@');
$local = substr($email, 0, $domain);
$domain = substr($email, $domain);
}
作为一个函数:
function parse_email($email) {
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
$a = strrpos($email, '@');
return array('local' => substr($email, 0, $a), 'domain' => substr($email, $a));
}
或者使用explode和implode:
if(filter_var($email, FILTER_VALIDATE_EMAIL)) {
$local = explode('@', $email);
$domain = '@' . array_pop($local);
$local = implode('@', $local);
}
作为一个函数:
function parse_email($email) {
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
$email = explode('@', $email);
$domain = '@' . array_pop($email);
return array('local' => implode('@', $email), 'domain' => $domain);
}
如果您仍想使用正则表达式,从有效电子邮件地址的末尾开始拆分字符串是最安全的选择。
/(.*)(@.*)$/
(.*) 匹配任何内容。
(@.*) 匹配以 @ 符号开头的任何内容。
$ 字符串结束。
if(filter_var($email, FILTER_VALIDATE_EMAIL)) {
$local = preg_split('/(.*)(@.*)$/', $email, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
$domain = $local[1];
$local = $local[0];
}
作为一个函数:
function parse_email($email) {
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
$email = preg_split('/(.*)(@.*)$/', $email, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
return array('local' => $email[0], 'domain' => $email[1]);
}
或者
if(filter_var($email, FILTER_VALIDATE_EMAIL)) {
preg_match('/(.*)(@.*)$/', $email, $matches);
$local = $matches[1];
$domain = $matches[2];
}
作为一个函数:
function parse_email($email) {
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
preg_match('/(.*)(@.*)$/', $email, $matches);
return array('local' => $matches[1], 'domain' => $matches[2]);
}