使用 checkdnsrr 验证电子邮件,是好还是坏的解决方案?
Validating emails using checkdnsrr, a good or bad solution?
我正在使用以下代码来验证电子邮件
if (checkdnsrr($domain , "MX")) {
echo 'mx - pass <br>';
} else {
echo 'mx - fail <br>';
}
我的愿望是检查域是否有效并且是否有 MX 记录。
我已经在使用正则表达式来检查电子邮件格式,但是人们输入了诸如 someone@gmail.con 之类的内容,这显然是错误的,但通过了基本格式验证。
我想进一步验证,但我不想走得太远而得到假阴性。
有没有人发现我的解决方案有任何问题或有更好的方法?
您的解决方案非常好!但是,在您进行 DNS 调用之前,我建议您先使用 FILTER_VALIDATE_EMAIL 验证电子邮件地址,然后将其传递给 MX DNS 检查。
虽然可能不需要检查 MX 记录是否存在,但您希望避免退回电子邮件,请继续!
是的,使用 checkdnsrr()
是个好主意。什么时候使用它是你应该关注的。我使用四遍系统。这是骨架,而不是我为电子邮件所做的确切组织。
四通系统
传递 1) 我的自定义过滤器使用 filter_input_array()
和此规则(其中过滤器出现在 class/object 的方法中。根据需要添加元素(用于其他领域)。
$customFilterRules = [
'email' => ['filter' => FILTER_CALLBACK,
'flags' => FILTER_REQUIRE_SCALAR,
'options' => [$this, 'scrubber']
];
通过 2) 将 filter_input_array()
与此过滤规则一起使用。根据需要添加更多元素(对于其他字段)。
$phpFilterRules = [
'email' => ['filter' => FILTER_SANITIZE_EMAIL,
'flags' => FILTER_REQUIRE_SCALAR]
];
通过 3) 使用此验证规则对 filter_input_array()
的输出使用 filter_var_array()
。根据需要添加更多规则。
$phpValidationRules = [
'email' => ['filter' => FILTER_VALIDATE_EMAIL,
'flags' => FILTER_REQUIRE_SCALAR]
];
第 4 次) 用 EmailValidator
class 检查以下内容。此外,如果您不喜欢使用 filter_input_array()
,这里有一些来自此 class 的方法通常可能会有帮助。根据需要进行更改。
哦,我还检查了基本的、特定于应用程序的、可接受的电子邮件地址长度:
$length = mb_strlen($email, 'UTF-8') //Make a decision based on this.
此外,我还有一个很棒的、特定于应用程序的电子邮件正则表达式,用于 preg_match()
。我只接受 128 个字符的电子邮件地址。
'/(?>\A[A-Za-z0-9_-][A-Za-z0-9_.-]{0,62}?[A-Za-z0-9_-]{0,1}@{1}?(?:(?:[A-Za-z0-9]{1}?){1}?(?:[A-Za-z0-9.-]{0,61}?[A-Za-z0-9]{1}?){0,1}?){1,127}?\.{1}?[a-z]{2,20}?\z){1}?/u'
这里有一些 EmailValidator
方法。
/**
* Compares 2 email addresses. If 1, just keep going.
*/
private function sameEmailAddress()
{
if (count($this->filteredInputArray) === 2) { //If there are two.
if ($this->identical($this->filteredInputArray['email1'], $this->filteredInputArray['email2'])) {
return true;
}
$this->testResultsArray['email1'] = false;
$this->testResultsArray['email2'] = false;
$this->errorMessagesArray['email1'] = 'Does not match e-mail below.';
$this->errorMessagesArray['email2'] = 'Does not match e-mail above.';
return false;
}
if (count($this->filteredInputArray) === 1) { //If there is only 1.
return true;
}
return false;
}
/**
* Finds problems with e-mail as a whole.
* There is a regular expression you can do this with.
*/
private function consecutivePeriodTest ($emailAddress, &$errorMessage)
{
if (!preg_match('/\A(?!..)+?\z/', $emailAddress)) {
return true;
}
$errorMessage = 'Consecutive periods are illegal!';
return false;
}
最后,我用checkdnsrr()
.
/**
* Given an array of unique domains, check DNS MX records.
*/
private function mxDNSPing(array $uniqueDomains)
{
$badDomains = [];
foreach ($uniqueDomains as $key => $domain) {
if (!checkdnsrr($domain, 'MX')) {
$this->testResultsArray[$key] = false;
$this->errorMessagesArray[$key] = 'No DNS MX records found.';
$badDomains[$key] = $domain;
}
}
return $badDomains;
}
正在确定电子邮件地址有什么问题。
/**
* Finds problems with local or domain parts.
* Should break up into two methods, though.
*/
private function emailPartProblemFinder($string, &$errorMessage)
{
$emailParts = $this->string->getEmailAddressParts($string); //explode() on `@`
if (count($emailParts) !== 2) {
$errorMessage = 'Invalid e-mail address!';
} else {
list($localPart, $domain) = $emailParts;
$localLength = mb_strlen($localPart);
$domainLength = mb_strlen($domain);
if ($localLength === 0) {
$errorMessage = 'Missing local part of address.';
} elseif ($localLength > 64) {
$errorMessage = 'Only 64 characters are alloed before the @ symbol ('.$localLength.' given)';
} elseif (mb_strrpos($string, '.') === ($localLength - 1)) {
$errorMessage = 'The local part of an email address cannot end with a period (.).';
} elseif (mb_strpos($string, '..') >= 0) {
$errorMessage = 'The local part of an email address cannot contain consecutive periods (..).';
} elseif ($domainLength < 4) { //x.yy, is my minimum domain format.
$errorMessage = 'Domain part < 4 characters. ('.$domainLength.' given)';
} elseif ($domainLength > 253) {
$errorMessage = 'Domain part exceeds 253 characters. ('.$domainLength.' given)';
}
}
return;
}
/**
* Finds problems with e-mail as a whole.
*/
private function emailAddressProblemFinder($string, $max, &$errorMessage)
{
$length = mb_strlen($string, 'UTF-8');
$atSymbolCount = mb_substr_count($string, '@', 'UTF-8');
if ($length === 0) {
return false; //The reason was already assigned to the error message inside of $this->validateInput()
} elseif ($length > $max) {
$errorMessage = 'Exceeds max length (' . $max . ' characters)';
} elseif ((mb_strpos($string, '@') === 0)) {
$errorMessage = 'Cannot start with a @';
} elseif ((mb_strrpos($string, '@') === ($length - 1))) {
$errorMessage = 'Cannot end with a @';
} elseif ($atSymbolCount > 1) {
$errorMessage = '@ appears '.$atSymbolCount.' times.';
} elseif ((mb_strpos($string, '@') === false)) {
$errorMessage = 'The @ symbol is missing.';
} elseif (mb_strpos($string, '.') === 0) {
$errorMessage = 'The local part of an email address cannot start with a period (.).';
} else {
$this->emailPartProblemFinder($string, $errorMessage);
}
return;
}
方法 emailAddressProblemFinder()
仅被调用以发现问题所在。如有必要,它会调用 emailPartProblemFinder()
。
我的观点是,在使用 checkdnsrr()
之前,您可以进行大量测试。这其中的智慧值得你和其他人争论。不管怎样,我总是喜欢看别人做的!
多年来我一直在使用 chkdnsrr()
,没有任何问题,直到本周(通过如上所述的预检查),当它无缘无故地踢出一个有效域 (dfp.com.my
) 时。我找不到造成这种情况的原因,所以我现在确保安装了 nslookup(在 CentOS 上,那是 sudo yum install bind-utils
),并使用了以下内容:
function isDomainValid($domain) {
$output = [];
$return = false;
exec("nslookup $domain", $output, $return);
return $return === 0;
}
我正在使用以下代码来验证电子邮件
if (checkdnsrr($domain , "MX")) {
echo 'mx - pass <br>';
} else {
echo 'mx - fail <br>';
}
我的愿望是检查域是否有效并且是否有 MX 记录。
我已经在使用正则表达式来检查电子邮件格式,但是人们输入了诸如 someone@gmail.con 之类的内容,这显然是错误的,但通过了基本格式验证。
我想进一步验证,但我不想走得太远而得到假阴性。
有没有人发现我的解决方案有任何问题或有更好的方法?
您的解决方案非常好!但是,在您进行 DNS 调用之前,我建议您先使用 FILTER_VALIDATE_EMAIL 验证电子邮件地址,然后将其传递给 MX DNS 检查。
虽然可能不需要检查 MX 记录是否存在,但您希望避免退回电子邮件,请继续!
是的,使用 checkdnsrr()
是个好主意。什么时候使用它是你应该关注的。我使用四遍系统。这是骨架,而不是我为电子邮件所做的确切组织。
四通系统
传递 1) 我的自定义过滤器使用 filter_input_array()
和此规则(其中过滤器出现在 class/object 的方法中。根据需要添加元素(用于其他领域)。
$customFilterRules = [
'email' => ['filter' => FILTER_CALLBACK,
'flags' => FILTER_REQUIRE_SCALAR,
'options' => [$this, 'scrubber']
];
通过 2) 将 filter_input_array()
与此过滤规则一起使用。根据需要添加更多元素(对于其他字段)。
$phpFilterRules = [
'email' => ['filter' => FILTER_SANITIZE_EMAIL,
'flags' => FILTER_REQUIRE_SCALAR]
];
通过 3) 使用此验证规则对 filter_input_array()
的输出使用 filter_var_array()
。根据需要添加更多规则。
$phpValidationRules = [
'email' => ['filter' => FILTER_VALIDATE_EMAIL,
'flags' => FILTER_REQUIRE_SCALAR]
];
第 4 次) 用 EmailValidator
class 检查以下内容。此外,如果您不喜欢使用 filter_input_array()
,这里有一些来自此 class 的方法通常可能会有帮助。根据需要进行更改。
哦,我还检查了基本的、特定于应用程序的、可接受的电子邮件地址长度:
$length = mb_strlen($email, 'UTF-8') //Make a decision based on this.
此外,我还有一个很棒的、特定于应用程序的电子邮件正则表达式,用于 preg_match()
。我只接受 128 个字符的电子邮件地址。
'/(?>\A[A-Za-z0-9_-][A-Za-z0-9_.-]{0,62}?[A-Za-z0-9_-]{0,1}@{1}?(?:(?:[A-Za-z0-9]{1}?){1}?(?:[A-Za-z0-9.-]{0,61}?[A-Za-z0-9]{1}?){0,1}?){1,127}?\.{1}?[a-z]{2,20}?\z){1}?/u'
这里有一些 EmailValidator
方法。
/**
* Compares 2 email addresses. If 1, just keep going.
*/
private function sameEmailAddress()
{
if (count($this->filteredInputArray) === 2) { //If there are two.
if ($this->identical($this->filteredInputArray['email1'], $this->filteredInputArray['email2'])) {
return true;
}
$this->testResultsArray['email1'] = false;
$this->testResultsArray['email2'] = false;
$this->errorMessagesArray['email1'] = 'Does not match e-mail below.';
$this->errorMessagesArray['email2'] = 'Does not match e-mail above.';
return false;
}
if (count($this->filteredInputArray) === 1) { //If there is only 1.
return true;
}
return false;
}
/**
* Finds problems with e-mail as a whole.
* There is a regular expression you can do this with.
*/
private function consecutivePeriodTest ($emailAddress, &$errorMessage)
{
if (!preg_match('/\A(?!..)+?\z/', $emailAddress)) {
return true;
}
$errorMessage = 'Consecutive periods are illegal!';
return false;
}
最后,我用checkdnsrr()
.
/**
* Given an array of unique domains, check DNS MX records.
*/
private function mxDNSPing(array $uniqueDomains)
{
$badDomains = [];
foreach ($uniqueDomains as $key => $domain) {
if (!checkdnsrr($domain, 'MX')) {
$this->testResultsArray[$key] = false;
$this->errorMessagesArray[$key] = 'No DNS MX records found.';
$badDomains[$key] = $domain;
}
}
return $badDomains;
}
正在确定电子邮件地址有什么问题。
/**
* Finds problems with local or domain parts.
* Should break up into two methods, though.
*/
private function emailPartProblemFinder($string, &$errorMessage)
{
$emailParts = $this->string->getEmailAddressParts($string); //explode() on `@`
if (count($emailParts) !== 2) {
$errorMessage = 'Invalid e-mail address!';
} else {
list($localPart, $domain) = $emailParts;
$localLength = mb_strlen($localPart);
$domainLength = mb_strlen($domain);
if ($localLength === 0) {
$errorMessage = 'Missing local part of address.';
} elseif ($localLength > 64) {
$errorMessage = 'Only 64 characters are alloed before the @ symbol ('.$localLength.' given)';
} elseif (mb_strrpos($string, '.') === ($localLength - 1)) {
$errorMessage = 'The local part of an email address cannot end with a period (.).';
} elseif (mb_strpos($string, '..') >= 0) {
$errorMessage = 'The local part of an email address cannot contain consecutive periods (..).';
} elseif ($domainLength < 4) { //x.yy, is my minimum domain format.
$errorMessage = 'Domain part < 4 characters. ('.$domainLength.' given)';
} elseif ($domainLength > 253) {
$errorMessage = 'Domain part exceeds 253 characters. ('.$domainLength.' given)';
}
}
return;
}
/**
* Finds problems with e-mail as a whole.
*/
private function emailAddressProblemFinder($string, $max, &$errorMessage)
{
$length = mb_strlen($string, 'UTF-8');
$atSymbolCount = mb_substr_count($string, '@', 'UTF-8');
if ($length === 0) {
return false; //The reason was already assigned to the error message inside of $this->validateInput()
} elseif ($length > $max) {
$errorMessage = 'Exceeds max length (' . $max . ' characters)';
} elseif ((mb_strpos($string, '@') === 0)) {
$errorMessage = 'Cannot start with a @';
} elseif ((mb_strrpos($string, '@') === ($length - 1))) {
$errorMessage = 'Cannot end with a @';
} elseif ($atSymbolCount > 1) {
$errorMessage = '@ appears '.$atSymbolCount.' times.';
} elseif ((mb_strpos($string, '@') === false)) {
$errorMessage = 'The @ symbol is missing.';
} elseif (mb_strpos($string, '.') === 0) {
$errorMessage = 'The local part of an email address cannot start with a period (.).';
} else {
$this->emailPartProblemFinder($string, $errorMessage);
}
return;
}
方法 emailAddressProblemFinder()
仅被调用以发现问题所在。如有必要,它会调用 emailPartProblemFinder()
。
我的观点是,在使用 checkdnsrr()
之前,您可以进行大量测试。这其中的智慧值得你和其他人争论。不管怎样,我总是喜欢看别人做的!
多年来我一直在使用 chkdnsrr()
,没有任何问题,直到本周(通过如上所述的预检查),当它无缘无故地踢出一个有效域 (dfp.com.my
) 时。我找不到造成这种情况的原因,所以我现在确保安装了 nslookup(在 CentOS 上,那是 sudo yum install bind-utils
),并使用了以下内容:
function isDomainValid($domain) {
$output = [];
$return = false;
exec("nslookup $domain", $output, $return);
return $return === 0;
}