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 public static EmailValidator getInstance(final boolean allowLocal, final boolean allowTld) {
106 if (allowLocal) {
107 if (allowTld) {
108 return EMAIL_VALIDATOR_WITH_LOCAL_WITH_TLD;
109 }
110 return EMAIL_VALIDATOR_WITH_LOCAL;
111 }
112 if (allowTld) {
113 return EMAIL_VALIDATOR_WITH_TLD;
114 }
115 return EMAIL_VALIDATOR;
116 }
117
118
119
120
121 private final boolean allowTld;
122
123
124
125
126 private final DomainValidator domainValidator;
127
128
129
130
131
132
133 protected EmailValidator(final boolean allowLocal) {
134 this(allowLocal, false);
135 }
136
137
138
139
140
141
142
143 protected EmailValidator(final boolean allowLocal, final boolean allowTld) {
144 this.allowTld = allowTld;
145 this.domainValidator = DomainValidator.getInstance(allowLocal);
146 }
147
148
149
150
151
152
153
154
155
156
157 public EmailValidator(final boolean allowLocal, final boolean allowTld, final DomainValidator domainValidator) {
158 this.allowTld = allowTld;
159 if (domainValidator == null) {
160 throw new IllegalArgumentException("DomainValidator cannot be null");
161 }
162 if (domainValidator.isAllowLocal() != allowLocal) {
163 throw new IllegalArgumentException("DomainValidator must agree with allowLocal setting");
164 }
165 this.domainValidator = domainValidator;
166 }
167
168
169
170
171
172
173
174
175 public boolean isValid(final String email) {
176 if (email == null || email.endsWith(".")) {
177 return false;
178 }
179
180 final Matcher emailMatcher = EMAIL_PATTERN.matcher(email);
181 if (!emailMatcher.matches()) {
182 return false;
183 }
184 if (!isValidUser(emailMatcher.group(1))) {
185 return false;
186 }
187 if (!isValidDomain(emailMatcher.group(2))) {
188 return false;
189 }
190 return true;
191 }
192
193
194
195
196
197
198
199 protected boolean isValidDomain(final String domain) {
200
201 final Matcher ipDomainMatcher = IP_DOMAIN_PATTERN.matcher(domain);
202
203 if (ipDomainMatcher.matches()) {
204 final InetAddressValidator inetAddressValidator =
205 InetAddressValidator.getInstance();
206 return inetAddressValidator.isValid(ipDomainMatcher.group(1));
207 }
208
209 if (allowTld) {
210 return domainValidator.isValid(domain) || !domain.startsWith(".") && domainValidator.isValidTld(domain);
211 }
212 return domainValidator.isValid(domain);
213 }
214
215
216
217
218
219
220
221 protected boolean isValidUser(final String user) {
222
223 if (user == null || user.length() > MAX_USERNAME_LEN) {
224 return false;
225 }
226
227 return USER_PATTERN.matcher(user).matches();
228 }
229
230 }