Javaの正規表現を使用して有効なメールアドレスを確認する

Java 正規表現

Javaの正規表現を使用して有効なメールアドレスを確認する

メールアドレス形式の扱いがサービス単位で異なり、定まっていないので、メールアドレスの妥当性を判定する時に正規表現を使うことが必然的に多くなると思います。

基本的にはRFC5321かRFC5322に準拠したフォーマットが妥当だとは思いますが、すでに取得されているアドレスが存在するため表記はサービス毎に見直し設定していく必要があります。

単純表現

一般的に現在使えそうな記号+_.-の判定かinput type="email"の形で入力制御をしているものを見かけます。

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に準拠したメールアドレスを確認する
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

このサイトは対応言語が多く、インプットで使えるワードが多いためテストがし易く非常に検証しやすいです。

また、入力できる正規表現の文字数も多く、他のチェッカーサイトだと桁が溢れるものも検証できるのが優れものです。

  • この記事を書いた人

朝倉卍丸

シングルモルトスコッチなどのお土産を持ってきた人を助けるのが好きです。まあ、昔ながらの方法でやりたいこともありますよね。

-Java, 正規表現