Apache commons-альтернатива валидатора для новых gTLD
Мне нужно, чтобы проверить электронную почту и Домены. Мне просто нужна формальная проверка, нет whois или других форм поиска домена.
В настоящее время я использую Apache commons-validator v1.4.0
к сожалению, мои клиенты используют новые рдву, как .велосипед или. производства, которые еще не поддерживаются классом DomainValidator. См.проблема Jira Apache для получения более подробной информации.
есть ли какие-либо звуковые альтернативы, которые я могу легко включить в свой Maven Пом?
4 ответов
если вас не беспокоят интернационализированные адреса, вы можете изменить последнюю часть адреса и продолжить использовать Apache commons.
этот подход основан на том факте, что каким бы ни был TLD, действительность всего доменного имени эквивалентна действительности того же доменного имени с заменой TLD на com
. Например:
-
abc.def.com
действителен. Аналогичноabc.def.name
,abc.def.xx--kput3i
,abc.def.uk
действительны. -
ab,de.com
is недействительный. Аналогично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, и это не должно иметь значения, поскольку речь идет о действительности адреса. - если строка не имеет допустимого TLD в конце,
String.replaceFirst()
вернет его как есть. Это еще может быть действительным, потому что адреса электронной почты форматx@[n.n.n.n]
здесьn.n.n.n.
действительный IP-адрес действительны. Так что в принципе, если вы не нашли TLD, вы позволяетеEmailValidator
решите вопрос о действительности сам. - конечно, если TLD не является признанным IANA TLD, эта проверка не скажет вам об этом. Письмо типа
david@galaxy.hoopie-frood
будет принято как законное, но у IANA пока нет этого TLD.
проверка домена аналогична, без trim()
детали:
if (userDomain == null ) {
return false;
}
return DomainValidator.getInstance().isValid(userDomain.replaceFirst("\.\p{Alpha}[\p{Alnum}-]*\p{Alnum}$"));
я также пробовал Проверка адреса электронной почты JavaMail, но мне это не очень нравится: она позволяет полностью недопустимые доменные имена, такие как net-name.net-
(заканчивается тире) или IP-адреса (которые не разрешены для электронной почты без квадратных скобок вокруг них), и это хорошо только для адресов электронной почты, а не для доменов.
интернационализации
Если вам нужно проверить для интернационализированных доменов и электронной почты, это немного другое. Легко проверить наличие интернационализированных доменов (например 元気。テスト
). Все, что вам нужно сделать, это преобразовать их в ASCII с java.net.IDN.toASCII()
(при xn--z4qx76d.xn--zckzah
для моего примера домена-это допустимый TLD), а затем сделайте то же самое, что я написал выше.
многоязычные электронные письма-это другая история. Если локальной частью является ASCII, можно преобразовать доменную часть в ASCII. Если вам нужно отобразить адрес электронной почты, вам нужно использовать версию Unicode, а если вам нужно отправить сообщение электронной почты, вы используете версию ASCII.
но в последнее время стандарт был введен и для интернационализированных локальных частей, что также позволяет отправлять в Юникод версию доменного имени без перевода его сначала в ASCII. Хотите ли вы поддержать это или нет, требует некоторого размышления, так как не многие почтовые серверы и агенты передачи почты поддерживают его в данный момент.
скопировал реализацию от DomainValidator и заменить на TOP_LABEL_REGEX
выражение "\p{Alpha}[\p{Alnum}-]*\p{Alpha}"
.
кроме того, я удалил проверку против жестко закодированного списка утвержденных рдву. Это, в основном, довольно слабо в том, что он не проверяет фактические Домены. Но я думаю, что это достаточно хорошо (ловит gTLDs, похожие на XN--YGBI2AMMX
).
см. полный список утвержденных рдву здесь.
// 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;
}
Что я часто делаю в этой ситуации, чтобы проверить исходный код для рассматриваемой библиотеки (это с открытым исходным кодом помните?), измените его в соответствии с моим требованием, а затем внесите патч обратно в проект.
ваш вариант использования, безусловно, звучит как полезный вклад.
Я сделал тебе публичный список суффиксов Java API. Метод PublicSuffixList.getRegistrableDomain()
может использоваться для проверки домена:
PublicSuffixListFactory factory = new PublicSuffixListFactory();
PublicSuffixList suffixList = factory.build();
assertNull(suffixList.getRegistrableDomain("galaxy.hoopie-frood"));
assertNotNull(suffixList.getRegistrableDomain("example.bike"));