filter_var con flag FILTER_VALIDATE_EMAIL en Filter->getEmail()

72 views
Skip to first unread message

Javier Ferrer

unread,
Nov 26, 2013, 10:09:56 AM11/26/13
to sif...@googlegroups.com
Hemos estado haciendo pruebas y, con la expresión regular que a día de hoy ejecuta el método getEmail para validar el formato de las direcciones de email, habrían como mínimo un par de tipos de casos que darían falsos positivos:
Tenemos dos opciones: pegarle una revisada a la expresión regular, o pasar a usar el flag FILTER_VALIDATE_EMAIL del método filter_var.

La opción de usar el filter_var parece mejor y, tras validar con este método todos los emails de nuestra BBDD, los únicos casos que aparentemente darían negativos son emails del tipo:
Las cuales no validan por tener más de 64 caracteres en la parte local de la dirección tal y como marca el RFC correspondiente
Además, son registros de inicios de 2011, con lo que no sé si Facebook ha dejado de usarlos.

¿Qué os parecería hacer el cambio a filter_var asumiendo esto?
¿No se ha hecho ya por algún motivo aparte?

Albert Lombarte

unread,
Nov 26, 2013, 5:55:02 PM11/26/13
to sif...@googlegroups.com
Creo recordar que la función filter_var daba falsos negativos, marcando algunos e-mails válidos como inválidos. Y viceversa, había emails tipo pepe@harry que validaban cuando no deberían. 

Las direcciones que pasas de falsos positivos diría que son perfectamente válidas por el RFC, otra cosa es que interesara de forma global no permitir este comportamiento.

Sin una batería de pruebas inmensa de emails válidos e inválidos no cambiaría la función actual, funciona muy bien y la hemos probado con decenas (cientos?) de miles de casos reales.




2013/11/26 Javier Ferrer <javier.m...@gmail.com>

--
You received this message because you are subscribed to the Google Groups "SIFO, PHP framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sifophp+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Daniel Picó

unread,
Nov 26, 2013, 6:04:35 PM11/26/13
to sif...@googlegroups.com

Albert Lombarte

unread,
Nov 26, 2013, 6:08:10 PM11/26/13
to sif...@googlegroups.com
Merci Dani,
  • Character . (dot, period, full stop) (ASCII: 46) provided that it is not the first or last character, and provided also that it does not appear two or more times consecutively (e.g. John..Doe@example.com is not allowed.).

Esta parte hay que corregirla entonces

2013/11/27 Daniel Picó <dap...@gmail.com>

Sergio Ambel Santoyo

unread,
Nov 26, 2013, 6:13:24 PM11/26/13
to sifophp
Ojo!

tengo las neuronas un poco distraídas pero recuerdo haber configurado ese filtro y haber tenido que volver a regexp por algunos usuarios de cierta herramienta web para twitter...




2013/11/27 Albert Lombarte <alom...@gmail.com>

Albert Garcia

unread,
Nov 27, 2013, 3:08:58 AM11/27/13
to sif...@googlegroups.com
Buenas!

Ayer pasamos la validación a toda nuestra BD (87K emails) con este cambio y saltaron unos 10 casos, todos ellos emails inválidos por doble punto, punto delante de la @, etc. De ahí la propuesta. 

La única contra que vimos es el tema de la validación del dominio. Este método no valida que el tld o el dominio del email sean válidos (el método actual valida contra una lista cerrada de TLDs). Y es que en principio, cualquier dominio o hostname podría ser válido. Por ejemplo, un hostname de una red interna para el caso de cuentas de correo no públicas. Sin embargo, el propio método getEmail incorpora un segundo parámetro, $check_dns, que nos serviría en el caso que queramos validar no sólo la sintaxis del email, si no también que se use un dominio válido para correo electrónico.

Viendo todo esto, nos surgió la duda de porqué se implementó con una expresión regular y no con la validación que ofrece el propio PHP desde la versión 5.2. Os suena?

Saludos!

--
Albert García Gibert
email. albert...@gibert.es
blog. http://obokaman.com
twitter. @obokaman

Albert Lombarte

unread,
Nov 27, 2013, 10:04:20 AM11/27/13
to sif...@googlegroups.com, sif...@googlegroups.com
Porque filter_var no garantizaba que los emails fueran válidos y el check dns es muy costoso.

