メールアドレス形式の扱いはサービス単位で異なり、定まっていないので、メールアドレスの妥当性を判定する時に正規表現を使うことが多くなると思います。
基本的にはRFC5321かRFC5322、次点でRFC822に準拠したフォーマットが妥当だとは思いますが、すでに取得されているアドレスが存在するため表記はサービス毎に見直し設定していく必要があります。
単純表現
現在多くのサービスでは、「+_.-」の記号を使用したり、「input type="email"」の形式で入力を制御しているものを見かけます。
「input type="email"」とおまけでAndroidで使われている形式。
import java.util.Scanner; public class ValidatingEmail { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("Enter your Email: "); String phone = sc.next; String regex = "^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+$"; // RFC5321に近いinput type="email"を使う場合↓ // "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" // Androidで使われるメールアドレス判定↓ // "[a-zA-Z0-9\+\.\_\%\-\+]{1,256}\@[a-zA-Z0-9][a-zA-Z0-9\-]{0,64}(\.[a-zA-Z0-9][a-zA-Z0-9\-]{0,25})+" boolean result = phone.matches(regex); if(result) { System.out.println("Given email-id is valid"); } else { System.out.println("Given email-id is not valid"); } } }
//出力 Enter your Email: test!?@gmail.com Given email-id is not valid
「+_.-」の正規表現で簡易記述でよく見られる形式。
public static final Pattern VALID_EMAIL_ADDRESS_REGEX = Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE); public static boolean isEmailValidate(String emailStr) { Matcher matcher = VALID_EMAIL_ADDRESS_REGEX.matcher(emailStr); return matcher.find(); }
Apache Commons Validator
Apache Commons Validatorのパッケージには、いくつかの標準検証が含まれています。
検証メソッドを提供するEmailValidatorクラスを使用して、RFC822標準に従って電子メールアドレスを検証できます。
https://commons.apache.org/proper/commons-validator/
import org.apache.commons.validator.routines.EmailValidator; // Java program to validate email in Java class Main { public static boolean emailValidator(String email) { // Get an EmailValidator EmailValidator validator = EmailValidator.getInstance(); // Validate specified String containing an email address if (!validator.isValid(email)) { return false; } return true; } public static void main(String[] args) { String email = "no-reply@techiedelight.com"; // Validate an email address if (emailValidator(email)) { System.out.println("The email address " + email + " is valid"); } else { System.out.println("The email address " + email + " is invalid"); } } }
RFCで公開されている正規表現
ガチガチのRFC5322かRFC5321、またはRFC822の正規表現はとても長いので、直して使うのはメンテを考えるとおすすめしません。
RFC822
RFC-822に完全に準拠した電子メールの正規表現は、とても巨大なものです。
Javaで書き直すのは長大すぎるので、RFC822に準拠しているInternetAddressを使う事を検討して下さい。
ユーザーのメールアドレスを入力する際、InternetAddressのコンストラクタに渡すことで検証を行うことができます。
入力値がRFC822に準拠していない場合、例外がスローされます。
public static boolean isValidEmailAddress(String aEmailAddress){ if (aEmailAddress == null) return false; boolean result = true; try { InternetAddress emailAddr = new InternetAddress(aEmailAddress); if (! hasNameAndDomain(aEmailAddress)) { result = false; } } catch (AddressException ex) { result = false; } return result; }
RFC5322
RFC5322はRFC822の更新版であり、電子メール検証のための正規表現を提供しています。
比較的単純な正規表現で、メールに含まれるすべての文字を許可します。
ただし、パイプ文字(|)とシングルクォート(')は許可すべきではありません。
これらは、クライアントサイトからサーバーに渡されたときにSQLインジェクションのリスクになる可能性があるからです。
//RFC 5322 //RFC 5322に準拠して簡易表現にした正規の電子メールアドレス regexp5322_1 = "^[a-zA-Z0-9_!#$%&'*+/=?`{|}~^.-]+@[a-zA-Z0-9.-]+$"; //RFC 5322 //電子メール正規表現 RFC 5322公式標準を踏襲型 regexp5322_2 = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])";
RFC 5321
RFC 5321はホスト名とIPアドレスの両方に関しての扱いが寛大なため注意が必要です。
-
Javaの正規表現を使用してRFC 5321に準拠したメールアドレスを確認する
RFC 5321:Simple Mail Transfer Protocol(SMTP)はメールサーバ間におけるメッセージの転送方式を定めた標準仕様です。 https://tools.ietf.org ...
Gmail用のケース
Gmailにのみ適用される特殊なケースがあります。
それは、メールのローカル部分に+文字の使用を許可する事です。
Gmailドメインの場合、username+something@gmail.comとusername@gmail.comの2つのメールアドレスは同じです。
public static void main(String []args){ String emailAddress = "username+something@domain.com"; String regexPattern = "^(?=.{1,64}@)[A-Za-z0-9\\+_-]+(\\.[A-Za-z0-9\\+_-]+)*@"+"[^-][A-Za-z0-9\\+-]+(\\.[A-Za-z0-9\\+-]+)*(\\.[A-Za-z]{2,})$"; boolean result = emailAddress.matches(regexPattern); if(result) { System.out.println("Gmail is valid"); } else { System.out.println("Gmail is not valid"); } } //Gmail is valid
最後に
自前のメールアドレスポリシーがある場合は正規表現で実装するしかありませんが、正規表現などを使って独自にメールアドレスパーサーを実装することは、ほとんどの場合あまり良くない考えです。
長く運用すると、詳細を正しく理解するの事が難しくなり、間違いを犯す可能性が高くなるからです。
さらに多くの場合、実運用に入るまで記述の間違いだけでなく、運用方針の間違いに気づくことがないのも問題です。
そういった運用経験から、海外の識者は昔Javaの電子メールの検証を、RFC822に準拠しているInternetAddressに基づくものを推していました。現代だと許容幅が広過ぎるかもしれません。
おまけ
正規表現チェッカー
https://www.regexplanet.com/advanced/java/index.html
このサイトは対応言語が多く、インプットで使えるワードが多いためテストがし易く非常に検証しやすいです。
また、入力できる正規表現の文字数も多く、他のチェッカーサイトだと桁が溢れるものも検証できるのが優れものです。