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"));