2011-12-17 4 views
0

좋은 전자 메일 유효성 검사 루틴을 찾은 후 this answer to a similar question을 찾았고 가능성이 가장 높은 후보로 결정되었습니다. 나는 또한 phpunit을 테스트를 내장전자 메일 유효성 검사가 작동하지 않음

class Email extends RegexMatch implements iface\Prop 
{ 
    const 
     /** 
     * Regular expression for validating email addresses 
     * 
     * This regex is meant to validate against RFC 5322 and was taken from 
     * a post on Stack Overflow regarding email validation (see the links) 
     * 
     * @link http://www.ietf.org/rfc/rfc5322.txt, https://stackoverflow.com/questions/201323/what-is-the-best-regular-expression-for-validating-email-addresses/1917982#1917982 
     */ 
     PATTERN = ' 
/(?(DEFINE) 
    (?<address>   (?&mailbox) | (?&group)) 
    (?<mailbox>   (?&name_addr) | (?&addr_spec)) 
    (?<name_addr>  (?&display_name)? (?&angle_addr)) 
    (?<angle_addr>  (?&CFWS)? < (?&addr_spec) > (?&CFWS)?) 
    (?<group>   (?&display_name) : (?:(?&mailbox_list) | (?&CFWS))? ; 
              (?&CFWS)?) 
    (?<display_name> (?&phrase)) 
    (?<mailbox_list> (?&mailbox) (?: , (?&mailbox))*) 

    (?<addr_spec>  (?&local_part) \@ (?&domain)) 
    (?<local_part>  (?&dot_atom) | (?&quoted_string)) 
    (?<domain>   (?&dot_atom) | (?&domain_literal)) 
    (?<domain_literal> (?&CFWS)? \[ (?: (?&FWS)? (?&dcontent))* (?&FWS)? 
           \] (?&CFWS)?) 
    (?<dcontent>  (?&dtext) | (?&quoted_pair)) 
    (?<dtext>   (?&NO_WS_CTL) | [\x21-\x5a\x5e-\x7e]) 

    (?<atext>   (?&ALPHA) | (?&DIGIT) | [!#\$%&\'*+-\/=?^_`{|}~]) 
    (?<atom>   (?&CFWS)? (?&atext)+ (?&CFWS)?) 
    (?<dot_atom>  (?&CFWS)? (?&dot_atom_text) (?&CFWS)?) 
    (?<dot_atom_text> (?&atext)+ (?: \. (?&atext)+)*) 

    (?<text>   [\x01-\x09\x0b\x0c\x0e-\x7f]) 
    (?<quoted_pair>  \\ (?&text)) 

    (?<qtext>   (?&NO_WS_CTL) | [\x21\x23-\x5b\x5d-\x7e]) 
    (?<qcontent>  (?&qtext) | (?&quoted_pair)) 
    (?<quoted_string> (?&CFWS)? (?&DQUOTE) (?:(?&FWS)? (?&qcontent))* 
         (?&FWS)? (?&DQUOTE) (?&CFWS)?) 

    (?<word>   (?&atom) | (?&quoted_string)) 
    (?<phrase>   (?&word)+) 

    # Folding white space 
    (?<FWS>    (?: (?&WSP)* (?&CRLF))? (?&WSP)+) 
    (?<ctext>   (?&NO_WS_CTL) | [\x21-\x27\x2a-\x5b\x5d-\x7e]) 
    (?<ccontent>  (?&ctext) | (?&quoted_pair) | (?&comment)) 
    (?<comment>   \((?: (?&FWS)? (?&ccontent))* (?&FWS)? \)) 
    (?<CFWS>   (?: (?&FWS)? (?&comment))* 
         (?: (?:(?&FWS)? (?&comment)) | (?&FWS))) 

    # No whitespace control 
    (?<NO_WS_CTL>  [\x01-\x08\x0b\x0c\x0e-\x1f\x7f]) 

    (?<ALPHA>   [A-Za-z]) 
    (?<DIGIT>   [0-9]) 
    (?<CRLF>   \x0d \x0a) 
    (?<DQUOTE>   ") 
    (?<WSP>    [\x20\x09]) 
) 

(?&address)/x'; 

    public function setConfig (array $config = array()) 
    { 
     $config = array_merge ($config, array ('needle' => self::PATTERN)); 
     return (parent::setConfig ($config)); 
    } 

    public function isValid() 
    { 
     return ((is_null ($this -> getData())) 
      || (parent::isValid())); 
    } 
} 

: 나는 이메일 확인을 위해 다음과 같은 클래스 (그것에서 상속 REGEXMATCH 클래스는 연관 구성 배열의 '바늘'키에 규정 된 정규 표현식에 대한 문자열의 유효성을 검사) 구현 다양한 소스 (주로 Wikipedia)에서 추출 된 유효하거나 유효하지 않은 이메일 주소의 다양한 순열에 대해이 클래스를 실행합니다.

클래스는 많은 평범한 경우에 기능을 수행하는 것처럼 보입니다. 그러나이 클래스는 유효하지 않다고 생각되는 일부 이메일을 전달하고 문제가있는 것으로 간주되어 일부는 실패합니다. 나는 아래를 나열했습니다

,536
  • this\ is\"really\"not\\[email protected] (무효로되어, 전달) (패스, 가정은 무효)

    PHP는 정규 표현식을 올바르게 파싱하는 것처럼 보이지만 오류, 경고 또는주의 사항을 내 보내지 않습니다. 또한 다른 모든 테스트 케이스 (7 개의 유효한 주소와 다른 2 개의 유효하지 않은 주소)가 통과되었거나 실패 했으므로 PHP (5.3.8) 버전이 여기에서 사용되는 정규식 구문을 지원하지 않기 때문에이 포트가 의심 스럽습니다. . 그러나 위양성과 위음성을 모두 가지고 있기 때문에 분명히 잘못된 것이 있습니다. 내 테스트 데이터가 올바르지 않습니다 (내가 주로 Wikipedia에서 추측 한 바와 같이) 또는 정규 표현식이 어떤 식 으로든 올바르지 않습니다.

    위의 정규 표현식이 맞습니까? 그렇지 않다면 어떤 수정을해야합니까? 맞다면 테스트 케이스에 문제가 있습니까?

    EDIT :이 클래스는 유효성 검사 클래스이므로 전자 메일 주소 만 포함 된 문자열 만 전달하면됩니다. 나는 비 전자 메일 주소 데이터 내에 유효한 전자 메일 주소가 포함 된 문자열을 전달하고 싶지 않습니다. 나는 당신이 ^pattern_goes_here$을 사용함으로써 그것을하는 것을 압니다. 그러나이 정규 표현식은 제가 과거에 작업 해 왔던 것보다 훨씬 진보적이며, ^와 $가 어디로 가야하는지 모르겠습니다. 당신도 그걸 도울 수 있다면 나는 그것을 감사 할 것입니다.

  • +0

    당신은 사용할 수 없습니다 :'filter_var ('[email protected] ', FILTER_VALIDATE_EMAIL)'? –

    +2

    사양이 매우 커서 정규식 전자 메일 발리 데이터 작성기가 매우 어렵다는 점에 유의하십시오. 모든 가능한 경우와 일치하는 단일 정규식이 있다고 생각하지 않습니다. – PeeHaa

    +0

    @GordonM : 당신에 관한 편집. 구분자 바로 앞에 그리고 앞에 놓으십시오. – PeeHaa

    답변

    2

    전자 메일 주소의 유효성을 완전히 확인하는 경우 매우 까다로운 비즈니스입니다.

    테스트를 완료하고이를 해결할 수있는 여러 가지 방법을 보여주는 목록이 있지만 모든 경우를 통과하지 못하는 목록입니다.

    http://fightingforalostcause.net/misc/2006/compare-email-regex.php

    최고의 점수 표현은 현재 마이클 Rushton하여 정규식을 기반으로 PHP의 filter_var()에서 사용하는 하나

    나는 강하게 당신 filter_var()

    를 사용하는 것이 좋습니다
    +0

    나는이 솔루션이 수치 적으로 더 성공적이라는 단순한 근거로이 솔루션과 함께 갈 것입니다 내 테스트 스위트와 함께. 그러나, 그것은 여전히 ​​실패합니다. 테스트를 통과해야합니다. – GordonM

    1

    ^$ 앵커를 추가하려는 경우이 장소가됩니다 :

    ^(?&address)$ /x'; 
    

    이메일 테스트 케이스 리소스를 확인해야합니다. 누군가가 RFC에서 BNF 선언을 번역하여이 정규 표현식 서브 루틴을 더 많이 신뢰할 것이라고 믿습니다.

    +0

    나는 그것과 같은 것이 될 것이라고 추측했다. 라인 앵커를 추가하면 3 개의 오 탐지 (통과해야하지만 대신 실패해야하는 주소)가 발생하지만 단 하나의 false negative (실패 할 때 빈 문자열이 전달됩니다). 나는 다른 솔루션과 함께 갈 것이라고 생각하지만 단순히 테스트 데이터에 대해 2 개의 오탐 (false positive)과 false negative (false negative)가 없기 때문입니다. 즉, 테스트 데이터가 의심 스러울 수 있으며, 그 주소의 유효성과 관련된 소스의 단어 만 있습니다. 신뢰할 수있는 테스트 데이터 소스를 알고 있다면 감사하게 생각합니다. – GordonM

    +0

    결국에는'^ (? & mailbox) $/x'를 대안으로 사용할 수 있습니다. 아마도 더 제한적 일 것입니다. 그러나 잘못된 음성에 대해서는 생각할 필요가 없습니다. 하지만 내장 된 filter_var 정규식은 나에게도 가장 충분합니다. – mario

    관련 문제