Java中的电子邮件地址验证

13

我正在研究检查字符串是否为有效电子邮件地址的最佳方式。现在我着迷于两种选择:使用javax.mail.internet.InternetAddress;或者使用Apache Commons EmailValidator,它内部使用复杂的正则表达式解析器。

我想知道在正确性方面从其中一种选择中挑选是否有任何优势,或者两者都可以吗?我知道InternetAddress在某些情况下不能有效地处理非ASCII字符。


我会使用Apache Commons,因为我认为正则表达式验证器没有任何问题。除了使用正则表达式之外,我不知道有更好的方法来验证电子邮件地址。你呢? - Icarus
请查看http://download.oracle.com/javaee/5/api/javax/mail/internet/InternetAddress.html。 - kuriouscoder
谢谢您提供的链接。您怎么知道库在内部不使用Regex表达式来验证电子邮件地址?如果没有使用,那真的比使用正则表达式更好吗?validate()方法并没有说它如何执行验证,它只是说“检查许多规则但不是所有有关RFC822的规则”。 - Icarus
我的问题非常简单--选择其中一个是否有任何陷阱? - kuriouscoder
没有任何陷阱,因为我确信两者都能适当地完成它们的任务(验证电子邮件地址)。 - Icarus
3个回答

31

您可以使用Apache Commons Validator库中的EmailValidator来实现此功能:

import org.apache.commons.validator.EmailValidator;
...

EmailValidator validator = EmailValidator.getInstance();
if (validator.isValid(email)) {
   // is valid, do something
} else {
   // is invalid, do something
}

isValid方法检查一个字段是否包含有效的电子邮件地址。

根据这个问题,这是最好的Java电子邮件地址验证方法。 什么是最好的Java电子邮件地址验证方法?


1
此验证器允许使用以下代码验证电子邮件:##$$$$#$%&&***SomeE@scom.comEmailValidator.getInstance(false).isValid(email); - Bilbo Baggins
1
我的错,根据此内容,这是有效的电子邮件地址,https://en.wikipedia.org/wiki/Email_address#Local-part - Bilbo Baggins
验证是否适用于由逗号或冒号分隔的多个收件人? - Mohammad Irfan

2

对于已经非常成熟的电子邮件地址格式而言,两种方法之间的区别微不足道。但是,五十年前,人们从未见过使用4个数字来编码年份的必要性,所以......

使用Apache Commons中的正则表达式唯一的“陷阱”是其验证电子邮件地址的功能不符合“Java标准”。作为开发人员,这在多大程度上会影响您?这取决于您有多么偏执。

另一方面,标准的Java实现可能效率较低。您需要构造一个InternetAddress并对其进行验证。查看JavaMail的源代码,我可以看到以下内容:

/**
 * Check that the address is a valid "mailbox" per RFC822.
 * (We also allow simple names.)
 *
 * XXX - much more to check
 * XXX - doesn't handle domain-literals properly (but no one uses them)
 */

“XXX”似乎是一种笔记或“待办事项”。


1
我刚测试了一下,显然在InternetAddress上的表现比使用EmailValidator要明显好。
package com.avaya.oss.server.errors;

import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;

import org.apache.commons.validator.EmailValidator;

public class TestValidationTypes {

    static String email = "test@testy.com";
    static int maxItr = 10000;

    public static void main(String[] args) throws AddressException {

        long start = System.currentTimeMillis();
        for (int i = 0; i < maxItr; i++) {
            EmailValidator.getInstance().isValid(email);
        }
        System.out.println("EmailValidator duration: " + (System.currentTimeMillis() - start));

        start = System.currentTimeMillis();
        for (int i = 0; i < maxItr; i++) {
            InternetAddress internetAddress = new InternetAddress(email);
            internetAddress.validate();
        }
        System.out.println("InternetAdress duration: " + (System.currentTimeMillis() - start));

    }

}

输出:

EmailValidator 持续时间: 1195

InternetAdress 持续时间: 67

结果是 EmailValidator 花费了大约20倍的时间:


1
user@localhost 被认为是有效的。 bla@bla 也被认为是有效的。 someone@[10.10.1.5] 也被认为是有效的。 我认为你会想要将它们视为无效。 因此,我认为花费20倍的时间是值得的。 - Saravanabalagi Ramachandran
对于那些几年后偶然发现这篇文章的人,JMail 比这两个选项都更快、更准确。此外,它还可以自定义,因此您可以将带有域文字(例如 user@localhost)的地址视为无效。 - Rohan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接