1b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook/* 2b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook * Copyright (C) 2010 The Android Open Source Project 3b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook * 4b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook * Licensed under the Apache License, Version 2.0 (the "License"); 5b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook * you may not use this file except in compliance with the License. 6b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook * You may obtain a copy of the License at 7b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook * 8b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook * http://www.apache.org/licenses/LICENSE-2.0 9b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook * 10b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook * Unless required by applicable law or agreed to in writing, software 11b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook * distributed under the License is distributed on an "AS IS" BASIS, 12b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook * See the License for the specific language governing permissions and 14b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook * limitations under the License. 15b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook */ 16b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook 17b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrookpackage com.android.common; 18b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook 19b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrookimport android.test.suitebuilder.annotation.SmallTest; 20b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook 214c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décampsimport junit.framework.TestCase; 224c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps 23b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrookimport java.util.HashMap; 24b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrookimport java.util.Map; 25b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook 26b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrookpublic class Rfc822ValidatorTest extends TestCase { 274c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps static final String[] VALID_EMAILS = new String[] { 284c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "a@example.org", "b@exemple.fr", "c@d.e-f", 294c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "Very.Common@example.org", 304c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "john@EXAMPLE.ORG", 314c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "john@a123b.c-d.dept.example.com", 324c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "xn--r8jz45g@example.com", 334c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "disposable.style.email.with+symbol@example.com", 344c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "other.email-with-dash@example.com", 354c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "!#$%&'*+-/=?^_`{}|~@example.com", // Use of allowed special characters. 364c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "a@domain-label-cannot-be-longer-than-63-chars-and-this-is-maximum.example.com", 374c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // Valid de facto, even if RFC doesn't allow it. 384c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "a..b@example.com", ".a@example.com", "b.@example.com", 394c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // Punycode is an ASCII representation of International domain names. 404c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "john.doe@xn--r8jz45g.xn--zckzah", 414c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "john.doe@XN--R8JZ45G.XN--ZXKZAH", 424c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "xn--r8jz45g@xn--r8jz45g.XN--ZXKZAH", 434c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // Quoted address. 444c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // TODO(regisd) Fix Rfc822Tokenizer which loses the quotes. 454c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // "\"much.more unusual\"", 464c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // "\"very.unusual.@.unusual.com\"" 474c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps 484c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // Valid only in new Internalized email address. 494c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "a@\u00E9.example.com", 504c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps //"みんな@例え.テスト", 514c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "\u307F\u3093\u306A@\u4F8B\u3048.\u30C6\u30B9\u30C8", 524c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // "test@test.テスト", // Unicode in TLD only. 534c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "everybody@example.\u30C6\u30B9\u30C8", 544c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // "test@例え.test", // Unicode in domain only. 554c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "everybody@\u4F8B\u3048.test", 564c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // "みんな@example.com" // Unicode in localpart only. 574c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "\u307F\u3093\u306A@example.test" 584c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps }; 594c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps 604c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps static final String[] INVALID_EMAILS = new String[] { 614c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "a", "example.com", "john.example.com", // Missing at sign. 624c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "a b", "a space@example.com", // Space not allowed. 634c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // Invalid domain. 644c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "john@example..com", "a@b", "a@-b.com", "a@b-.com", "a@b.c", 654c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "a@a123456789-123456789-123456789-123456789-123456789-123456789-bcd.example.com", 664c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // Invalid characters in domain as per RFC 1034 and RFC 1035, 674c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // even if these characters are in RFC5322's domain production. 684c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "a@d_e.fg", "a@d!e.fg", "a@d#e.fg", "a@d$e.fg", "a@d%e.fg", "a@d&e.fg", "a@d'e.fg", 694c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "a@d*e.fg", "a@d+e.fg", "a@d/e.fg", "a@d=e.fg", "a@d?e.fg", "a@d^e.fg", "a@d{}e.fg", 704c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "a@d|e.fg", "a@d~e.fg", 714c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // The domain is too long 724c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "no@domain-label-cannot-be-longer-than-63-chars-but-this-is-64-chars.com", 734c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "john@doe@example.com", // @ must be unique. 744c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // Incorrect double quote. 754c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // TODO(regisd): Fix Rfc822tokenizer which strips the quotes 764c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps // "just\"not\"right@example.com", "\"just.not\\\"@example.com", 774c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps "this\\ still\\\"not\\\\allowed@example.com" 784c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps }; 79b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook 80b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook @SmallTest 81b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook public void testEmailValidator() { 82b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook Rfc822Validator validator = new Rfc822Validator("gmail.com"); 83b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook 844c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps for (String email : VALID_EMAILS) { 85b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook assertTrue(email + " should be a valid email address", validator.isValid(email)); 86b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook } 87b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook 884c384ab3ae7621e602a95aeac6e527a52bb5598cRégis Décamps for (String email : INVALID_EMAILS) { 89b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook assertFalse(email + " should not be a valid email address", validator.isValid(email)); 90b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook } 91b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook 92b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook Map<String, String> fixes = new HashMap<String, String>(); 93b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook fixes.put("a", "<a@gmail.com>"); 94b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook fixes.put("a b", "<ab@gmail.com>"); 95b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook fixes.put("a@b", "<a@b>"); 96490556a764a879cd0eaff358e90705cc1335c92eErik fixes.put("()~><@not.work", ""); 97490556a764a879cd0eaff358e90705cc1335c92eErik 98490556a764a879cd0eaff358e90705cc1335c92eErik for (Map.Entry<String, String> e : fixes.entrySet()) { 99490556a764a879cd0eaff358e90705cc1335c92eErik assertEquals(e.getValue(), validator.fixText(e.getKey()).toString()); 100490556a764a879cd0eaff358e90705cc1335c92eErik } 101490556a764a879cd0eaff358e90705cc1335c92eErik } 102490556a764a879cd0eaff358e90705cc1335c92eErik 103490556a764a879cd0eaff358e90705cc1335c92eErik @SmallTest 104490556a764a879cd0eaff358e90705cc1335c92eErik public void testEmailValidatorNullDomain() { 105490556a764a879cd0eaff358e90705cc1335c92eErik Rfc822Validator validator = new Rfc822Validator(null); 106490556a764a879cd0eaff358e90705cc1335c92eErik 107490556a764a879cd0eaff358e90705cc1335c92eErik Map<String, String> fixes = new HashMap<String, String>(); 108490556a764a879cd0eaff358e90705cc1335c92eErik fixes.put("a", "<a>"); 109490556a764a879cd0eaff358e90705cc1335c92eErik fixes.put("a b", "<a b>"); 110490556a764a879cd0eaff358e90705cc1335c92eErik fixes.put("a@b", "<a@b>"); 111490556a764a879cd0eaff358e90705cc1335c92eErik fixes.put("a@b.com", "<a@b.com>"); // this one is correct 112490556a764a879cd0eaff358e90705cc1335c92eErik 113490556a764a879cd0eaff358e90705cc1335c92eErik for (Map.Entry<String, String> e : fixes.entrySet()) { 114490556a764a879cd0eaff358e90705cc1335c92eErik assertEquals(e.getValue(), validator.fixText(e.getKey()).toString()); 115490556a764a879cd0eaff358e90705cc1335c92eErik } 116490556a764a879cd0eaff358e90705cc1335c92eErik } 117490556a764a879cd0eaff358e90705cc1335c92eErik 118490556a764a879cd0eaff358e90705cc1335c92eErik @SmallTest 119490556a764a879cd0eaff358e90705cc1335c92eErik public void testEmailValidatorRemoveInvalid() { 120490556a764a879cd0eaff358e90705cc1335c92eErik Rfc822Validator validator = new Rfc822Validator("google.com"); 121490556a764a879cd0eaff358e90705cc1335c92eErik validator.setRemoveInvalid(true); 122490556a764a879cd0eaff358e90705cc1335c92eErik 123490556a764a879cd0eaff358e90705cc1335c92eErik Map<String, String> fixes = new HashMap<String, String>(); 124490556a764a879cd0eaff358e90705cc1335c92eErik fixes.put("a", ""); 125490556a764a879cd0eaff358e90705cc1335c92eErik fixes.put("a b", ""); 126490556a764a879cd0eaff358e90705cc1335c92eErik fixes.put("a@b", ""); 127490556a764a879cd0eaff358e90705cc1335c92eErik fixes.put("a@b.com", "<a@b.com>"); // this one is correct 128b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook 129b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook for (Map.Entry<String, String> e : fixes.entrySet()) { 130b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook assertEquals(e.getValue(), validator.fixText(e.getKey()).toString()); 131b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook } 132b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook } 133b4f5e0e5755938f2be9a2f1a1a6609b018c530adPaul Westbrook} 134