{"action":"created","issue":{"url":"https://api.github.com/repos/phalcon/cphalcon/issues/3227","labels_url":"https://api.github.com/repos/phalcon/cphalcon/issues/3227/labels{/name}","comments_url":"https://api.github.com/repos/phalcon/cphalcon/issues/3227/comments","events_url":"https://api.github.com/repos/phalcon/cphalcon/issues/3227/events","html_url":"https://github.com/phalcon/cphalcon/issues/3227","id":54381773,"number":3227,"title":"Email Validation","user":{"login":"sergeyklay","id":1256298,"avatar_url":"https://avatars.githubusercontent.com/u/1256298?v=3","gravatar_id":"","url":"https://api.github.com/users/sergeyklay","html_url":"https://github.com/sergeyklay","followers_url":"https://api.github.com/users/sergeyklay/followers","following_url":"https://api.github.com/users/sergeyklay/following{/other_user}","gists_url":"https://api.github.com/users/sergeyklay/gists{/gist_id}","starred_url":"https://api.github.com/users/sergeyklay/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sergeyklay/subscriptions","organizations_url":"https://api.github.com/users/sergeyklay/orgs","repos_url":"https://api.github.com/users/sergeyklay/repos","events_url":"https://api.github.com/users/sergeyklay/events{/privacy}","received_events_url":"https://api.github.com/users/sergeyklay/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":20,"created_at":"2015-01-14T21:49:46Z","updated_at":"2015-07-06T20:56:05Z","closed_at":null,"body":"### Intro\r\n\r\nAfter a little research it became apparent that the current validators using `FILTER_VALIDATE_EMAIL` is not quite perfect (`Phalcon\\Mvc\\Model\\Validator\\Email` and `Phalcon\\Validation\\Validator\\Email`).\r\n\r\nBelow I will give a small example test.\r\n\r\n### Emails\r\n\r\nThese and many other, more exotic, but real email addresses are valid (see [RFC822](http://www.ietf.org/rfc/rfc0822.txt?number=822), [RFC2822](http://tools.ietf.org/html/rfc2822), [RFC2821](http://tools.ietf.org/html/rfc2821), [RFC3696](http://tools.ietf.org/html/rfc3696))\r\n```\r\n\"Joe\\\\Blow\"@example.com\r\njohn@doe.com\r\njohn.doe@site.com\r\njohn_doe@site.com\r\njohn_doe@domain.site.com\r\njohn@doe-site.com\r\n\"Abc@def\"@example.com\r\nj.o.h.n@d.o.e.com\r\nisposable.style.email.with+symbol@example.com\r\njohn@localhost\r\nj.o.h.n@my.c\r\n\"Fred Bloggs\"@example.com\r\n```\r\n\r\n### Tests\r\n\r\nLet us proceed for tests\r\n\r\n```php\r\n<?php\r\n\r\nfunction validateViaRegexp($email, $strict = false)\r\n{\r\n    if (mb_strlen($email) > 254) {\r\n        return false;\r\n    }\r\n\r\n    if ($strict) {\r\n        $qtext = '[^\\\\x0d\\\\x22\\\\x5c\\\\x80-\\\\xff]';\r\n        $dtext = '[^\\\\x0d\\\\x5b-\\\\x5d\\\\x80-\\\\xff]';\r\n        $atom  = '[^\\\\x00-\\\\x20\\\\x22\\\\x28\\\\x29\\\\x2c\\\\x2e\\\\x3a-\\\\x3c\\\\x3e\\\\x40\\\\x5b-\\\\x5d\\\\x7f-\\\\xff]+';\r\n        $pair  = '\\\\x5c[\\\\x00-\\\\x7f]';\r\n\r\n        $domain_literal = \"\\\\x5b($dtext|$pair)*\\\\x5d\";\r\n        $quoted_string  = \"\\\\x22($qtext|$pair)*\\\\x22\";\r\n        $sub_domain     = \"($atom|$domain_literal)\";\r\n        $word           = \"($atom|$quoted_string)\";\r\n        $domain         = \"$sub_domain(\\\\x2e$sub_domain)*\";\r\n        $local_part     = \"$word(\\\\x2e$word)*\";\r\n\r\n        $expression     = \"/^$local_part\\\\x40$domain$/D\";\r\n    } else {\r\n        $expression = '/^[-_a-z0-9\\'+*$^&%=~!?{}]++(?:\\.[-_a-z0-9\\'+*$^&%=~!?{}]+)*+@(?:(?![-.])[-a-z0-9.]+(?<![-.])\\.[a-z]{2,6}|\\d{1,3}(?:\\.\\d{1,3}){3})$/iD';\r\n    }\r\n\r\n    return (bool) preg_match($expression, (string) $email);\r\n}\r\n\r\nfunction validateViaFilter($email)\r\n{\r\n    return (bool) filter_var($email, FILTER_VALIDATE_EMAIL);\r\n}\r\n\r\n$emails = [\r\n    '\"Joe\\\\Blow\"@example.com',\r\n    'john@doe.com',\r\n    'john.doe@site.com',\r\n    'john_doe@site.com',\r\n    'john_doe@domain.site.com',\r\n    'john@doe-site.com',\r\n    '\"Abc@def\"@example.com',\r\n    'j.o.h.n@d.o.e.com',\r\n    'isposable.style.email.with+symbol@example.com',\r\n    'john@localhost',\r\n    'j.o.h.n@my.c',\r\n    '\"Fred Bloggs\"@example.com'\r\n];\r\n\r\n\r\necho 'Validate Via Regexp (non strict)<br>';\r\n$start = microtime(true);\r\nforeach ($emails as $email) {\r\n    echo(sprintf('%s is valid: %s<br>', $email, validateViaRegexp($email, false) ? 'TRUE' : 'FALSE'));\r\n}\r\necho(sprintf('Total time: %.10f sec.<hr>', microtime(true) - $start));\r\n\r\n\r\necho 'Validate Via Regexp (strict)<br>';\r\n$start = microtime(true);\r\nforeach ($emails as $email) {\r\n    echo(sprintf('%s is valid: %s<br>', $email, validateViaRegexp($email, true) ? 'TRUE' : 'FALSE'));\r\n}\r\necho(sprintf('Total time: %.10f sec.<hr>', microtime(true) - $start));\r\n\r\n\r\necho 'Validate Via Filter<br>';\r\n$start = microtime(true);\r\nforeach ($emails as $email) {\r\n    echo(sprintf('%s is valid: %s<br>', $email, validateViaFilter($email) ? 'TRUE' : 'FALSE'));\r\n}\r\necho(sprintf('Total time: %.10f sec.<hr>', microtime(true) - $start));\r\n```\r\n\r\n### Output\r\n\r\n```\r\nValidate Via Regexp (non strict)\r\n\"Joe\\Blow\"@example.com is valid: FALSE\r\njohn@doe.com is valid: TRUE\r\njohn.doe@site.com is valid: TRUE\r\njohn_doe@site.com is valid: TRUE\r\njohn_doe@domain.site.com is valid: TRUE\r\njohn@doe-site.com is valid: TRUE\r\n\"Abc@def\"@example.com is valid: FALSE\r\nj.o.h.n@d.o.e.com is valid: TRUE\r\nisposable.style.email.with+symbol@example.com is valid: TRUE\r\njohn@localhost is valid: FALSE\r\nj.o.h.n@my.c is valid: FALSE\r\n\"Fred Bloggs\"@example.com is valid: FALSE\r\nTotal time: 0.0000591278 sec.\r\n---------------------------------------------------------------------------------------\r\nValidate Via Regexp (strict)\r\n\"Joe\\Blow\"@example.com is valid: TRUE\r\njohn@doe.com is valid: TRUE\r\njohn.doe@site.com is valid: TRUE\r\njohn_doe@site.com is valid: TRUE\r\njohn_doe@domain.site.com is valid: TRUE\r\njohn@doe-site.com is valid: TRUE\r\n\"Abc@def\"@example.com is valid: TRUE\r\nj.o.h.n@d.o.e.com is valid: TRUE\r\nisposable.style.email.with+symbol@example.com is valid: TRUE\r\njohn@localhost is valid: TRUE\r\nj.o.h.n@my.c is valid: TRUE\r\n\"Fred Bloggs\"@example.com is valid: TRUE\r\nTotal time: 0.0000748634 sec.\r\n---------------------------------------------------------------------------------------\r\nValidate Via Filter\r\n\"Joe\\Blow\"@example.com is valid: TRUE\r\njohn@doe.com is valid: TRUE\r\njohn.doe@site.com is valid: TRUE\r\njohn_doe@site.com is valid: TRUE\r\njohn_doe@domain.site.com is valid: TRUE\r\njohn@doe-site.com is valid: TRUE\r\n\"Abc@def\"@example.com is valid: TRUE\r\nj.o.h.n@d.o.e.com is valid: TRUE\r\nisposable.style.email.with+symbol@example.com is valid: TRUE\r\njohn@localhost is valid: FALSE\r\nj.o.h.n@my.c is valid: TRUE\r\n\"Fred Bloggs\"@example.com is valid: FALSE\r\nTotal time: 0.0001180172 sec.\r\n---------------------------------------------------------------------------------------\r\n```\r\n\r\n<bountysource-plugin>\r\n---\r\nWant to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/7769600-email-validation?utm_campaign=plugin&utm_content=tracker%2F50707&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F50707&utm_medium=issues&utm_source=github).\r\n</bountysource-plugin>"},"comment":{"url":"https://api.github.com/repos/phalcon/cphalcon/issues/comments/118995517","html_url":"https://github.com/phalcon/cphalcon/issues/3227#issuecomment-118995517","issue_url":"https://api.github.com/repos/phalcon/cphalcon/issues/3227","id":118995517,"user":{"login":"egulias","id":791806,"avatar_url":"https://avatars.githubusercontent.com/u/791806?v=3","gravatar_id":"","url":"https://api.github.com/users/egulias","html_url":"https://github.com/egulias","followers_url":"https://api.github.com/users/egulias/followers","following_url":"https://api.github.com/users/egulias/following{/other_user}","gists_url":"https://api.github.com/users/egulias/gists{/gist_id}","starred_url":"https://api.github.com/users/egulias/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/egulias/subscriptions","organizations_url":"https://api.github.com/users/egulias/orgs","repos_url":"https://api.github.com/users/egulias/repos","events_url":"https://api.github.com/users/egulias/events{/privacy}","received_events_url":"https://api.github.com/users/egulias/received_events","type":"User","site_admin":false},"created_at":"2015-07-06T20:56:05Z","updated_at":"2015-07-06T20:56:05Z","body":"Sorry for the delay. I have a doubt. Do I have to port the validator into .zep_ If not, can you point me to the docs?\r\nThanks!"}}