2011-12-17 20 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)から抽出された有効な電子メールアドレスと無効な電子メールアドレスのさまざまな置換に対してこのクラスを実行します。

クラスは多くの世俗的なケースで機能しているようですが、無効であると思われる電子メールをいくつか渡して問題が発生しています。私は、以下のそれらをリストアップしました:

  • much."more\ unusual"@example.com(失敗し、有効であるために仮定)
  • "(),:;<>[\]@example.com(無効ことになって、渡し)
  • just"not"[email protected](渡し、無効であると仮定)
  • [email protected]@[email protected] (通過し、無効であると想定)
  • 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

最高のスコアを持つ式は、現在、マイケル・ラッシュトンで正規表現に基づいているPHPのにfilter_var()、で使用されるものである

は、私は強くあなたがfilter_var()

を使用することをお勧め
+0

私はそれが数値的により成功した単純な根拠私のテストスイートでは、しかし、それはまだ失敗しますそれが通過すべき2つのテスト。 – GordonM

1

^$のアンカーを追加する場合は、これが場所になります。

^(?&address)$ /x'; 

また、メールテストケースのリソースを確認する必要があります。誰かがBNF宣言をRFCから翻訳して書いたので、私はこれらの正規表現のサブルーチンをもっと信頼するでしょう。

+0

私はそれがそうであることを推測しました。行アンカーを追加すると、3つの誤検出(アドレスは合格しても失敗する)が発生しますが、偽陰性は1つのみです(失敗すると空文字列が渡されます)。私は、他のソリューションに行くつもりだと思っていますが、それは2つの偽陽性と私のテストデータに対して偽陰性がないという事実のためだけです。つまり、テストデータが疑わしいと思うかもしれません。私はそのアドレスがどれくらい有効であるかに関するソースの言葉しか持っていません。あなたが信頼できるテストデータのソースを知っていれば、それに感謝します。 – GordonM

+0

あなたは最終的に '^(?&mailbox)$/x'を代替として試してみることができます。おそらくより制限的です。しかし、偽陰性については考えがありません。 - しかし、組み込みのfilter_var正規表現も私にとって最も十分だと思われます。 – mario

関連する問題