しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

.NET Framework の正規表現とメールアドレス検証に悩まされた件

今週は .NET Framework の正規表現とメールアドレス検証に目いっぱい悩まされました。事の顛末を説明すると以下のような感じ。

正規表現

Regex クラスはデフォルトでは文字クラスの扱いなどが、ECMAScript の挙動とは異なるので悩みました。

コード例を出して説明すると、電話番号のように数値(とハイフンとか)のみ入力可能にする検証を正規表現で書いていたわけですよ。

public class User
{
    // 03-1234-5678 という電話番号を期待
    [RegularExpression(@"\d{2,4}\-\d{1,5}\-\d{4}")]
    public string PhoneNumber { get; set; }
}

こう書くと、半角数字しか入力できないと思うじゃないですか。しかし .NET Framework の正規表現では \d は数字にマッチします。つまり、半角と全角の両方にマッチしてしまうんですよね。

具体例を挙げると、以下の両方がこの検証では入力可能なわけです。

  • 03-1234-5678
  • 03-1234-5678

Twitter で呟くと数人の方から RegexOptions.ECMAScript フラグを付けると半角にしかマッチしなくなると教えてもらいましたが、RegularExpression 属性はパターンしか指定できないので、新しく検証属性を作るしかないといった状態です。

この仕様では誰も幸せにならないし、ASP.NET MVC のクライアントサイド検証を有効にしている場合には、クライアントサイド検証の結果とサーバサイド検証の結果が異なる*1という、不幸に拍車がかかってしまう状態でしたので Connect でフィードバックしておきました。

Behavior of RegularExpression attributes and client-side validation of ASP.NET MVC is different | Microsoft Connect

せめて設定で変更可能にしてほしかったです。

メールアドレス検証

そして、この前日には .NET 4.5 で追加された EmailAddress 属性が、マルチバイト文字列を含んでいても有効なメールアドレスだと判定する仕様だったので悩みました。

コード例を出して説明すると、正しいメールアドレスであることの検証を EmailAddress 属性を使って行っていたわけですよ。

public class User
{
    // foo@bar.com という普通のメールアドレスを期待
    [EmailAddress]
    public string EmailAddress { get; set; }
}

このように EmailAddress 属性を使って検証を行うと、以下のようにマルチバイト文字列を含んだメールアドレスも有効だと判定されます。

  • あああ@domain.com

少し調べてみると、.NET 4.5 から System.Net.Mail 周りは国際化メールアドレス (EAI) に対応したらしく、この関係で EmailAddress 属性もマルチバイトを通すようになっているのかもしれません。

電子メール アドレスの国際化 (EAI) のサポート。 詳細については、「System.Net.Mail」を参照してください。

.NET Framework 4.5 の新機能

そして EAI 自体はつい最近、仕様が標準化されたらしいです。

電子メールにおける国際化の概要 | 2013年 | ドメイン名関連会議報告 | ドメイン名関連情報 | JPRS

JPRS め、マジで余計なことしやがって…。

しかし、標準化されたばかりで誰も使っていないような仕様に従った検証など、これまた誰も幸せにならないと思ったので、こっちも Connect でフィードバックしておきました。

EmailAddressAttribute has allowed multi-byte string. | Microsoft Connect

EAI の対応はしてもいいけど、黎明期まで達していないんだから、設定か何かで切り替えできるようにして欲しかったですね。

*1:当たり前ながら JavaScript の正規表現は ECMAScript の挙動だから