001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.validator.routines; 018 019 import java.io.Serializable; 020 import java.util.regex.Matcher; 021 import java.util.regex.Pattern; 022 023 /** 024 * <p>Perform email validations.</p> 025 * <p> 026 * This class is a Singleton; you can retrieve the instance via the getInstance() method. 027 * </p> 028 * <p> 029 * Based on a script by <a href="mailto:stamhankar@hotmail.com">Sandeep V. Tamhankar</a> 030 * http://javascript.internet.com 031 * </p> 032 * <p> 033 * This implementation is not guaranteed to catch all possible errors in an email address. 034 * For example, an address like nobody@noplace.somedog will pass validator, even though there 035 * is no TLD "somedog" 036 * </p>. 037 * 038 * @version $Revision: 594904 $ $Date: 2007-11-14 15:30:27 +0100 (Mi, 14. Nov 2007) $ 039 * @since Validator 1.4 040 */ 041 public class EmailValidator implements Serializable { 042 043 private static final String SPECIAL_CHARS = "\\p{Cntrl}\\(\\)<>@,;:'\\\\\\\"\\.\\[\\]"; 044 private static final String VALID_CHARS = "[^\\s" + SPECIAL_CHARS + "]"; 045 private static final String QUOTED_USER = "(\"[^\"]*\")"; 046 private static final String WORD = "((" + VALID_CHARS + "|')+|" + QUOTED_USER + ")"; 047 048 private static final String LEGAL_ASCII_REGEX = "^\\p{ASCII}+$"; 049 private static final String EMAIL_REGEX = "^\\s*?(.+)@(.+?)\\s*$"; 050 private static final String IP_DOMAIN_REGEX = "^\\[(.*)\\]$"; 051 private static final String USER_REGEX = "^\\s*" + WORD + "(\\." + WORD + ")*$"; 052 053 private static final Pattern MATCH_ASCII_PATTERN = Pattern.compile(LEGAL_ASCII_REGEX); 054 private static final Pattern EMAIL_PATTERN = Pattern.compile(EMAIL_REGEX); 055 private static final Pattern IP_DOMAIN_PATTERN = Pattern.compile(IP_DOMAIN_REGEX); 056 private static final Pattern USER_PATTERN = Pattern.compile(USER_REGEX); 057 058 /** 059 * Singleton instance of this class. 060 */ 061 private static final EmailValidator EMAIL_VALIDATOR = new EmailValidator(); 062 063 /** 064 * Returns the Singleton instance of this validator. 065 * 066 * @return singleton instance of this validator. 067 */ 068 public static EmailValidator getInstance() { 069 return EMAIL_VALIDATOR; 070 } 071 072 /** 073 * Protected constructor for subclasses to use. 074 */ 075 protected EmailValidator() { 076 super(); 077 } 078 079 /** 080 * <p>Checks if a field has a valid e-mail address.</p> 081 * 082 * @param email The value validation is being performed on. A <code>null</code> 083 * value is considered invalid. 084 * @return true if the email address is valid. 085 */ 086 public boolean isValid(String email) { 087 if (email == null) { 088 return false; 089 } 090 091 Matcher asciiMatcher = MATCH_ASCII_PATTERN.matcher(email); 092 if (!asciiMatcher.matches()) { 093 return false; 094 } 095 096 // Check the whole email address structure 097 Matcher emailMatcher = EMAIL_PATTERN.matcher(email); 098 if (!emailMatcher.matches()) { 099 return false; 100 } 101 102 if (email.endsWith(".")) { 103 return false; 104 } 105 106 if (!isValidUser(emailMatcher.group(1))) { 107 return false; 108 } 109 110 if (!isValidDomain(emailMatcher.group(2))) { 111 return false; 112 } 113 114 return true; 115 } 116 117 /** 118 * Returns true if the domain component of an email address is valid. 119 * 120 * @param domain being validated. 121 * @return true if the email address's domain is valid. 122 */ 123 protected boolean isValidDomain(String domain) { 124 // see if domain is an IP address in brackets 125 Matcher ipDomainMatcher = IP_DOMAIN_PATTERN.matcher(domain); 126 127 if (ipDomainMatcher.matches()) { 128 InetAddressValidator inetAddressValidator = 129 InetAddressValidator.getInstance(); 130 return inetAddressValidator.isValid(ipDomainMatcher.group(1)); 131 } else { 132 // Domain is symbolic name 133 DomainValidator domainValidator = 134 DomainValidator.getInstance(); 135 return domainValidator.isValid(domain); 136 } 137 } 138 139 /** 140 * Returns true if the user component of an email address is valid. 141 * 142 * @param user being validated 143 * @return true if the user name is valid. 144 */ 145 protected boolean isValidUser(String user) { 146 return USER_PATTERN.matcher(user).matches(); 147 } 148 149 }