1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.validator.routines;
18
19 import java.io.Serializable;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
22
23
24
25
26
27
28
29
30
31
32
33
34
35 public class EmailValidator implements Serializable {
36
37 private static final long serialVersionUID = 1705927040799295880L;
38
39 private static final String SPECIAL_CHARS = "\\p{Cntrl}\\(\\)<>@,;:'\\\\\\\"\\.\\[\\]";
40 private static final String VALID_CHARS = "(\\\\.)|[^\\s" + SPECIAL_CHARS + "]";
41 private static final String QUOTED_USER = "(\"(\\\\\"|[^\"])*\")";
42 private static final String WORD = "((" + VALID_CHARS + "|')+|" + QUOTED_USER + ")";
43
44 private static final String EMAIL_REGEX = "^(.+)@(\\S+)$";
45 private static final String IP_DOMAIN_REGEX = "^\\[(.*)\\]$";
46 private static final String USER_REGEX = "^" + WORD + "(\\." + WORD + ")*$";
47
48 private static final Pattern EMAIL_PATTERN = Pattern.compile(EMAIL_REGEX);
49 private static final Pattern IP_DOMAIN_PATTERN = Pattern.compile(IP_DOMAIN_REGEX);
50 private static final Pattern USER_PATTERN = Pattern.compile(USER_REGEX);
51
52 private static final int MAX_USERNAME_LEN = 64;
53
54
55
56
57
58 private static final EmailValidator EMAIL_VALIDATOR = new EmailValidator(false, false);
59
60
61
62
63
64 private static final EmailValidator EMAIL_VALIDATOR_WITH_TLD = new EmailValidator(false, true);
65
66
67
68
69
70 private static final EmailValidator EMAIL_VALIDATOR_WITH_LOCAL = new EmailValidator(true, false);
71
72
73
74
75
76 private static final EmailValidator EMAIL_VALIDATOR_WITH_LOCAL_WITH_TLD = new EmailValidator(true, true);
77
78
79
80
81
82
83 public static EmailValidator getInstance() {
84 return EMAIL_VALIDATOR;
85 }
86
87
88
89
90
91
92
93
94 public static EmailValidator getInstance(final boolean allowLocal) {
95 return getInstance(allowLocal, false);
96 }
97
98
99
100
101
102
103
104
105
106 public static EmailValidator getInstance(final boolean allowLocal, final boolean allowTld) {
107 if (allowLocal) {
108 if (allowTld) {
109 return EMAIL_VALIDATOR_WITH_LOCAL_WITH_TLD;
110 }
111 return EMAIL_VALIDATOR_WITH_LOCAL;
112 }
113 if (allowTld) {
114 return EMAIL_VALIDATOR_WITH_TLD;
115 }
116 return EMAIL_VALIDATOR;
117 }
118
119 private final boolean allowTld;
120
121 private final DomainValidator domainValidator;
122
123
124
125
126
127
128 protected EmailValidator(final boolean allowLocal) {
129 this(allowLocal, false);
130 }
131
132
133
134
135
136
137
138 protected EmailValidator(final boolean allowLocal, final boolean allowTld) {
139 this.allowTld = allowTld;
140 this.domainValidator = DomainValidator.getInstance(allowLocal);
141 }
142
143
144
145
146
147
148
149
150
151
152 public EmailValidator(final boolean allowLocal, final boolean allowTld, final DomainValidator domainValidator) {
153 this.allowTld = allowTld;
154 if (domainValidator == null) {
155 throw new IllegalArgumentException("DomainValidator cannot be null");
156 }
157 if (domainValidator.isAllowLocal() != allowLocal) {
158 throw new IllegalArgumentException("DomainValidator must agree with allowLocal setting");
159 }
160 this.domainValidator = domainValidator;
161 }
162
163
164
165
166
167
168
169
170 public boolean isValid(final String email) {
171 if (email == null) {
172 return false;
173 }
174
175 if (email.endsWith(".")) {
176 return false;
177 }
178
179
180 final Matcher emailMatcher = EMAIL_PATTERN.matcher(email);
181 if (!emailMatcher.matches()) {
182 return false;
183 }
184
185 if (!isValidUser(emailMatcher.group(1))) {
186 return false;
187 }
188
189 if (!isValidDomain(emailMatcher.group(2))) {
190 return false;
191 }
192
193 return true;
194 }
195
196
197
198
199
200
201
202 protected boolean isValidDomain(final String domain) {
203
204 final Matcher ipDomainMatcher = IP_DOMAIN_PATTERN.matcher(domain);
205
206 if (ipDomainMatcher.matches()) {
207 final InetAddressValidator inetAddressValidator =
208 InetAddressValidator.getInstance();
209 return inetAddressValidator.isValid(ipDomainMatcher.group(1));
210 }
211
212 if (allowTld) {
213 return domainValidator.isValid(domain) || !domain.startsWith(".") && domainValidator.isValidTld(domain);
214 }
215 return domainValidator.isValid(domain);
216 }
217
218
219
220
221
222
223
224 protected boolean isValidUser(final String user) {
225
226 if (user == null || user.length() > MAX_USERNAME_LEN) {
227 return false;
228 }
229
230 return USER_PATTERN.matcher(user).matches();
231 }
232
233 }