Arreglemos la regexp y pongamos lo de los puntos y si faltara algún TLD se añade.

Sent from Mailbox for iPhone

Javier Ferrer

unread,
Nov 27, 2013, 10:12:34 AM11/27/13
to sif...@googlegroups.com
Si quieres, le estuve echando un vistazo antes de caer en lo del filter_var, así que aquí tienes lo que llegué a hacer

La que hay a día de hoy sería esta y lo que se añade con respecto a ella es el tema de que tenga que acabar con un carácter alfanumérico, que sólo pueda tener un modificador del tipo "+loquesea" y que no pueda tener dos puntos seguidos.

--
Javier Ferrer | Twitter | LinkedIn


2013/11/27 Albert Lombarte <alom...@gmail.com>
You received this message because you are subscribed to a topic in the Google Groups "SIFO, PHP framework" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/sifophp/5o0tkI2nC44/unsubscribe.
To unsubscribe from this group and all its topics, send an email to sifophp+u...@googlegroups.com.

Javier Ferrer

unread,
Nov 27, 2013, 10:28:34 AM11/27/13
to sif...@googlegroups.com
La que he puesto no tira para casos simples como "mail...@sub.domain.com", aquí tienes otra versión que, a pesar de que no controla el que haya un punto antes de la @, sí que valida el que no hayan dos puntos seguidos.

Albert Lombarte

unread,
Nov 27, 2013, 4:41:44 PM11/27/13
to sif...@googlegroups.com
Intento contestar ahora con una versión algo más extendida, explicando el por qué.

El día 0 que hice la clase Filter lo primero que pensé fué utilizar filter_var como en el resto de métodos. ¿Para qué iba a inventar algo cuando PHP ya lo soportaba?, desde luego era la opción fácil.

El problema vino cuando empecé a hacer tests y vi que PHP aceptaba prácticamente cualquier cosa con forma de e-mail y no encontré nadie que hubiera solucionado esto de manera convincente. Ejemplos de emails aceptados por filter_var serían entonces test@local o ho...@127.0.0.1 por lo que acababa llenando de basura cualquier registro abierto al público. En ese momento filter_var NO CUMPLIA con el RFC, por lo que no veía beneficio en usarlo.

Por otro lado, si hacía una implementación estricta del RCF, tendría que permitir cosas como antonia@[127.0.0.1] (que es RFC válido)  pero si tienes una aplicación online y la gente se registra con este tipo de emails, hay un 99,9% de posibilidades que sea SPAM. Este tipo de direcciones tampoco pasaban por el filter_var (probablemente esto haya evolucionado con el paso del tiempo) aún siendo como decía válidas en el RFC. La funcion de PHP quedaba lejos de tener una utilidad real.

Así que la solución práctica fue permitir tan solo emails con un TLD válido y además complementar esto con una validación de registro MX. Empecé a buscar la expresión regular que pasaba una burrada de casos y la puse online, con un sistema paralelo que aquellas que no pasaban se logeaban para una posterior revisión y refinamiento del sistema. Y con este registro complementé la validación y pasaron por allí unas 60.000 direcciones y fui tuneándola para añadir más casos, como por ejemplo TLDs extraños como .mil (si, tuve registros de estos dominios O_O )

Quizá reinventé la rueda en ese momento pero ya os digo que en ese momento no había alternativa que usar, casi todos los frameworks que he mirado utilizan filter_var directamente (e.g: Symfony) y parece que ya les es suficiente. Desconozco si con el paso de los años la validación de emails ha mejorado, ciertamente el uso de filter_var es o debería ser un "industry standard".

La casuística que probé fue sobretodo la de que emails validos fueran bien detectados, pero tampoco lleva al extremo el caso de que emails inválidos que no pasaran. Veo que esto no fue suficiente u habéis encontrado este caso de pepe..@loquesea.com que es inválido y no se detecta.

Propuesta
1) Añadir a la expresión regular las condiciones que faltan
2) Cambio por filter_var en el caso de que haya prosperado. Condición imprescindible la de hacer un test de la muerte :)

