Blog ElCodiguero
11 Jan 2010 PHP

Validar una dirección de correo electrónico

Cualquier sistema que utilice el correo electrónico debería tener algún tipo de validación para evitar errores y datos basura. Pero ¿cómo validar correctamente? Antes que nada hay que tener por seguro que no hay forma (rápida y práctica) de comprobar que una dirección de correo existe y tiene a un usuario detrás, solamente se puede comprobar que la dirección tiene una forma válida y apunta a un dominio activo.

Como suele suceder, el problema puede atacarse de diferentes formas. Hay sistemas que simplemente validan que la información ingresada contenga una arroba, hay otros que usan expresiones regulares complejas que fallan en cuanto la dirección ingresada no es común (aunque sea válida). La forma que voy a plantear no es novedosa, y es bastante sencilla, a la vez que efectiva.

Una expresión regular permisiva

Debe poder validar a cualquier dirección de correo válida, esto quiere decir que debe ser también bastante genérica. El patrón debe validar que exista una arroba, un nombre de usuario, y una parte que indique el dominio. A pesar de que probablemente nunca se usen nombres de usuario complejos en una dirección de correo, la verdad es que se puede usar cualquier caracter en esta parte de la dirección. Por lo que la expresión regular que debe validar esto no puede ser otra que

.+

Que representa a una cadena conteniendo al menos 1 caracter.

El dominio es un poco más complicado. Muchos cometen el error de solamente permitir dos o tres partes separadas por punto, o rechazar direcciones cuya última parte contenga más de 3 caracteres. Con esto se supone que incluyen a todos los dominios de primer nivel (.com, .net, .org… y los de los países, que tienen 2 letras). Pero se olvidan que Internet cambia, y ya tenemos TLD .info y .aero (de cuatro letras) e incluso .museum (de seis).

Debido a esto, y considerando que lentamente están apareciendo los dominios con ñ y letras acentuadas, y que quizás pronto las direcciones comiencen a aceptar más caracteres UTF-8, es que también para validar el dominio se debe utilizar un patrón genérico. El único requisito en este paso es que contenga al menos 2 secuencias de caracteres separadas por un punto. Debe haber al menos un punto, ya que no hay dominios que no desciendan de alguno de los TLD (en realidad sí hay direcciones válidas en entornos de red local que pertenecen a máquinas sin nombre de dominio, pero una dirección así no sirve en internet).

.+\..+

Este patrón representa a una secuencia de caracteres no vacía, seguida de un punto, y seguida de otra secuencia de caracteres no vacía.

Finalmente, juntando las partes el patrón queda:

^.+@.+\..+$

Validación del dominio con PHP

Una versión anterior de este artículo recomendaba validar el dominio con checkdnsrr(). Esta parte ha sido eliminada, y el motivo es bastante simple, a decir verdad.

La función checkdnsrr solamente puede determinar si un dominio está registrado, y con el parámetro adecuado permite saber si el dominio tiene un registro MX (Mail eXchange) asociado (es decir, si es capaz de recibir correo). Pero una entrada DNS correcta no implica que realmente haya un servidor funcionando en el dominio. Otras opciones, como gethostbyname por ejemplo, tienen sus propios problemas:

Por estos motivos es que la validación del dominio funcionará en la mayoría de los casos pero fallará en otros, y si no se puede saber que será exitosa en todos los casos, no se puede confiar en ella.

De todas formas se incluyen los enlaces a las páginas del manual de PHP que corresponden a estas funciones, para que cada uno decida si hacer la validación o no.

Vale recordar lo que se mencionó al principio: no existe forma práctica de comprobar con certeza que la dirección es válida aún cuando se pudiese validar el dominio, dado que la dirección podría ser válida en forma pero no existir en el servidor, o podría estar mal escrita por error. La única manera de saber con seguridad si la dirección es válida es enviar un correo de confirmación antes de habilitar al usuario a continuar en el sitio. Pero esto tampoco es la solución en todos los casos; a veces solicitar confirmación al usuario no tiene sentido (por ejempo en un formulario de contacto).

A continuación el código de mi función de validación:

1 <?php
2 function validar_correo($correo) {
3     return preg_match('/^.+@(.+\..+)$/', $correo);
4 }

A modo de resumen: la validación de direcciones de correo es compleja y no vale la pena intentar validar más que la forma. La mayoría de los métodos más estrictos con los que uno se puede llegar a encontrar suelen rechazar direcciones perfectamente correctas (aunque relativamente raras).

Enlaces relacionados

Activa Javascript para para cargar los comentarios, basados en DISQUS

El Blog de ElCodiguero funciona sobre Pelican

Inicio | Blog | Acerca de