0

検証メールはオプションではありません:(

電子メール アドレスを検証するために使用する必要がある、非常に具体的な一連のルールがあります。Apache Commons ライブラリと JavaMail ライブラリを試しました。どちらも RFC 2822 に準拠していますが、私のルールでは無効なメールがいくつか通過します。私は正規表現(regexi?)で運を試してきましたが、役に立ちませんでした。分かってる。正規表現は最良の選択肢ではなく、多くの時間がかかり、複雑になる可能性があります。それでも、それほど難しくない用語で概説されたルールがあるので、この特定のインスタンス用にルールを構築するだけで十分だと考えました。

ルール:

  1. 電子メール アドレスのローカル部分は、次のいずれかを使用できます。
    • 大文字と小文字
    • 数字の 0 ~ 9
    • 特殊文字: , ! # $ % ^ & * ( ) ' ` + = - _ { } | 〜
    • ピリオド。ピリオドで開始または終了することはできません
    • 連続するピリオドを含めることはできません
  2. 電子メールのローカル部分とドメイン部分の間にアットマーク (@) が必要です
  3. ドメインには、文字、数字、アンダースコア、ピリオド、ハイフンのみを含める必要があります
    • ハイフンで始めることはできません
    • ハイフンで終わることはできません
    • 2 つの連続するハイフンを含めることはできません
  4. メールのドメイン部分と TLD 部分の間にはピリオドが必要です
    • TLD には文字のみを含める必要があります
    • TLD はピリオドで終わらせてはいけません

これまでのところ、次の正規表現を使用しようとしています。

^((?!.\.{2,}.)[^.][-a-zA-Z0-9_.\!\@\#\$\%\^\&\*\(\)\, \'\+\=\`\{\|\}\~\-]+[^.])@((?!.\-{2,}.)[^-_][-a-zA- Z0-9_.]+[^-_]\.[a-zA-z]+)$


^((?!.\.{2,}.)[^.][-a-zA-Z0-9_.!@#$%^&*(),'+=`{|}~-]+[^.])@((?!.\-{2,}.)[^-_][-a-zA-Z0-9_.]+[^-_]\.[a-zA-z]+)$

これは、無効な電子メール (justlikethat@gm--ail.com など) でまだ失敗しています。

正規表現で何が欠けているか、間違っていますか? 電子メールが正規表現なしで要件に準拠していることを確認する別の方法はありますか?

前もって感謝します!

PSこれはJavaであるため、上記の正規表現のすべてのエスケープ文字は二重にエスケープする必要があります(例:\.is \\.)。私は明らかに正規表現の第一人者ではないので、これを視覚化するためにRegexperも使用しています。

4

2 に答える 2

2

私は提案します:

@シンボルで分割します。最後の期間で分割します (String#substringとを使用String#lastIndexOf)。これで、ローカル部分、ドメイン、および TLD がすべて別々の文字列になりました。if ステートメントを使用して検証します。すべて(連続する 2 つのピリオド?)に適用されるルールがある場合は、分割する前にそれを行います。正しく理解するのも、理解するのも、維持するのもずっと簡単です。

ただし、本当に正規表現に固執したい場合は、私が見たいくつかのことを次に示します。

[^.]前の はである@必要があります(?<!\.)。そうでない場合、 の前の最後の文字は@ほぼ何でもかまいません。

.1 つの文字にすぎないため(?!.\-{2,}.)、 と(?!.\.{2,}.)はあなたが思っていることをしません。作るだけで.*治りそうです。また、探しているものの後に文字をチェックする必要はありません。

明示的には述べられていませんが、ドメインと TLD に 2 つの連続したピリオドを含めることはできないと思います。これが許可されている場合、正規表現の最初の部分(?!.*\.{2,}.*@)@.

を使用する場合String#matches^$は必要ありません。

不要な があり()ます。

最終的な正規表現:

(?!.*\.{2,})[^.][-a-zA-Z0-9_.!@#$%^&*(),'+=`{|}~-]+(?<!\.)@(?!.*\-{2,})[^-_][-a-zA-Z0-9_.]+[^-_]\.[a-zA-z]+

正規表現に固執することを選択した場合は、広範なコメントをお勧めします。

String regex =
          "(?!.*\\.{2,})" // doesn't contain 2 consecutive .'s
       // local part
          + "[^.]" // doesn't start with a .
          + "[-a-zA-Z0-9_.!@#$%^&*(),'+=`{|}~-]+" // valid chars for local part
          + "(?<!\\.)" // last char of local part isn't a .
       // at symbol
          + "@"
       // domain
          ...

やり過ぎのように思えるかもしれませんが、特に数か月間正規表現に触れていない場合は、数か月後にそれを維持しようとする場合は、持っていればよかったと思うでしょう。

于 2013-05-22T20:44:18.867 に答える
1

一般に、電子メールは単一の正規表現には複雑すぎるということです。SMTP サーバーが送信できるかどうかを確認することで、電子メール アドレスを簡単に確認できます。あなたはすでにそう言われています。

したがって、アドレスを事前に検証する必要があると仮定すると (そして、それが電子メール部分のみであり、Unicode 名などのすべての機能が含まれているわけではないと仮定すると)、私の推奨事項は次のようになります。

  1. 問題を小さな部分に分解する
  2. 各部分にメソッドを与える
  3. 各部分を (おそらくループで) 検証します。
  4. 正規表現と標準ロジックの組み合わせを使用して、有効であることを確認します(ルールに従って)

これは、次回コードを見る可哀想な吸盤が保守可能で理解できる、やや合理的なシステムを残すための唯一の現実的な方法です。

例えば

private void validateNamePart(String npart) {
  if (!npart.matches("")) {
    throw new .....;
  }
}

private void validateName(String name) {
  int parts = 0;
  for (String npart : name.split("\\.")) {
    validateNamePart(npart);
    parts++;
  }
  if (parts == 0) {
     throw ....;
  }
}

private void validateDomainPart(String dpart) {
  ....
}

private void validateDomain(String domain) {
  ....
}

public void validateEMail(String email) {
  String parts = email.split("@");
  if (parts.length == 2) {
    validateName(parts[0]);
    validateDomain(parts[1]);
  } else {
    throw ....
  }
}
于 2013-05-22T20:13:53.263 に答える