我需要验证电子邮件和域名。我只需要正式验证,不需要whois或其他形式的域查找。
目前我正在使用apache' s commons-validator v1.4.0
不幸的是,我的客户使用新的gTLD,例如DomainValidator类尚不支持的.bike或.productions。 有关详细信息,请参阅Apache's Jira issue。
我可以轻松地在Maven POM中包含任何合理的替代方案吗?
答案 0 :(得分:7)
如果您不关心国际化地址,可以更改地址的最后部分,并继续使用Apache公共地址。
此方法基于以下事实:无论TLD是什么,整个域名的有效性等同于域名替换为com
的相同域名的有效性。例如:
abc.def.com
有效。同样,abc.def.name
,abc.def.xx--kput3i
,abc.def.uk
也有效。ab,de.com
无效。同样,ab,de.name
,ab,de.xx-kput3i
,ab,de.uk
无效。所以不要打电话
return EmailValidator.getInstance().isValid(userEmail);
你可以打电话
if ( userEmail == null ) {
return false;
}
return EmailValidator.getInstance().isValid(userEmail.trim().replaceFirst("\\.\\p{Alpha}[\\p{Alnum}-]*\\p{Alnum}$", ".com"));
说明
"\\.\\p{Alpha}[\\p{Alnum}-]*\\p{Alnum}$"
检查TLD部分:它位于字符串的末尾(由于$
),它以点开头,不包含其他点,并且它符合标准:以ASCII Alpha字符开头,后跟零个或多个字母数字或破折号,并以字母数字字符结尾。trim()
因为到目前为止,如果您使用EmailValidator
,它会在地址之前和之后允许空格。删除空格只会使更换TLD变得更容易,就地址的有效性而言,这并不重要。String.replaceFirst()
将按原样返回。它仍然有效,因为x@[n.n.n.n]
格式的电子邮件地址n.n.n.n.
是有效的IP地址。所以基本上,如果您没有找到顶级域名,请让EmailValidator
自行决定有效性问题。david@galaxy.hoopie-frood
这样的电子邮件将被视为合法邮件,但IANA尚未拥有该顶级域名。检查域名类似,没有trim()
部分:
if (userDomain == null ) {
return false;
}
return DomainValidator.getInstance().isValid(userDomain.replaceFirst("\\.\\p{Alpha}[\\p{Alnum}-]*\\p{Alnum}$"));
我也尝试过JavaMail的电子邮件地址验证,但我不是很喜欢它:它允许完全无效的域名,例如net-name.net-
(以破折号结尾)或IP地址(不允许使用没有方括号的电子邮件),它只适用于电子邮件地址,而不适用于域名。
如果您需要检查国际化域名和电子邮件,则会有所不同。检查国际化域名(例如元気。テスト
)很容易。您需要做的就是使用java.net.IDN.toASCII()
将它们转换为ASCII(我的示例域产生xn--z4qx76d.xn--zckzah
- 这是一个有效的TLD),然后按照我上面的说法进行操作。
国际化的电子邮件是另一回事。如果本地部分是ASCII,则可以将域部分转换为ASCII。如果必须显示电子邮件地址,则需要使用Unicode版本,如果必须发送电子邮件,则使用ASCII版本。
但最近也为国际化本地部分引入了一个标准,它也允许发送到域名的unicode版本而不首先将其转换为ASCII。无论您是否想要支持,都需要一些思考,因为目前没有多少邮件服务器和邮件传输代理支持它。
答案 1 :(得分:1)
从DomainValidator复制了实施,并将TOP_LABEL_REGEX
表达式替换为"\\p{Alpha}[\\p{Alnum}-]*\\p{Alpha}"
。
此外,我删除了针对已批准gTLD的硬编码列表的验证。这基本上是非常弱的,因为它不会对实际域进行验证。但我认为这已经足够好了(抓住与XN--YGBI2AMMX
类似的通用顶级域名)。
查看已批准的gTLD完整列表here。
// Copied from org.apache.commons.validator.routines.DomainValidator
private static final String DOMAIN_LABEL_REGEX = "\\p{Alnum}(?>[\\p{Alnum}-]*\\p{Alnum})*";
// Changed to include new gTLD - http://data.iana.org/TLD/tlds-alpha-by-domain.txt
private static final String TOP_LABEL_REGEX = "\\p{Alpha}[\\p{Alnum}-]*\\p{Alpha}";
// Copied from org.apache.commons.validator.routines.DomainValidator
private static final String DOMAIN_NAME_REGEX = "^(?:" + DOMAIN_LABEL_REGEX + "\\.)+" + "(" + TOP_LABEL_REGEX + ")$";
private static final RegexValidator domainRegex = new RegexValidator(DOMAIN_NAME_REGEX);
private static final EmailValidator EMAIL_VALIDATOR = new EmailValidator();
public static boolean isValidDomain(String domain) {
String[] groups = domainRegex.match(domain);
return groups != null && groups.length > 0;
}
答案 2 :(得分:0)
在这种情况下我经常做的是检查相关库的源代码(它的开源是否记得?),修改它以满足我的要求,然后将补丁提供给项目。
您的用例肯定听起来像是一个有用的贡献。
答案 3 :(得分:0)
我让你成为public suffix list Java API。方法PublicSuffixList.getRegistrableDomain()
可用于域验证:
PublicSuffixListFactory factory = new PublicSuffixListFactory();
PublicSuffixList suffixList = factory.build();
assertNull(suffixList.getRegistrableDomain("galaxy.hoopie-frood"));
assertNotNull(suffixList.getRegistrableDomain("example.bike"));
答案 4 :(得分:0)
虽然DomainValidator缺少一些新的TLD,但对我而言,最好的解决方案是更新TLD。
DomainValidator.updateTLDOverride(ArrayType.COUNTRY_CODE_PLUS, new String[]{"someTLD"});
然后启动EmailValidator实例
EmailValidator.getInstance(false, true)