1 17 18 package org.apache.mailet; 19 20 import java.util.Locale ; 21 import javax.mail.internet.InternetAddress ; 22 import javax.mail.internet.ParseException ; 23 24 60 public class MailAddress implements java.io.Serializable { 61 public static final long serialVersionUID = 2779163542539434916L; 64 65 private final static char[] SPECIAL = 66 {'<', '>', '(', ')', '[', ']', '\\', '.', ',', ';', ':', '@', '\"'}; 67 68 private String user = null; 69 private String host = null; 70 private int pos = 0; 72 73 81 public MailAddress(String address) throws ParseException { 82 address = address.trim(); 83 StringBuffer userSB = new StringBuffer (); 84 StringBuffer hostSB = new StringBuffer (); 85 88 try { 89 if (address.charAt(pos) == '\"') { 92 userSB.append(parseQuotedLocalPart(address)); 93 } else { 94 userSB.append(parseUnquotedLocalPart(address)); 95 } 96 if (userSB.toString().length() == 0) { 97 throw new ParseException ("No local-part (user account) found at position " + (pos + 1)); 98 } 99 100 if (pos >= address.length() || address.charAt(pos) != '@') { 102 throw new ParseException ("Did not find @ between local-part and domain at position " + (pos + 1)); 103 } 104 pos++; 105 106 while (true) { 110 if (address.charAt(pos) == '#') { 111 hostSB.append(parseNumber(address)); 112 } else if (address.charAt(pos) == '[') { 113 hostSB.append(parseDotNum(address)); 114 } else { 115 hostSB.append(parseDomainName(address)); 116 } 117 if (pos >= address.length()) { 118 break; 119 } 120 if (address.charAt(pos) == '.') { 121 hostSB.append('.'); 122 pos++; 123 continue; 124 } 125 break; 126 } 127 128 if (hostSB.toString().length() == 0) { 129 throw new ParseException ("No domain found at position " + (pos + 1)); 130 } 131 } catch (IndexOutOfBoundsException ioobe) { 132 throw new ParseException ("Out of data at position " + (pos + 1)); 133 } 134 135 user = userSB.toString(); 136 host = hostSB.toString(); 137 } 138 139 147 public MailAddress(String newUser, String newHost) throws ParseException { 148 149 user = newUser; 150 host = newHost; 151 } 152 153 157 public MailAddress(InternetAddress address) throws ParseException { 158 this(address.getAddress()); 159 } 160 161 168 public String getHost() { 169 if (!(host.startsWith("[") && host.endsWith("]"))) { 170 return host; 171 } else { 172 return host.substring(1, host.length() -1); 173 } 174 } 175 176 183 public String getUser() { 184 return user; 185 } 186 187 public String toString() { 188 StringBuffer addressBuffer = 189 new StringBuffer (128) 190 .append(user) 191 .append("@") 192 .append(host); 193 return addressBuffer.toString(); 194 } 195 196 public InternetAddress toInternetAddress() { 197 try { 198 return new InternetAddress (toString()); 199 } catch (javax.mail.internet.AddressException ae) { 200 return null; 202 } 203 } 204 205 public boolean equals(Object obj) { 206 if (obj == null) { 207 return false; 208 } else if (obj instanceof String ) { 209 String theString = (String )obj; 210 return toString().equalsIgnoreCase(theString); 211 } else if (obj instanceof MailAddress) { 212 MailAddress addr = (MailAddress)obj; 213 return getUser().equalsIgnoreCase(addr.getUser()) && getHost().equalsIgnoreCase(addr.getHost()); 214 } 215 return false; 216 } 217 218 227 public int hashCode() { 228 return toString().toLowerCase(Locale.US).hashCode(); 229 } 230 231 private String parseQuotedLocalPart(String address) throws ParseException { 232 StringBuffer resultSB = new StringBuffer (); 233 resultSB.append('\"'); 234 pos++; 235 while (true) { 238 if (address.charAt(pos) == '\"') { 239 resultSB.append('\"'); 240 pos++; 242 break; 243 } 244 if (address.charAt(pos) == '\\') { 245 resultSB.append('\\'); 246 pos++; 247 char x = address.charAt(pos); 249 if (x < 0 || x > 127) { 250 throw new ParseException ("Invalid \\ syntaxed character at position " + (pos + 1)); 251 } 252 resultSB.append(x); 253 pos++; 254 } else { 255 char q = address.charAt(pos); 258 if (q <= 0 || q == '\n' || q == '\r' || q == '\"' || q == '\\') { 259 throw new ParseException ("Unquoted local-part (user account) must be one of the 128 ASCI characters exception <CR>, <LF>, quote (\"), or backslash (\\) at position " + (pos + 1)); 260 } 261 resultSB.append(q); 262 pos++; 263 } 264 } 265 return resultSB.toString(); 266 } 267 268 private String parseUnquotedLocalPart(String address) throws ParseException { 269 StringBuffer resultSB = new StringBuffer (); 270 boolean lastCharDot = false; 272 while (true) { 273 if (address.charAt(pos) == '\\') { 276 resultSB.append('\\'); 277 pos++; 278 char x = address.charAt(pos); 280 if (x < 0 || x > 127) { 281 throw new ParseException ("Invalid \\ syntaxed character at position " + (pos + 1)); 282 } 283 resultSB.append(x); 284 pos++; 285 lastCharDot = false; 286 } else if (address.charAt(pos) == '.') { 287 resultSB.append('.'); 288 pos++; 289 lastCharDot = true; 290 } else if (address.charAt(pos) == '@') { 291 break; 293 } else { 294 char c = address.charAt(pos); 302 if (c <= 31 || c >= 127 || c == ' ') { 303 throw new ParseException ("Invalid character in local-part (user account) at position " + (pos + 1)); 304 } 305 for (int i = 0; i < SPECIAL.length; i++) { 306 if (c == SPECIAL[i]) { 307 throw new ParseException ("Invalid character in local-part (user account) at position " + (pos + 1)); 308 } 309 } 310 resultSB.append(c); 311 pos++; 312 lastCharDot = false; 313 } 314 } 315 if (lastCharDot) { 316 throw new ParseException ("local-part (user account) ended with a \".\", which is invalid."); 317 } 318 return resultSB.toString(); 319 } 320 321 private String parseNumber(String address) throws ParseException { 322 324 StringBuffer resultSB = new StringBuffer (); 325 while (true) { 327 if (pos >= address.length()) { 328 break; 329 } 330 char d = address.charAt(pos); 332 if (d == '.') { 333 break; 334 } 335 if (d < '0' || d > '9') { 336 throw new ParseException ("In domain, did not find a number in # address at position " + (pos + 1)); 337 } 338 resultSB.append(d); 339 pos++; 340 } 341 return resultSB.toString(); 342 } 343 344 private String parseDotNum(String address) throws ParseException { 345 while(address.indexOf("\\")>-1){ 347 address= address.substring(0,address.indexOf("\\")) + address.substring(address.indexOf("\\")+1); 348 } 349 StringBuffer resultSB = new StringBuffer (); 350 resultSB.append(address.charAt(pos)); 353 pos++; 354 355 for (int octet = 0; octet < 4; octet++) { 357 StringBuffer snumSB = new StringBuffer (); 361 for (int digits = 0; digits < 3; digits++) { 362 char d = address.charAt(pos); 363 if (d == '.') { 364 break; 365 } 366 if (d == ']') { 367 break; 368 } 369 if (d < '0' || d > '9') { 370 throw new ParseException ("Invalid number at position " + (pos + 1)); 371 } 372 snumSB.append(d); 373 pos++; 374 } 375 if (snumSB.toString().length() == 0) { 376 throw new ParseException ("Number not found at position " + (pos + 1)); 377 } 378 try { 379 int snum = Integer.parseInt(snumSB.toString()); 380 if (snum > 255) { 381 throw new ParseException ("Invalid number at position " + (pos + 1)); 382 } 383 } catch (NumberFormatException nfe) { 384 throw new ParseException ("Invalid number at position " + (pos + 1)); 385 } 386 resultSB.append(snumSB.toString()); 387 if (address.charAt(pos) == ']') { 388 if (octet < 3) { 389 throw new ParseException ("End of number reached too quickly at " + (pos + 1)); 390 } else { 391 break; 392 } 393 } 394 if (address.charAt(pos) == '.') { 395 resultSB.append('.'); 396 pos++; 397 } 398 } 399 if (address.charAt(pos) != ']') { 400 throw new ParseException ("Did not find closing bracket \"]\" in domain at position " + (pos + 1)); 401 } 402 resultSB.append(']'); 403 pos++; 404 return resultSB.toString(); 405 } 406 407 private String parseDomainName(String address) throws ParseException { 408 StringBuffer resultSB = new StringBuffer (); 409 417 421 while (true) { 425 if (pos >= address.length()) { 426 break; 427 } 428 char ch = address.charAt(pos); 429 if ((ch >= '0' && ch <= '9') || 430 (ch >= 'a' && ch <= 'z') || 431 (ch >= 'A' && ch <= 'Z') || 432 (ch == '-')) { 433 resultSB.append(ch); 434 pos++; 435 continue; 436 } 437 if (ch == '.') { 438 break; 439 } 440 throw new ParseException ("Invalid character at " + pos); 441 } 442 String result = resultSB.toString(); 443 if (result.startsWith("-") || result.endsWith("-")) { 444 throw new ParseException ("Domain name cannot begin or end with a hyphen \"-\" at position " + (pos + 1)); 445 } 446 return result; 447 } 448 } 449 | Popular Tags |