我使用以下代码验证电子邮件
if (checkdnsrr($domain , "MX")) {
echo 'mx - pass <br>';
} else {
echo 'mx - fail <br>';
}
我希望检查域名是否有效并且有MX记录。
我已经使用正则表达式来检查电子邮件格式,但是人们输入像someone@gmail.con这样的内容,这显然是错误的,但是会进行基本的格式验证。
我想进一步验证,但我不想走太远而得到假阴性。
有没有人看到我的解决方案有任何问题或有更好的方法?
答案 0 :(得分:3)
是的,使用checkdnsrr()
是一个好主意。什么时候使用它是你应该关注的。我使用四通系统。这是骨架,而不是我为电子邮件做的确切组织。
传递1 )我的自定义过滤器使用filter_input_array()
和此规则(其中过滤器出现在类/对象的方法中。根据需要添加元素(对于其他字段)。
$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_var_array()
的输出上使用filter_input_array()
。根据需要添加更多规则。
$phpValidationRules = [
'email' => ['filter' => FILTER_VALIDATE_EMAIL,
'flags' => FILTER_REQUIRE_SCALAR]
];
通过4 )使用EmailValidator
课程检查以下内容。另外,如果您不喜欢使用filter_input_array()
,则此类中的一些方法通常可能会有所帮助。必要时更改。
哦,我还会检查电子邮件地址的基本,特定于应用程序,可接受的长度:
$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()
之前,您可以进行大量的测试。这种智慧是你和其他人辩论的东西。无论如何,我总是喜欢看别人做的事情!
答案 1 :(得分:1)
你的解决方案非常好!但是,在您进行DNS呼叫之前,我建议您首先使用FILTER_VALIDATE_EMAIL验证电子邮件地址,然后将其传递给MX DNS检查。
虽然可能不需要检查MX记录是否存在,但是您希望避免退回电子邮件,请继续!
答案 2 :(得分:0)
我使用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;
}