Si vamos en la dirección del punto 2, hagamos un test con PHPUnit, que se nos debería caer a todos la cara de vergüenza ya. Yo el primero que tengo ficheros de test no versionado en mi ordenador.


2013/11/27 Javier Ferrer <javier.m...@gmail.com>
La que he puesto no tira para casos simples como "mail...@sub.domain.com", aquí tienes otra versión que, a pesar de que no controla el que haya un punto antes de la @, sí que valida el que no hayan dos puntos seguidos.

--

Albert Garcia

unread,
Nov 28, 2013, 3:59:54 AM11/28/13
to sif...@googlegroups.com
Buenas!

Por las pruebas que hemos estado haciendo parece que en lo que a filter_var se refiere, el tema que nos preocupa estaría en la parte del dominio del email, y es que permite usar tanto un dominio, como un hostname (una palabra, aunque no haya TLD), como una IP... Por ejemplo, mimail@hostname. Al final "hostname" puede ser un valor tan "inválido" como, por ejemplo, estedominioquenoexiste.com. Con la implementación actual el primero no pasaría y el segundo sí, cuando en realidad no debería permitirse ninguno de los dos. :-) Pero para conseguir esto creo que la única alternativa es forzar la validación de DNS.

Con esto, siendo prácticos y centrándonos sólo en el tema sintaxis, si no veis claro el pasar a usar filter_var, vemos si podemos conseguir una expresión regular que añada a los controles actuales:

* NO permitir dos puntos seguidos (ya sea antes o después de la @). Ej. pepe..lopez@gmail.com
* NO permitir un punto al principio ni al final antes de la arroba Ej: .pepe...@gmail.com o pepelopez.@gmail.com
* NO permitir puntos después del símbolo del modificador "+". Ej: et+mi...@espacio.com

Tenemos una versión inicial que en principio parece controlar los casos que hemos estado comentando, pero os agradecería que le echáramos todos un repaso para ver que no haya algún otro caso descontrolado.


Besos,
--
Albert García Gibert
email. albert...@gibert.es
blog. http://obokaman.com
twitter. @obokaman


Javier Ferrer

unread,
Nov 28, 2013, 4:37:05 AM11/28/13
to sif...@googlegroups.com
Le hemos dado un par más de vueltas y nos ha quedado esta: https://www.debuggex.com/r/4bQ3BFQhi95vFWQJ

^(([a-z0-9_%\-]+\.?)+)?(\+([a-z0-9_%\-]+\.?)+)?[a-z0-9]@(([a-z0-9\-]+)?[a-z0-9]\.)+([a-z]{2}|com|edu|org|net|biz|info|name|aero|biz|info|jobs|travel|museum|name|cat|asia|coop|jobs|mobi|tel|pro|arpa|gov|mil)$

Básicamente comprueba cosas como:
Permitiendo:
¿Alguien con una batería de pruebas así molona para darle de comer? 

--
Javier Ferrer | Twitter | LinkedIn


2013/11/28 Albert Garcia <albert...@gibert.es>

--
You received this message because you are subscribed to a topic in the Google Groups "SIFO, PHP framework" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/sifophp/5o0tkI2nC44/unsubscribe.
To unsubscribe from this group and all its topics, send an email to sifophp+u...@googlegroups.com.
1C4.gif

Albert Lombarte

unread,
Nov 28, 2013, 5:34:18 AM11/28/13
to sif...@googlegroups.com
Albert,

Efectivamente un email puede parecer muy válido pero si no hay un servdor de email detrás, tu tía. Per al menos nuestro getEmail tiene que asegurar lo mázimo posible que no se va a hacer una comprobación via red a la primera de cambio. La comprovación de la DNS o el envío de email de confirmación es un paso más pero que no tiene que interferir en la efectividad del formato en sí.

Javier,

Mirando la expresión regular que me pasas veo que esto no cumple...
...cuando se usan modificadores, por ejemplo: mail.mod...@sub.dom.ain.com

Si la cambiamos debería incuir también los siguientes TLD de reciente aparición:

  • .int
  • .post
  • .xxx
Gracias!


2013/11/28 Javier Ferrer <javier.m...@gmail.com>
1C4.gif

Javier Ferrer

