Algunas veces se necesita validar una cuenta de correo introducida por un usuario. Las formas más conocidas pasan por chequear la validez de la construcción de la dirección de correo mediante regular expresions y enviarle un mensaje de validación a esa cuenta y que el usuario le dé a algun link.
Pero yo buscaba algún sistema que me dijera si una dirección de correo existe realmente sin enviarle un mail de validación, y he encontrado un método que consulta a un servidor DNS por la existencia del dominio y luego le pregunta al servidor del dominio por la existencia del mailbox.
Después de mucho buscar encuentro en Tienhuis Networking un sistema que realiza tres pasos para comprobar una dirección de correo:
- Comprueba la correcta construcción mediante una expresión regular.
- Comprueba la existencia y disponibilidad de un registro MX en el DNS con el nombre del dominio de la dirección de mail.
- Comprueba si el mailserver encontrado accepta esa cuenta de mail.
La ventaja de este sistema de validación de correo es que no sólo se comprueba que la dirección contenga carácteres válidos, una arroba y una extensión de dominio válida, sino que consulta el propio servidor por su existencia.
Para realizar la segunda función se tira de la funcion de PHP getmxrr() (no disponible en servidores Windows!) que devuelve una posible lista de servidores de correo disponibles. Con éso podríamos decir que el dominio existe y que el servidor está en línea.
Pero para estar seguros que la cuenta existe y está operativa debemos probar la cuenta de correo contra los servidores encontrados en el punto anterior. Se abre un socket en el puerto 25 contra el servidor de correo y se le envía un conjunto de instrucciones directas (HELO, MAIL FROM, RCPT TO y QUIT) que servirán para provocar el error si la cuenta no existe en el servidor.
Este último punto es un poco engañoso, pues mientras el servidor de Hotmail (prueba por excelencia
) funciona perfectamente, lo he probado en mi propio servidor de correo de mi hosting y responde OK para todas las cuentas que verifiquemos en su dominio, aunque no existan. Supongo que debe ser por tener activado el CatchAll, pero claro, ésto provoca falsos positivos. Si alguien tiene una idea será bienvenida
Para poder probar y demostrar el sistema he colgado una página de test aquí: Check Mail. El código fuente de la función lo posteo a continuación, y lo pongo disponible para bajar aquí.
PHP:
-
function validateEmail($email, $domainCheck = false, $verify = false, $return_errors=false) {
-
-
if($debug) {echo "<pre>";
}
-
-
# Check syntax with regex
-
if (preg_match('/^([a-zA-Z0-9\._\+-]+)\@((\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,7}|[0-9]{1,3})(\]?))$/',
$email,
$matches)) {
-
$user = $matches[1];
-
$domain = $matches[2];
-
# Check availability of DNS MX records
-
-
# Construct array of available mailservers
-
if(getmxrr($domain,
$mxhosts,
$mxweight)) {
-
for($i=0;$i<count($mxhosts);$i++){
-
$mxs[$mxhosts[$i]] = $mxweight[$i];
-
}
-
-
-
-
-
} else {
-
-
}
-
$total =
count($mailers);
-
# Query each mailserver
-
if($total> 0 && $verify) {
-
# Check if mailers accept mail
-
for($n=0; $n <$total; $n++) {
-
# Check if socket can be opened
-
if($debug) { echo "Checking server $mailers[$n]...\n";
}
-
$connect_timeout = 2;
-
$errno = 0;
-
$errstr = 0;
-
$probe_address = 'postmaster@tienhuis.nl';
-
# Try to open up socket
-
if($sock = @
fsockopen($mailers[$n],
25,
$errno ,
$errstr,
$connect_timeout)) {
-
$response =
fgets($sock);
-
if($debug) {echo "Opening up socket to $mailers[$n]... Succes!\n";
}
-
-
-
if($debug) { echo "$mailers[$n] replied: $response\n";
}
-
-
"HELO outkast.tienhuis.nl", # Be sure to set this correctly!
-
"MAIL FROM: <$probe_address>",
-
"RCPT TO: <$email>",
-
"QUIT",
-
);
-
# Hard error on connect -> break out
-
if(!
$meta['timed_out'] && !
preg_match('/^2\d\d[ -]/',
$response)) {
-
$error = "Error: $mailers[$n] said: $response\n";
-
break;
-
}
-
foreach($cmds as $cmd) {
-
-
fputs($sock,
"$cmd\r\n");
-
$response =
fgets($sock,
4096);
-
-
-
if(!
$meta['timed_out'] &&
preg_match('/^5\d\d[ -]/',
$response)) {
-
$error = "Unverified address: $mailers[$n] said: $response";
-
break 2;
-
}
-
}
-
-
if($debug) { echo "Succesful communication with $mailers[$n], no hard errors, assuming OK";
}
-
break;
-
} elseif($n == $total-1) {
-
$errors = "None of the mailservers listed for $domain could be contacted";
-
}
-
}
-
} else {
-
$error = "No usable DNS records found for domain '$domain'";
-
}
-
}
-
} else {
-
$error = 'Address syntax not correct';
-
}
-
if($debug) { echo "</pre>";
}
-
#echo "</pre>";
-
if($return_errors) {
-
# Give back details about the error(s).
-
# Return FALSE if there are no errors.
-
# Keep this in mind when using it like:
-
# if(checkEmail($addr)) {
-
# Because of this strange behaviour this
-
# is not default
-
-
} else {
-
# 'Old' behaviour, simple to understand
-
if(isset($error)) return false;
else return true;
-
}
-
}
Tag:
Escribe un Comentario