Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<version.light-4j>2.2.1-SNAPSHOT</version.light-4j>
<version.jackson>2.18.1</version.jackson>
<version.jmail>1.6.3</version.jmail>
<version.slf4j>2.0.16</version.slf4j>
<version.logback>1.5.16</version.logback>
<version.junit>4.13.2</version.junit>
Expand Down Expand Up @@ -133,11 +132,6 @@
<artifactId>jackson-dataformat-yaml</artifactId>
<version>${version.jackson}</version>
</dependency>
<dependency>
<groupId>com.sanctionco.jmail</groupId>
<artifactId>jmail</artifactId>
<version>${version.jmail}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
Expand Down
2,316 changes: 2,316 additions & 0 deletions src/main/java/com/networknt/oas/validator/DomainValidator.java

Large diffs are not rendered by default.

228 changes: 228 additions & 0 deletions src/main/java/com/networknt/oas/validator/EmailValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.networknt.oas.validator;

import java.io.Serializable;
import java.io.Serializable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* <p>Perform email validations.</p>
* <p>
* Based on a script by <a href="mailto:stamhankar@hotmail.com">Sandeep V. Tamhankar</a>
* https://javascript.internet.com
* </p>
* <p>
* This implementation is not guaranteed to catch all possible errors in an email address.
* </p>.
*
* @since 1.4
*/
public class EmailValidator implements Serializable {
private static final long serialVersionUID = 1705927040799295880L;

private static final String SPECIAL_CHARS = "\\p{Cntrl}\\(\\)<>@,;:'\\\\\\\"\\.\\[\\]";
private static final String VALID_CHARS = "(\\\\.)|[^\\s" + SPECIAL_CHARS + "]";
private static final String QUOTED_USER = "(\"(\\\\\"|[^\"])*\")";
private static final String WORD = "((" + VALID_CHARS + "|')+|" + QUOTED_USER + ")";

private static final String EMAIL_REGEX = "^(.+)@(\\S+)$";
private static final String IP_DOMAIN_REGEX = "^\\[(.*)\\]$";
private static final String USER_REGEX = "^" + WORD + "(\\." + WORD + ")*$";

private static final Pattern EMAIL_PATTERN = Pattern.compile(EMAIL_REGEX);
private static final Pattern IP_DOMAIN_PATTERN = Pattern.compile(IP_DOMAIN_REGEX);
private static final Pattern USER_PATTERN = Pattern.compile(USER_REGEX);

private static final int MAX_USERNAME_LEN = 64;

/**
* Singleton instance of this class, which
* doesn't consider local addresses as valid.
*/
private static final EmailValidator EMAIL_VALIDATOR = new EmailValidator(false, false);

/**
* Singleton instance of this class, which
* doesn't consider local addresses as valid.
*/
private static final EmailValidator EMAIL_VALIDATOR_WITH_TLD = new EmailValidator(false, true);

/**
* Singleton instance of this class, which does
* consider local addresses valid.
*/
private static final EmailValidator EMAIL_VALIDATOR_WITH_LOCAL = new EmailValidator(true, false);

/**
* Singleton instance of this class, which does
* consider local addresses valid.
*/
private static final EmailValidator EMAIL_VALIDATOR_WITH_LOCAL_WITH_TLD = new EmailValidator(true, true);

/**
* Returns the Singleton instance of this validator.
*
* @return singleton instance of this validator.
*/
public static EmailValidator getInstance() {
return EMAIL_VALIDATOR;
}

/**
* Returns the Singleton instance of this validator,
* with local validation as required.
*
* @param allowLocal Should local addresses be considered valid?
* @return singleton instance of this validator
*/
public static EmailValidator getInstance(final boolean allowLocal) {
return getInstance(allowLocal, false);
}

/**
* Returns the Singleton instance of this validator,
* with local validation as required.
*
* @param allowLocal Should local addresses be considered valid?
* @param allowTld Should TLDs be allowed?
* @return singleton instance of this validator
*/
public static EmailValidator getInstance(final boolean allowLocal, final boolean allowTld) {
if (allowLocal) {
if (allowTld) {
return EMAIL_VALIDATOR_WITH_LOCAL_WITH_TLD;
}
return EMAIL_VALIDATOR_WITH_LOCAL;
}
if (allowTld) {
return EMAIL_VALIDATOR_WITH_TLD;
}
return EMAIL_VALIDATOR;
}

private final boolean allowTld;

private final DomainValidator domainValidator;

/**
* Protected constructor for subclasses to use.
*
* @param allowLocal Should local addresses be considered valid?
*/
protected EmailValidator(final boolean allowLocal) {
this(allowLocal, false);
}

/**
* Protected constructor for subclasses to use.
*
* @param allowLocal Should local addresses be considered valid?
* @param allowTld Should TLDs be allowed?
*/
protected EmailValidator(final boolean allowLocal, final boolean allowTld) {
this.allowTld = allowTld;
this.domainValidator = DomainValidator.getInstance(allowLocal);
}

/**
* constructor for creating instances with the specified domainValidator
*
* @param allowLocal Should local addresses be considered valid?
* @param allowTld Should TLDs be allowed?
* @param domainValidator allow override of the DomainValidator.
* The instance must have the same allowLocal setting.
* @since 1.7
*/
public EmailValidator(final boolean allowLocal, final boolean allowTld, final DomainValidator domainValidator) {
this.allowTld = allowTld;
if (domainValidator == null) {
throw new IllegalArgumentException("DomainValidator cannot be null");
}
if (domainValidator.isAllowLocal() != allowLocal) {
throw new IllegalArgumentException("DomainValidator must agree with allowLocal setting");
}
this.domainValidator = domainValidator;
}

/**
* <p>Checks if a field has a valid e-mail address.</p>
*
* @param email The value validation is being performed on. A {@code null}
* value is considered invalid.
* @return true if the email address is valid.
*/
public boolean isValid(final String email) {
if (email == null) {
return false;
}

if (email.endsWith(".")) { // check this first - it's cheap!
return false;
}

// Check the whole email address structure
final Matcher emailMatcher = EMAIL_PATTERN.matcher(email);
if (!emailMatcher.matches()) {
return false;
}

if (!isValidUser(emailMatcher.group(1))) {
return false;
}

return isValidDomain(emailMatcher.group(2));
}

/**
* Returns true if the domain component of an email address is valid.
*
* @param domain being validated, may be in IDN format
* @return true if the email address's domain is valid.
*/
protected boolean isValidDomain(final String domain) {
// see if domain is an IP address in brackets
final Matcher ipDomainMatcher = IP_DOMAIN_PATTERN.matcher(domain);

if (ipDomainMatcher.matches()) {
final InetAddressValidator inetAddressValidator =
InetAddressValidator.getInstance();
return inetAddressValidator.isValid(ipDomainMatcher.group(1));
}
// Domain is symbolic name
if (allowTld) {
return domainValidator.isValid(domain) || !domain.startsWith(".") && domainValidator.isValidTld(domain);
}
return domainValidator.isValid(domain);
}

/**
* Returns true if the user component of an email address is valid.
*
* @param user being validated
* @return true if the user name is valid.
*/
protected boolean isValidUser(final String user) {

if (user == null || user.length() > MAX_USERNAME_LEN) {
return false;
}

return USER_PATTERN.matcher(user).matches();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.networknt.oas.validator;

/**
* This is an extension of the Apache Commons Validator that correctly
* handles email addresses containing an IPv6 literal as the domain.
* <p>
* Apache's {@link EmailValidator} delegates validation of the domain to
* its {@link DomainValidator}, which is not aware that it is validating
* an email address, which has a peculiar way of representing an IPv6
* literal.
*/
public class IPv6AwareEmailValidator extends EmailValidator {
private static final long serialVersionUID = 1L;

/**
* Creates a new IPv6AwareEmailValidator.
*
* @param allowLocal Should local addresses be considered valid?
* @param allowTld Should TLDs be allowed?
*/
public IPv6AwareEmailValidator(final boolean allowLocal, final boolean allowTld) {
super(allowLocal, allowTld);
}

@Override
protected boolean isValidDomain(String domain) {
return super.isValidDomain(domain.startsWith("[IPv6:") ? domain.replace("IPv6:", "") : domain);
}

}
Loading