unread,
Nov 28, 2013, 5:57:24 AM11/28/13
to sif...@googlegroups.com
Jarl, tienes razón.

Realmente petaba por tener un sólo carácter como modificador, es decir: mail.mod...@sub.dom.ain.com sería válida pero mai...@domain.com no.

Con esta modificación ya no pasa esto :)

^(([a-z0-9_%\-]+\.?)+)?(\+(([a-z0-9_%\-]+\.?)|)+)?[a-z0-9]@(([a-z0-9\-]+)?[a-z0-9]\.)+([a-z]{2}|com|edu|org|net|biz|info|name|aero|biz|info|jobs|travel|museum|name|cat|asia|coop|jobs|mobi|tel|pro|arpa|gov|mil)$

--
Javier Ferrer | Twitter | LinkedIn


2013/11/28 Albert Lombarte <alom...@gmail.com>
1C4.gif

Albert Lombarte

unread,
Nov 28, 2013, 6:36:21 AM11/28/13
to sif...@googlegroups.com
Esta no va: mai...@domain.post xD

Faltan los 3 nuevos TLDs


2013/11/28 Javier Ferrer <javier.m...@gmail.com>
1C4.gif

Javier Ferrer

unread,
Nov 28, 2013, 6:38:21 AM11/28/13
to sif...@googlegroups.com

Done:
^(([a-z0-9_%\-]+\.?)+)?(\+(([a-z0-9_%\-]+\.?)|)+)?[a-z0-9]@(([a-z0-9\-]+)?[a-z0-9]\.)+([a-z]{2}|com|edu|org|net|biz|info|name|aero|biz|info|jobs|travel|museum|name|cat|asia|coop|jobs|mobi|tel|pro|arpa|gov|mil|int|post|xxx)$
32B.gif
1C4.gif

Albert Lombarte

unread,
Nov 28, 2013, 2:38:03 PM11/28/13
to sif...@googlegroups.com
Hola,

Lo he lanzado sobre bbdd de producción limitando a 10.000 emails esto es lo que he encontrado:

KO:  loquesea.-@ dominio.com 
KO:  maria_antonia_@ dominio.com 
KO:  tariroriquetivi_@ dominio.com 


2013/11/28 Javier Ferrer <javier.m...@gmail.com>
32B.gif
1C4.gif

Albert Garcia

unread,
Nov 28, 2013, 2:54:41 PM11/28/13
to sif...@googlegroups.com
En la expresión regular hemos forzado que la parte que precede a la @ deba terminar en alfanumérico:

^(([a-z0-9_%\-]+\.?)+)?(\+(([a-z0-9_%\-]+\.?)|)+)?[a-z0-9]@(([a-z0-9\-]+)?[a-z0-9]\.)+([a-z]{2}|com|edu|org|net|biz|info|name|aero|biz|info|jobs|travel|museum|name|cat|asia|coop|jobs|mobi|tel|pro|arpa|gov|mil|int|post|xxx)$

Si queremos incluir guiones (parece que el RFC822 lo permite), habría que incluirlo ahí mismo:

^(([a-z0-9_%\-]+\.?)+)?(\+(([a-z0-9_%\-]+\.?)|)+)?[a-z0-9\-_]@(([a-z0-9\-]+)?[a-z0-9]\.)+([a-z]{2}|com|edu|org|net|biz|info|name|aero|biz|info|jobs|travel|museum|name|cat|asia|coop|jobs|mobi|tel|pro|arpa|gov|mil|int|post|xxx)$

Parece que ya pasarían los emails que comentas: https://www.debuggex.com/r/gUKFgdkAjVNNMNL1

Salutti,

--
Albert García Gibert
email. albert...@gibert.es
blog. http://obokaman.com
twitter. @obokaman


32B.gif
1C4.gif

Albert Lombarte

unread,
Nov 28, 2013, 4:26:54 PM11/28/13
to sif...@googlegroups.com
Esta última ha pasado los 10.000 sin problemas.También pasa el caso +pe...@dominio.com que es correcto.

Por mi OK, dejad el modificador /i al final de la expresión.

Gracias!!


2013/11/28 Albert Garcia <albert...@gibert.es>
32B.gif
1C4.gif
Reply all
Reply to author
Forward
0 new messages