2011-12-17 32 views
0

找到好的電子郵件驗證程序後,我發現this answer to a similar question,並認定它看起來最有可能成爲候選人。我實現爲電子郵件驗證以下類(它繼承的REGEXMATCH類驗證對正則表達式的字符串作爲一個關聯配置數組的「針」鍵提供):無法通過電子郵件驗證進行工作

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())); 
    } 
} 

我還內置了PHPUnit的測試運行這個類對各種來源(主要是維基百科)撲滅的有效和無效的電子郵件地址排列。

該類似乎在很多更平常的情況下起作用,但它遇到了一些問題,因爲它傳遞了一些應該是無效的電子郵件,並且失敗了一些應該沒問題的電子郵件。我列出了他們下面:

PHP似乎正確解析正則表達式,它不會發出任何錯誤,警告或通知。另外,我所有其他的測試用例(其他7個有效地址和另外2個無效的地址)都應該是合格或不合格的,所以我懷疑這是因爲我的PHP版本(5.3.8)不支持這裏使用的正則表達式語法。但由於我有誤報和誤報,顯然有些問題。要麼我的測試數據不正確(正如我所說,我大多是從維基百科剔除的),或者正則表達式在某種程度上是不正確的。

上面輸入的正則表達式正確嗎?如果不是,需要修正什麼?如果它是正確的,那麼我的測試用例是否有問題?

編輯:我也忘了提及,因爲這是一個驗證類,它只需要傳遞包含電子郵件地址的字符串而沒有別的。我不想在非電子郵件地址數據中傳遞包含有效電子郵件地址的字符串。我知道你通過使用^pattern_goes_here$來做到這一點,但是這個正則表達式比我過去使用過的大多數更加先進,而且我不確定^和$應該在哪裏。如果你也可以提供幫助,我會很感激。

+0

你不能使用:'filter_var('[email protected]',FILTER_VALIDATE_EMAIL)'? – 2011-12-17 21:55:48

+2

請注意,由於規格非常大,因此很難製作正則表達式電子郵件驗證程序!我不認爲有一個匹配所有可能的情況的單一正則表達式。 – PeeHaa 2011-12-17 21:59:02

+0

@GordonM:關於你編輯。就像通常那樣,將它放在分隔符後面和分隔符之前。 – PeeHaa 2011-12-17 22:03:45

回答

2

完全驗證電子郵件地址是一個棘手的業務。

下面是一個列表,包含測試,顯示不同的方式來處理它,但沒有一個會通過所有的情況。

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

與最好成績的表現是目前PHP的filter_var(),這是由邁克爾·拉什頓基於正則表達式中使用的

我強烈建議你使用filter_var()

+0

我打算用這個解決方案的簡單理由,它在數值上更成功與我的測試套件,但它仍然失敗它應該通過一些測試。 – GordonM 2011-12-18 07:07:28

1

如果你想添加^$錨點,這將是這個地方:

^(?&address)$ /x'; 

您還需要驗證您的電子郵件測試用例資源。我會更信任那些正則表達式子例程,因爲有人通過翻譯RFC中的BNF聲明來寫它。

+0

我猜想它會是這樣的,感謝符合。添加行錨會導致3個誤報(應該通過但失敗的地址),但只有一個錯誤否定(當它應該失敗時通過空字符串)。我想我會和其他的解決方案一起使用,只是因爲它只有2個誤報,並且沒有針對我的測試數據的假陰性。也就是說,測試數據可能是可疑的,我只有關於這些地址的有效性的消息來源。如果您知道測試數據的可靠來源,我會很感激。 – GordonM 2011-12-18 07:06:30

+0

您最終可以嘗試使用'^(?&mailbox)$/x'作爲替代方案,這可能更具限制性。然而,不知道有關假陰性。 - 但內置的filter_var正則表達式對我來說似乎也是最充分的。 – mario 2011-12-18 07:09:54

相關問題