Vylepsenie validacie Form::EMAIL

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
westrem
Člen | 398
+
0
-

Zdravim,
tak na Nette som presiel tak pred 2 mesiacmi a mmtalne si stale dorabam urcite featuresy, ktore som v mojom predslom FM mal nakodene ale v Nette mi chybaju. Medzi ne patria aj oddelene Validatory, o ktore tu uz bolo viac komunitnych pokusov (najvyraznejsie asi od vrtak-cz ).

Na jeho rieseni sa mi vsak nepacilo, ze v podstate robil presun validacnych metod z TextBase niekam inam. Moje riesenie je proste samostatna staticka trieda so vsetkymi stavajuci Nette validatormi (miestami vylepsenymi), ktore sa daju plne pouzit v Nette\Forms alebo hocikde v modeli prip. v aplikacii.

Podme ale od rozsiahlejsieho uvodu priamo k veci. Pocas tohto prepisovania a vytvarania validatorov, som sa jednak inspiroval svojimi uz napisanymi funkciami a druhorak Davidovou validaciou v TextBase pripadne FormControl. Po napisani validatorov prislo na testy. Tu som narazil na dve chyby (chybky).

  1. popisujem v tomto threade
  2. ktora sa tyka validacie e-mailovych adries sa pokusim popisat tu

Pre validaciu e-mailovych adries som sa nechal inspirovat touto peknou strankou: Comparing E-mail Address Validating Regular Expressions

Je tam zoznam dostupnych regexpov na validaciu e-mailovych adries, pricom iba jeden z nich kompletne prejde testami (ten prvy uvedeny).

Schvalne som teda podrobil Nette validator tomuto testu. Vysledky su podla mna vcelku slusne, no nie 100% tak ako by mohli byt:

Toto by mali byt validne e-maily

- l3tt3rsAndNumb3rs@domain.com: true
- has-dash@domain.com: true
- hasApostrophe.o'leary@domain.org: true
- uncommonTLD@domain.museum: true
- uncommonTLD@domain.travel: true
- uncommonTLD@domain.mobi: true
- countryCodeTLD@domain.uk: true
- countryCodeTLD@domain.rw: true
- lettersInDomain@911.com: true
- underscore_inLocal@domain.net: true
- IPInsteadOfDomain@127.0.0.1: **false**
- IPAndPort@127.0.0.1:25: **false**
- subdomain@sub.domain.com: true
- local@dash-inDomain.com: true
- dot.inLocal@foo.com: true
- a@singleLetterLocal.org: true
- singleLetterDomain@x.org: true
- &*=?^+{}'~@validCharsInLocal.net: true
- foor@bar.newTLD: true

False znamena chybu, pretoze e-mail mal prejst

Toto by mali byt nevalidne e-maily

- missingDomain@.com: false
- @missingLocal.org: false
- missingatSign.net: false
- missingDot@com: false
- two@@signs.com: false
- colonButNoPort@127.0.0.1:: false
- : false
- someone-else@127.0.0.1.26: **true**
- .localStartsWithDot@domain.com: false
- localEndsWithDot.@domain.com: false
- two..consecutiveDots@domain.com: false
- domainStartsWithDash@-domain.com: false
- domainEndsWithDash@domain-.com: false
- numbersInTLD@domain.c0m: **true**
- missingTLD@domain.: false
- ! "#$%(),/;<>[]`|@invalidCharsInLocal.org: false
- invalidCharsInDomain@! "#$%(),/;<>_[]`|.org: false
- local@SecondLevelDomainNamesAreInvalidIfTheyAreLongerThan64Charactersss.org: false

True znamena chybu, pretoze e-mail nemal prejst

Verim, ze ked David tvoril regexp pre validaciu e-mailov, tak si poriadne nastudoval dane dokumenty (o com svedcia aj komentare pri kode a odkazy na konkretne RFC) avsak ocividne to nepokryva kompletny set (cim jeho validaciu nechcem zhadzovat, 4 chyby su podla mna este statocny vykon).

Bola by vsak snaha toto napravit a pouzit ten regexp co je na stranke preferovany ako jediny co presiel testami?

PaBi3
Bronze Partner | 62
+
0
-

Myslím, že ten regexp na e-maily commitoval Jakub Vrána.

Patrik Votoček
Člen | 2221
+
0
-

Občas si říkám že problematika validace e-mailové adresy by měla mít vlastní vědní obor (pokud nemá). Protože i to tebou navrhované řešení není dokonalé. A řešení z nette ho za jisté situace válcuje. Tou situací je IDN. Jakožto majitel IDN domény jsem to prostě musel otestovat. Test přikládám zde https://gist.github.com/565491

Jakub Nerad
Člen | 21
+
0
-

Validátor na email má spíš fungovat když se někdo omylem přepíše. Což teď funguje velmi dobře. Nějaká dokonalost u emailu je pomalu na vědeckou práci.

westrem
Člen | 398
+
0
-

Och ospravedlnujem sa Davidovi, nejak ma nenapadlo pozriet si (resp. s GitHubom si natolko este netykam aby som vobec vedel ako) kto to commitoval.

Avsak ako som vravel, nijak extremne mi nevadi sucasny stav, podla mna Nette so svojim validatorom odvadza dobru pracu, ja som ho len porovnal s niecim co som uz poznal.

Vrtak-cz napsal:

Pekny test, skusil som si a naozaj na IDN to pada, kdezto Nette pouziva superset IDN znakov. Vysledok je teda vlastne 50:50 (prijatie nevalidneho e-mailu je vzdy lepsie ako odmietnutie validneho).

Vedecka prace

Presne tak, miestami to zaraza aj mna, nechapem preco pre e-mail, co je tak strasne dlho zauzivana vec na internete neexistuje ujednoteny format a teda regexp.

Riesenie

Riesenie problemu je v podstate podla mna, jednoduche, staci sa pozriet, kde Jakub Vrana navrhol superset of IDN a ako ho pouziva a toto doplnit do toho „hrozneho regexpu“ nasledovne:

"/^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9\x80-\xFF]{1}[a-z0-9\x80-\xFF\-]{0,62}[a-z0-9\x80-\xFF]{1})|[a-z0-9\x80-\xFF])\.)+[a-z\x80-\xFF]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i"

Vrtak-cz: ak si vo svojom teste das tento regexp namiesto toho povodneho, prejdu aj IDN domeny a vsetko co ma byt zelene je zelene a zvysok je cerveny, co na to poviete?

David Grudl
Nette Core | 8228
+
0
-

Emailové adresy jako IPInsteadOfDomain@127.0.0.1 nejsou podporované záměrně. Takové adresy skutečně nikdo nemá. Smyslem formulářové validace je odhalit nesmyslné adresy, ačkoliv mohou být podle nějakého RFC platné.

jtousek
Člen | 951
+
0
-

David Grudl napsal(a):

Emailové adresy jako IPInsteadOfDomain@127.0.0.1 nejsou podporované záměrně. Takové adresy skutečně nikdo nemá. Smyslem formulářové validace je odhalit nesmyslné adresy, ačkoliv mohou být podle nějakého RFC platné.

Souhlasím, v tom případě má smysl opravovat maximálně tuto adresu:
numbersInTLD@domain.c0m