1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/* 2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2015 The Android Open Source Project 3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License"); 5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License. 6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at 7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * http://www.apache.org/licenses/LICENSE-2.0 9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software 11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS, 12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and 14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License. 15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.util; 18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.google.common.base.CharMatcher; 20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/** 22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Parsing the email address 23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic final class EmailAddress { 25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final CharMatcher ANY_WHITESPACE = CharMatcher.anyOf( 26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd " \t\n\r\f\u000B\u0085\u2028\u2029\u200D\uFFEF\uFFFD\uFFFE\uFFFF"); 27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final CharMatcher EMAIL_ALLOWED_CHARS = CharMatcher.inRange((char) 0, (char) 31) 28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .or(CharMatcher.is((char) 127)) 29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .or(CharMatcher.anyOf(" @,:<>")) 30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .negate(); 31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Helper method that checks whether the input text is valid email address. 34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * TODO: This creates a new EmailAddress object each time 35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Need to make it more lightweight by pulling out the validation code into a static method. 36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static boolean isValidEmail(final String emailText) { 38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new EmailAddress(emailText).isValid(); 39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Parses the specified email address. Internationalized addresses are treated as invalid. 43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param emailString A string representing just an email address. It should 45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * not contain any other tokens. <code>"Name<foo@example.org>"</code> won't be valid. 46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public EmailAddress(final String emailString) { 48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd this(emailString, false); 49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Parses the specified email address. 53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param emailString A string representing just an email address. It should 55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * not contain any other tokens. <code>"Name<foo@example.org>"</code> won't be valid. 56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param i18n Accept an internationalized address if it is true. 57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public EmailAddress(final String emailString, final boolean i18n) { 59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd allowI18n = i18n; 60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd valid = parseEmail(emailString); 61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Parses the specified email address. Internationalized addresses are treated as invalid. 65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param user A string representing the username in the email prior to the '@' symbol 67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param host A string representing the host following the '@' symbol 68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public EmailAddress(final String user, final String host) { 70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd this(user, host, false); 71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Parses the specified email address. 75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param user A string representing the username in the email prior to the '@' symbol 77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param host A string representing the host following the '@' symbol 78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param i18n Accept an internationalized address if it is true. 79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public EmailAddress(final String user, final String host, final boolean i18n) { 81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd allowI18n = i18n; 82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd this.user = user; 83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setHost(host); 84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected boolean parseEmail(final String emailString) { 87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // check for null 88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (emailString == null) { 89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Check for an '@' character. Get the last one, in case the local part is 93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // quoted. See http://b/1944742. 94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int atIndex = emailString.lastIndexOf('@'); 95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if ((atIndex <= 0) || // no '@' character in the email address 96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // or @ on the first position 97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd (atIndex == (emailString.length() - 1))) { // last character, no host 98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd user = emailString.substring(0, atIndex); 102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd host = emailString.substring(atIndex + 1); 103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return isValidInternal(); 105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public String toString() { 109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return user + "@" + host; 110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Ensure the email address is valid, conforming to current RFC2821 and 114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * RFC2822 guidelines (although some iffy characters, like ! and ;, are 115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * allowed because they are not technically prohibited in the RFC) 116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private boolean isValidInternal() { 118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if ((user == null) || (host == null)) { 119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if ((user.length() == 0) || (host.length() == 0)) { 123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // check for white space in the host 127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (ANY_WHITESPACE.indexIn(host) >= 0) { 128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // ensure the host is above the minimum length 132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (host.length() < 4) { 133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int firstDot = host.indexOf('.'); 137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // ensure host contains at least one dot 139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (firstDot == -1) { 140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // check if the host contains two continuous dots. 144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (host.indexOf("..") >= 0) { 145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // check if the first host char is a dot. 149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (host.charAt(0) == '.') { 150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int secondDot = host.indexOf(".", firstDot + 1); 154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // if there's a dot at the end, there needs to be a second dot 156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (host.charAt(host.length() - 1) == '.' && secondDot == -1) { 157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Host must not have any disallowed characters; allowI18n dictates whether 161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // host must be ASCII. 162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!EMAIL_ALLOWED_CHARS.matchesAllOf(host) 163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd || (!allowI18n && !CharMatcher.ASCII.matchesAllOf(host))) { 164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (user.startsWith("\"")) { 168d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!isQuotedUserValid()) { 169d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 170d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 171d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 172d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // check for white space in the user 173d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (ANY_WHITESPACE.indexIn(user) >= 0) { 174d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 175d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 176d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 177d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // the user cannot contain two continuous dots 178d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (user.indexOf("..") >= 0) { 179d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 180d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 181d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 182d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // User must not have any disallowed characters; allow I18n dictates whether 183d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // user must be ASCII. 184d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!EMAIL_ALLOWED_CHARS.matchesAllOf(user) 185d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd || (!allowI18n && !CharMatcher.ASCII.matchesAllOf(user))) { 186d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 187d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 188d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 189d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return true; 190d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 191d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 192d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private boolean isQuotedUserValid() { 193d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int limit = user.length() - 1; 194d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (limit < 1 || !user.endsWith("\"")) { 195d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 196d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 197d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 198d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Unusual loop bounds (looking only at characters between the outer quotes, 199d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // not at either quote character). Plus, i is manipulated within the loop. 200d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = 1; i < limit; ++i) { 201d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final char ch = user.charAt(i); 202d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (ch == '"' || ch == 127 203d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // No non-whitespace control chars: 204d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd || (ch < 32 && !ANY_WHITESPACE.matches(ch)) 205d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // No non-ASCII chars, unless i18n is in effect: 206d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd || (ch >= 128 && !allowI18n)) { 207d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 208d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else if (ch == '\\') { 209d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (i + 1 < limit) { 210d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ++i; // Skip the quoted character 211d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 212d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // We have a trailing backslash -- so it can't be quoting anything. 213d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 214d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 215d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 216d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 217d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 218d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return true; 219d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 220d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 221d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 222d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean equals(final Object otherObject) { 223d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Do an instance check first as an optimization. 224d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (this == otherObject) { 225d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return true; 226d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 227d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (otherObject instanceof EmailAddress) { 228d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final EmailAddress otherAddress = (EmailAddress) otherObject; 229d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return toString().equals(otherAddress.toString()); 230d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 231d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 232d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 233d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 234d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 235d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public int hashCode() { 236d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Arbitrary hash code as a function of both host and user. 237d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return toString().hashCode(); 238d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 239d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 240d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // accessors 241d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean isValid() { 242d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return valid; 243d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 244d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 245d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public String getUser() { 246d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return user; 247d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 248d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 249d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public String getHost() { 250d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return host; 251d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 252d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 253d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // used to change the host on an email address and rechecks validity 254d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 255d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 256d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Changes the host name of the email address and rechecks the address' 257d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * validity. Exercise caution when storing EmailAddress instances in 258d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * hash-keyed collections. Calling setHost() with a different host name will 259d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * change the return value of hashCode. 260d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 261d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param hostName The new host name of the email address. 262d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 263d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void setHost(final String hostName) { 264d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd host = hostName; 265d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd valid = isValidInternal(); 266d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 267d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 268d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected boolean valid = false; 269d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected String user = null; 270d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected String host = null; 271d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected boolean allowI18n = false; 272d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd} 273