├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── src ├── main │ └── java │ │ └── com │ │ └── fewlaps │ │ └── quitnowemailsuggester │ │ ├── exception │ │ └── InvalidEmailException.java │ │ ├── util │ │ └── StringUtils.java │ │ ├── AndroidAccountEmailCleaner.java │ │ ├── bean │ │ └── EmailCorrection.java │ │ ├── EmailPartsSplitter.java │ │ ├── repository │ │ └── Repository.java │ │ ├── EmailValidator.java │ │ └── EmailSuggester.java └── test │ └── java │ └── com │ └── fewlaps │ └── quitnowemailsuggester │ ├── AndroidAccountEmailCleanerTest.java │ ├── util │ └── StringUtilsTest.java │ ├── EmailPartsSplitterTest.java │ ├── EmailSuggestorGoodEmailsTest.java │ ├── EmailValidatorTest.java │ └── EmailSuggestorBadEmailsTest.java ├── .travis.yml ├── .gitmodules ├── .gitignore ├── LICENSE.md ├── gradlew.bat ├── README.md └── gradlew /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'quitnow-email-suggester' 2 | 3 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fewlaps/quitnow-email-suggester/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/java/com/fewlaps/quitnowemailsuggester/exception/InvalidEmailException.java: -------------------------------------------------------------------------------- 1 | package com.fewlaps.quitnowemailsuggester.exception; 2 | 3 | public class InvalidEmailException extends Exception { 4 | } 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 4 | 5 | dist: trusty 6 | 7 | before_install: 8 | - chmod +x gradlew 9 | - git submodule update --init --recursive 10 | 11 | after_success: 12 | - ./gradlew cobertura coveralls 13 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/main/resources/list"] 2 | path = src/main/resources/list 3 | url = https://github.com/publicsuffix/list.git 4 | [submodule "src/main/resources/disposables"] 5 | path = src/main/resources/disposables 6 | url = https://github.com/ivolo/disposable-email-domains 7 | -------------------------------------------------------------------------------- /src/main/java/com/fewlaps/quitnowemailsuggester/util/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.fewlaps.quitnowemailsuggester.util; 2 | 3 | public class StringUtils { 4 | public String replaceLast(String text, String regex, String replacement) { 5 | return text.replaceFirst("(?s)(.*)" + regex, "$1" + replacement); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/fewlaps/quitnowemailsuggester/AndroidAccountEmailCleaner.java: -------------------------------------------------------------------------------- 1 | package com.fewlaps.quitnowemailsuggester; 2 | 3 | public class AndroidAccountEmailCleaner { 4 | 5 | public static final String ANDROID_ACCOUNT_SUFFIX_SEPARATOR = ":"; 6 | 7 | public String cleanEmail(String androidAccountEmail) { 8 | return androidAccountEmail.split(ANDROID_ACCOUNT_SUFFIX_SEPARATOR)[0]; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/fewlaps/quitnowemailsuggester/bean/EmailCorrection.java: -------------------------------------------------------------------------------- 1 | package com.fewlaps.quitnowemailsuggester.bean; 2 | 3 | public class EmailCorrection { 4 | private final String badEnd; 5 | private final String goodEnd; 6 | 7 | public EmailCorrection(String badEnd, String goodEnd) { 8 | this.badEnd = badEnd; 9 | this.goodEnd = goodEnd; 10 | } 11 | 12 | public String getBadEnd() { 13 | return badEnd; 14 | } 15 | 16 | public String getGoodEnd() { 17 | return goodEnd; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/com/fewlaps/quitnowemailsuggester/AndroidAccountEmailCleanerTest.java: -------------------------------------------------------------------------------- 1 | package com.fewlaps.quitnowemailsuggester; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | 8 | public class AndroidAccountEmailCleanerTest { 9 | 10 | AndroidAccountEmailCleaner aaec; 11 | 12 | @Before 13 | public void init() { 14 | aaec = new AndroidAccountEmailCleaner(); 15 | } 16 | 17 | @Test 18 | public void shouldRemainTheSame_whenEmailIsAValidOne() { 19 | String email = "roc@fewlaps.com"; 20 | String result = aaec.cleanEmail(email); 21 | assertEquals(email, result); 22 | } 23 | 24 | @Test 25 | public void shouldRemoveNonEmailPart_whenEmailHasIt() { 26 | String email = "bernat.borras@example.com:Office"; 27 | String result = aaec.cleanEmail(email); 28 | assertEquals("bernat.borras@example.com", result); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/com/fewlaps/quitnowemailsuggester/util/StringUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.fewlaps.quitnowemailsuggester.util; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | 6 | import static junit.framework.Assert.assertEquals; 7 | 8 | public class StringUtilsTest { 9 | 10 | StringUtils su; 11 | 12 | @Before 13 | public void init() { 14 | su = new StringUtils(); 15 | } 16 | 17 | @Test 18 | public void shouldReturnEmpty1() { 19 | assertEquals("", su.replaceLast("", "", "")); 20 | } 21 | 22 | @Test 23 | public void shouldReturnEmpty2() { 24 | assertEquals("", su.replaceLast("", "ll", "xx")); 25 | } 26 | 27 | @Test 28 | public void shouldReturnHeo() { 29 | assertEquals("heo", su.replaceLast("hello", "ll", "")); 30 | } 31 | 32 | @Test 33 | public void shouldReturnAaabxx() { 34 | assertEquals("aaabxx", su.replaceLast("aaabbb", "bb", "xx")); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio 2 | 3 | *.iml 4 | 5 | ## Directory-based project format: 6 | .idea/ 7 | # if you remove the above rule, at least ignore the following: 8 | 9 | # User-specific stuff: 10 | # .idea/workspace.xml 11 | # .idea/tasks.xml 12 | # .idea/dictionaries 13 | 14 | # Sensitive or high-churn files: 15 | # .idea/dataSources.ids 16 | # .idea/dataSources.xml 17 | # .idea/sqlDataSources.xml 18 | # .idea/dynamic.xml 19 | # .idea/uiDesigner.xml 20 | 21 | # Gradle: 22 | # .idea/gradle.xml 23 | # .idea/libraries 24 | 25 | # Mongo Explorer plugin: 26 | # .idea/mongoSettings.xml 27 | 28 | ## File-based project format: 29 | *.ipr 30 | *.iws 31 | 32 | ## Plugin-specific files: 33 | 34 | # IntelliJ 35 | /out/ 36 | 37 | # mpeltonen/sbt-idea plugin 38 | .idea_modules/ 39 | 40 | # JIRA plugin 41 | atlassian-ide-plugin.xml 42 | 43 | # Crashlytics plugin (for Android Studio and IntelliJ) 44 | com_crashlytics_export_strings.xml 45 | crashlytics.properties 46 | crashlytics-build.properties 47 | target/ 48 | release.properties 49 | .gradle/ 50 | build/ 51 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Fewlaps 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/java/com/fewlaps/quitnowemailsuggester/EmailPartsSplitter.java: -------------------------------------------------------------------------------- 1 | package com.fewlaps.quitnowemailsuggester; 2 | 3 | import com.fewlaps.quitnowemailsuggester.exception.InvalidEmailException; 4 | import com.fewlaps.quitnowemailsuggester.util.StringUtils; 5 | 6 | public class EmailPartsSplitter { 7 | 8 | EmailValidator ev = new EmailValidator(); 9 | 10 | public String getTld(String email) throws InvalidEmailException { 11 | if (email == null || !ev.hasGoodSyntax(email)) { 12 | throw new InvalidEmailException(); 13 | } 14 | 15 | String[] domainNameParts = getDomain(email).split("\\."); 16 | 17 | StringBuilder sb = new StringBuilder(); 18 | for (int i = 1; i <= domainNameParts.length - 1; i++) { 19 | sb.append(".").append(domainNameParts[i]); 20 | } 21 | sb.replace(0, 1, ""); 22 | return sb.toString(); 23 | } 24 | 25 | public String getDomain(String email) throws InvalidEmailException { 26 | if (email == null || !ev.hasGoodSyntax(email)) { 27 | throw new InvalidEmailException(); 28 | } 29 | 30 | return email.substring(email.indexOf('@') + 1); 31 | } 32 | 33 | public String getDomainWithoutTld(String email) throws InvalidEmailException { 34 | if (email == null || !ev.hasGoodSyntax(email)) { 35 | throw new InvalidEmailException(); 36 | } 37 | 38 | StringUtils stringUtils = new StringUtils(); 39 | return stringUtils.replaceLast(getDomain(email), ".".concat(getTld(email)), ""); 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /src/main/java/com/fewlaps/quitnowemailsuggester/repository/Repository.java: -------------------------------------------------------------------------------- 1 | package com.fewlaps.quitnowemailsuggester.repository; 2 | 3 | import com.google.gson.Gson; 4 | 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.IOException; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.Scanner; 11 | 12 | public class Repository { 13 | 14 | private final String SUFFIX_FILE_LOCATION = "list/public_suffix_list.dat"; 15 | private final String DISPOSABLES_FILE_LOCATION = "disposables/index.json"; 16 | 17 | public List getTlds() { 18 | try { 19 | List lines = new ArrayList(); 20 | FileInputStream inputStream = null; 21 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 22 | File file = new File(classLoader.getResource(SUFFIX_FILE_LOCATION).getFile()); 23 | Scanner sc = null; 24 | try { 25 | inputStream = new FileInputStream(file); 26 | sc = new Scanner(inputStream, "UTF-8"); 27 | while (sc.hasNextLine()) { 28 | lines.add(sc.nextLine()); 29 | } 30 | } finally { 31 | if (inputStream != null) { 32 | inputStream.close(); 33 | } 34 | if (sc != null) { 35 | sc.close(); 36 | } 37 | } 38 | 39 | return lines; 40 | } catch (IOException e) { 41 | return null; 42 | } 43 | } 44 | 45 | public String[] getDisposables() { 46 | try { 47 | StringBuilder sb = new StringBuilder(); 48 | FileInputStream inputStream = null; 49 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 50 | File file = new File(classLoader.getResource(DISPOSABLES_FILE_LOCATION).getFile()); 51 | Scanner sc = null; 52 | try { 53 | inputStream = new FileInputStream(file); 54 | sc = new Scanner(inputStream, "UTF-8"); 55 | while (sc.hasNextLine()) { 56 | sb.append(sc.nextLine()); 57 | } 58 | } finally { 59 | if (inputStream != null) { 60 | inputStream.close(); 61 | } 62 | if (sc != null) { 63 | sc.close(); 64 | } 65 | } 66 | 67 | Gson gson = new Gson(); 68 | return gson.fromJson(sb.toString(), String[].class); 69 | } catch (IOException e) { 70 | return null; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/fewlaps/quitnowemailsuggester/EmailValidator.java: -------------------------------------------------------------------------------- 1 | package com.fewlaps.quitnowemailsuggester; 2 | 3 | import com.fewlaps.quitnowemailsuggester.exception.InvalidEmailException; 4 | import com.fewlaps.quitnowemailsuggester.repository.Repository; 5 | 6 | import java.io.IOException; 7 | import java.security.InvalidParameterException; 8 | import java.util.List; 9 | import java.util.regex.Matcher; 10 | import java.util.regex.Pattern; 11 | 12 | public class EmailValidator { 13 | 14 | private static final String EMAIL_PATTERN = 15 | "[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" + 16 | "\\@" + 17 | "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" + 18 | "(" + 19 | "\\." + 20 | "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" + 21 | ")+"; 22 | private static final String ALIAS_PATTERN = "([^\\s]+(\\+([\\w])*@))"; 23 | private final Pattern emailPattern; 24 | private final Pattern aliasPattern; 25 | private Matcher matcher; 26 | 27 | public EmailValidator() { 28 | emailPattern = Pattern.compile(EMAIL_PATTERN); 29 | aliasPattern = Pattern.compile(ALIAS_PATTERN); 30 | } 31 | 32 | public boolean hasGoodSyntax(String email) { 33 | if (email == null) { 34 | return false; 35 | } 36 | 37 | matcher = emailPattern.matcher(email); 38 | return matcher.matches(); 39 | } 40 | 41 | public boolean hasValidTld(String email) throws InvalidEmailException { 42 | if (email == null || email.isEmpty()) { 43 | throw new InvalidParameterException("The suffix can't be null or blank"); 44 | } 45 | 46 | String suffix = new EmailPartsSplitter().getTld(email); 47 | List lines = new Repository().getTlds(); 48 | 49 | for (String line : lines) { 50 | if (line.trim().equalsIgnoreCase(suffix)) { 51 | return true; 52 | } 53 | } 54 | return false; 55 | } 56 | 57 | public boolean isAlias(String email) { 58 | return hasGoodSyntax(email) && aliasPattern.matcher(email).find(); 59 | } 60 | 61 | public boolean isDisposable(String email) throws InvalidEmailException { 62 | if (email == null || email.isEmpty()) { 63 | throw new InvalidParameterException("The email can't be null or blank"); 64 | } 65 | 66 | String domain = new EmailPartsSplitter().getDomain(email); 67 | String[] disposables = new Repository().getDisposables(); 68 | 69 | for (String disposable : disposables) { 70 | if (disposable.equals(domain)) { 71 | return true; 72 | } 73 | } 74 | return false; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/test/java/com/fewlaps/quitnowemailsuggester/EmailPartsSplitterTest.java: -------------------------------------------------------------------------------- 1 | package com.fewlaps.quitnowemailsuggester; 2 | 3 | import com.fewlaps.quitnowemailsuggester.exception.InvalidEmailException; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import static junit.framework.Assert.assertEquals; 8 | 9 | public class EmailPartsSplitterTest { 10 | 11 | EmailPartsSplitter ep; 12 | 13 | @Before 14 | public void init() { 15 | ep = new EmailPartsSplitter(); 16 | } 17 | 18 | @Test 19 | public void shouldReturnCom() throws InvalidEmailException { 20 | assertEquals("com", ep.getTld("roc@fewlaps.com")); 21 | } 22 | 23 | @Test 24 | public void shouldReturnAt() throws InvalidEmailException { 25 | assertEquals("at", ep.getTld("roc@rocboron.at")); 26 | } 27 | 28 | @Test 29 | public void shouldReturnComDotUk() throws InvalidEmailException { 30 | assertEquals("co.uk", ep.getTld("roc@fewlaps.co.uk")); 31 | } 32 | 33 | @Test 34 | public void shouldReturnFewlapsDotCom() throws InvalidEmailException { 35 | assertEquals("fewlaps.com", ep.getDomain("roc@fewlaps.com")); 36 | } 37 | 38 | @Test 39 | public void shouldReturnFewlapsDotCoDotUk() throws InvalidEmailException { 40 | assertEquals("fewlaps.co.uk", ep.getDomain("roc@fewlaps.co.uk")); 41 | } 42 | 43 | @Test 44 | public void shouldReturnFewlaps() throws InvalidEmailException { 45 | assertEquals("fewlaps", ep.getDomainWithoutTld("roc@fewlaps.co.uk")); 46 | } 47 | 48 | @Test 49 | public void shouldReturnRocboron() throws InvalidEmailException { 50 | assertEquals("rocboron", ep.getDomainWithoutTld("roc@rocboron.at")); 51 | } 52 | 53 | @Test 54 | public void shouldReturnGmail() throws InvalidEmailException { 55 | assertEquals("gmail", ep.getDomainWithoutTld("roc@gmail.com")); 56 | } 57 | 58 | /** 59 | * Key test with IT, 'cause "hitmail" contains "it", the TLD 60 | */ 61 | @Test 62 | public void shouldReturnHitmail() throws InvalidEmailException { 63 | assertEquals("hitmail", ep.getDomainWithoutTld("roc@hitmail.it")); 64 | } 65 | 66 | @Test(expected = InvalidEmailException.class) 67 | public void shouldLaunchAnInvalidEmailExceptionForNullAtGetTld() throws InvalidEmailException { 68 | ep.getTld(null); 69 | } 70 | 71 | @Test(expected = InvalidEmailException.class) 72 | public void shouldLaunchAnInvalidEmailExceptionForNopeAtGetTld() throws InvalidEmailException { 73 | ep.getTld("nope"); 74 | } 75 | 76 | @Test(expected = InvalidEmailException.class) 77 | public void shouldLaunchAnInvalidEmailExceptionForNullAtGetDomain() throws InvalidEmailException { 78 | ep.getDomain(null); 79 | } 80 | 81 | @Test(expected = InvalidEmailException.class) 82 | public void shouldLaunchAnInvalidEmailExceptionForNopeAtGetDomain() throws InvalidEmailException { 83 | ep.getDomain("nope"); 84 | } 85 | 86 | @Test(expected = InvalidEmailException.class) 87 | public void shouldLaunchAnInvalidEmailExceptionForNullAtGetDomainWoTld() throws InvalidEmailException { 88 | ep.getDomainWithoutTld(null); 89 | } 90 | 91 | @Test(expected = InvalidEmailException.class) 92 | public void shouldLaunchAnInvalidEmailExceptionForNopeAtGetDomainWoTld() throws InvalidEmailException { 93 | ep.getDomainWithoutTld("nope"); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/com/fewlaps/quitnowemailsuggester/EmailSuggester.java: -------------------------------------------------------------------------------- 1 | package com.fewlaps.quitnowemailsuggester; 2 | 3 | import com.fewlaps.quitnowemailsuggester.bean.EmailCorrection; 4 | import com.fewlaps.quitnowemailsuggester.exception.InvalidEmailException; 5 | 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | public class EmailSuggester { 10 | 11 | public static final String YAHOO = "yahoo"; 12 | public static final String GMAIL = "gmail"; 13 | public static final String HOTMAIL = "hotmail"; 14 | public static final String OUTLOOK = "outlook"; 15 | 16 | public static final String COM = "com"; 17 | 18 | public static final String DOTCOM = ".com"; 19 | public static final String DOTNET = ".net"; 20 | public static final String DOTFR = ".fr"; 21 | 22 | public List tldCorrections = Arrays.asList( 23 | new EmailCorrection(".cpm", DOTCOM), 24 | new EmailCorrection(".cpn", DOTCOM), 25 | new EmailCorrection(".con", DOTCOM), 26 | new EmailCorrection(".col", DOTCOM), 27 | new EmailCorrection(".comm", DOTCOM), 28 | new EmailCorrection(".cxom", DOTCOM), 29 | new EmailCorrection(".coml", DOTCOM), 30 | new EmailCorrection(".clm", DOTCOM), 31 | new EmailCorrection(".cm", DOTCOM), 32 | new EmailCorrection(".ney", DOTNET), 33 | new EmailCorrection(".nte", DOTNET), 34 | new EmailCorrection(".ft", DOTFR), 35 | new EmailCorrection(".vom", DOTCOM), 36 | new EmailCorrection(".fe", DOTFR) 37 | ); 38 | 39 | public List domainCorrections = Arrays.asList( 40 | new EmailCorrection("gnail", GMAIL), 41 | new EmailCorrection("gmial", GMAIL), 42 | new EmailCorrection("gmaail", GMAIL), 43 | new EmailCorrection("gnail", GMAIL), 44 | new EmailCorrection("gamil", GMAIL), 45 | new EmailCorrection("gmal", GMAIL), 46 | new EmailCorrection("ygmail", GMAIL), 47 | new EmailCorrection("gmai", GMAIL), 48 | new EmailCorrection("gimail", GMAIL), 49 | new EmailCorrection("gmaik", GMAIL), 50 | new EmailCorrection("gemail", GMAIL), 51 | new EmailCorrection("gmali", GMAIL), 52 | 53 | new EmailCorrection("hotmaail", HOTMAIL), 54 | new EmailCorrection("hotmal", HOTMAIL), 55 | new EmailCorrection("hotmai", HOTMAIL), 56 | new EmailCorrection("hotmali", HOTMAIL), 57 | new EmailCorrection("hitmail", HOTMAIL), 58 | new EmailCorrection("hotmial", HOTMAIL), 59 | new EmailCorrection("hotmale", HOTMAIL), 60 | new EmailCorrection("homtail", HOTMAIL), 61 | new EmailCorrection("hotnail", HOTMAIL), 62 | new EmailCorrection("hormail", HOTMAIL), 63 | new EmailCorrection("hotmmail", HOTMAIL), 64 | 65 | new EmailCorrection("yaho", YAHOO), 66 | new EmailCorrection("yaoo", YAHOO), 67 | new EmailCorrection("yaboo", YAHOO), 68 | new EmailCorrection("yahou", YAHOO), 69 | new EmailCorrection("uahoo", YAHOO), 70 | new EmailCorrection("yhoo", YAHOO), 71 | 72 | new EmailCorrection("outllok", OUTLOOK), 73 | new EmailCorrection("outilook", OUTLOOK) 74 | ); 75 | 76 | public List domainAndTldCorrections = Arrays.asList( 77 | new EmailCorrection("gmail.co", GMAIL + DOTCOM), 78 | new EmailCorrection("yahoo.om", YAHOO + DOTCOM), 79 | new EmailCorrection("gmail.om", GMAIL + DOTCOM) 80 | ); 81 | 82 | public String getSuggestedEmail(String email) throws InvalidEmailException { 83 | if (email == null) { 84 | throw new InvalidEmailException(); 85 | } 86 | 87 | email = fixComWithAnotherChar(email); 88 | for (EmailCorrection correction : tldCorrections) { 89 | email = fixTld(email, correction.getBadEnd(), correction.getGoodEnd()); 90 | } 91 | for (EmailCorrection correction : domainCorrections) { 92 | email = fixDomain(email, correction.getBadEnd(), correction.getGoodEnd()); 93 | } 94 | for (EmailCorrection correction : domainAndTldCorrections) { 95 | email = fixDomainAndTld(email, correction.getBadEnd(), correction.getGoodEnd()); 96 | } 97 | 98 | return email; 99 | } 100 | 101 | private String fixComWithAnotherChar(String email) throws InvalidEmailException { 102 | EmailPartsSplitter ep = new EmailPartsSplitter(); 103 | String tld = ep.getTld(email); 104 | if (tld.contains(COM) && tld.length() == COM.length() + 1) {//if it's coma, comb, comc, acom, bcom, ccom... 105 | return fixTld(email, tld, COM); 106 | } else { 107 | return email; 108 | } 109 | } 110 | 111 | private String fixTld(String email, String badTld, String goodTld) { 112 | if (email.endsWith(badTld)) { 113 | email = email.substring(0, email.length() - badTld.length()).concat(goodTld); 114 | } 115 | return email; 116 | } 117 | 118 | private String fixDomain(String email, String badDomain, String goodDomain) throws InvalidEmailException { 119 | EmailPartsSplitter ep = new EmailPartsSplitter(); 120 | String domain = ep.getDomainWithoutTld(email); 121 | if (domain.equals(badDomain)) { 122 | email = email.replaceAll(domain, goodDomain); 123 | } 124 | return email; 125 | } 126 | 127 | private String fixDomainAndTld(String email, String badDomainAndTld, String goodDomainAndTld) { 128 | if (email.endsWith(badDomainAndTld)) { 129 | email = email.substring(0, email.length() - badDomainAndTld.length()).concat(goodDomainAndTld); 130 | } 131 | return email; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/Fewlaps/quitnow-email-suggester.svg?branch=master)](https://travis-ci.org/Fewlaps/quitnow-email-suggester) 2 | [![Coverage Status](https://coveralls.io/repos/Fewlaps/quitnow-email-suggester/badge.svg?branch=master&service=github)](https://coveralls.io/github/Fewlaps/quitnow-email-suggester?branch=master) 3 | [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-quitnow--email--suggester-green.svg?style=flat)](https://android-arsenal.com/details/1/2465) 4 | [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Fewlaps/quitnow-email-suggester?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) 5 | 6 | # [QuitNow!](http://quitnowapp.com)'s e-mail suggester 7 | People don't write e-mail addresses without misspelling from time to time. @gmial.con addresses are too common... And we need to put a stop to it! 8 | 9 | QuitNow!'s server is doing the usual e-mail validaton during user creation time. We're doing it like everyone does: sending an e-mail to the user, and waiting for the user to click a link. The only validation we do is to check the e-mail with usual regex... but we need to go a little beyond that. Looking for *.con* and suggesting *.com* is something that would make the world a better place! 10 | 11 | By the way, we recently learnt a lot about TDD (Test-Driven Development) at some [Karumi](https://github.com/Karumi) masterclasses, so we decided to go on with TDD. The only way to master something is by doing. Incidentally, it will be useful if we improve our e-mail validation (and, hopefully, yours). 12 | 13 | If you want to see what suggestions and validations are being done, check the actual tests. It's an easy way for us to document the behaviour, and it's the tried-and-true list for you to know what's exactly happening here. 14 | 15 | ## How it works? 16 | 17 | ### Email suggester 18 | ```java 19 | // Hello! Let me show the magic of this library: the email suggester 20 | EmailSuggester suggester = new EmailSuggester(); 21 | 22 | // It is a little thing that has an algorithm to fix human typos. 23 | // Let's say your user mistyped his email address: 24 | String badEmail = "roc@gmial.com"; 25 | String goodEmail = suggester.getSuggestedEmail(badEmail); 26 | // goodEmail will contain the fixed email address. WOW! 27 | // And there are tons of email fixes. They're listed at https://goo.gl/IF52EV 28 | // In addition, it will never suggest a bad domain. All the suggestions are written one by one, 29 | // based on the QuitNow! users and their e-mail bounces. If it doesn't know nothing 30 | // better than the input, it will return the same email. 31 | ``` 32 | 33 | ### Email validator & Android account email cleaner 34 | ```java 35 | // Well! Something else? Yes: this library hosts some more email related things 36 | EmailValidator validator = new EmailValidator(); 37 | validator.hasGoodSyntax(goodEmail); //Does it match the email regex? 38 | validator.hasValidTld(goodEmail); //Has it a valid TLD? 39 | validator.isAlias(goodEmail); //Is it an alias? 40 | validator.isDisposable(goodEmail); //Is it listed as a disposable domain? 41 | 42 | // To finish up: if you work with Android, you'll find roc@fewlaps.com:WhatEVER emails 43 | // If you want to clean them, here it goes: 44 | AndroidAccountEmailCleaner cleaner = new AndroidAccountEmailCleaner(); 45 | String androidAccountEmail = "roc@fewlaps.com:WhatEVER"; 46 | String cleanedEmail = cleaner.cleanEmail(androidAccountEmail); 47 | // cleanedEmail will contain roc@fewlaps.com 48 | ``` 49 | 50 | 51 | #### *.hasValidTld()* and *.isDisposable()* under the hood 52 | - *.hasValidTld()* is getting data from this public repo: https://github.com/publicsuffix/list 53 | - *.isDisposable()* is checking the domain against this another one: https://github.com/ivolo/disposable-email-domains 54 | 55 | The files needs to be attached to the project cause they're parsed locally. 56 | 57 | So, before starting, initalise git submodules: 58 | 59 | ``` 60 | git submodule update --init --recursive 61 | ``` 62 | 63 | ## Download 64 | 65 | * Get the latest .jar 66 | 67 | * Grab via Gradle: 68 | ```groovy 69 | repositories { jcenter() } 70 | 71 | compile 'com.fewlaps.quitnowemailsuggester:quitnow-email-suggester:2.0.0' 72 | ``` 73 | * Grab via Maven: 74 | ```xml 75 | 76 | jcenter 77 | http://jcenter.bintray.com 78 | 79 | 80 | 81 | com.fewlaps.quitnowemailsuggester 82 | quitnow-email-suggester 83 | 2.0.0 84 | 85 | ``` 86 | 87 | ## LICENSE 88 | 89 | The MIT License (MIT) 90 | 91 | Copyright (c) 2015 Fewlaps 92 | 93 | Permission is hereby granted, free of charge, to any person obtaining a copy 94 | of this software and associated documentation files (the "Software"), to deal 95 | in the Software without restriction, including without limitation the rights 96 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 97 | copies of the Software, and to permit persons to whom the Software is 98 | furnished to do so, subject to the following conditions: 99 | 100 | The above copyright notice and this permission notice shall be included in all 101 | copies or substantial portions of the Software. 102 | 103 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 104 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 105 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 106 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 107 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 108 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 109 | SOFTWARE. 110 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /src/test/java/com/fewlaps/quitnowemailsuggester/EmailSuggestorGoodEmailsTest.java: -------------------------------------------------------------------------------- 1 | package com.fewlaps.quitnowemailsuggester; 2 | 3 | import com.fewlaps.quitnowemailsuggester.exception.InvalidEmailException; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | import static org.junit.Assert.assertTrue; 9 | 10 | /** 11 | * This will use the most common e-mails, testing that they are valid and the suggested emails are not different as the sent ones 12 | */ 13 | public class EmailSuggestorGoodEmailsTest { 14 | 15 | EmailSuggester es; 16 | EmailValidator ev; 17 | 18 | @Before 19 | public void init() { 20 | es = new EmailSuggester(); 21 | ev = new EmailValidator(); 22 | } 23 | 24 | @Test 25 | public void shouldBeValidAndUnsuggestedRocboronatDotNet() throws InvalidEmailException { 26 | String email = "roc@rocboronat.net"; 27 | assertTrue(ev.hasGoodSyntax(email)); 28 | assertEquals(email, es.getSuggestedEmail(email)); 29 | } 30 | 31 | @Test 32 | public void shouldBeValidAndUnsuggestedRocbonDotAt() throws InvalidEmailException { 33 | String email = "roc@rocboron.at"; 34 | assertTrue(ev.hasGoodSyntax(email)); 35 | assertEquals(email, es.getSuggestedEmail(email)); 36 | } 37 | 38 | @Test 39 | public void shouldBeValidAndUnsuggestedFewlaps() throws InvalidEmailException { 40 | String email = "roc@fewlaps.com"; 41 | assertTrue(ev.hasGoodSyntax(email)); 42 | assertEquals(email, es.getSuggestedEmail(email)); 43 | } 44 | 45 | @Test 46 | public void shouldBeValidAndUnsuggestedDotCo() throws InvalidEmailException { 47 | String email = "roc@roc.co"; 48 | assertTrue(ev.hasGoodSyntax(email)); 49 | assertEquals(email, es.getSuggestedEmail(email)); 50 | } 51 | 52 | @Test 53 | public void shouldBeValidAndUnsuggested1() throws InvalidEmailException { 54 | String email = "roc@gmail.com"; 55 | assertTrue(ev.hasGoodSyntax(email)); 56 | assertEquals(email, es.getSuggestedEmail(email)); 57 | } 58 | 59 | @Test 60 | public void shouldBeValidAndUnsuggested2() throws InvalidEmailException { 61 | String email = "roc@hotmail.com"; 62 | assertTrue(ev.hasGoodSyntax(email)); 63 | assertEquals(email, es.getSuggestedEmail(email)); 64 | } 65 | 66 | @Test 67 | public void shouldBeValidAndUnsuggested3() throws InvalidEmailException { 68 | String email = "roc@yahoo.com"; 69 | assertTrue(ev.hasGoodSyntax(email)); 70 | assertEquals(email, es.getSuggestedEmail(email)); 71 | } 72 | 73 | @Test 74 | public void shouldBeValidAndUnsuggested4() throws InvalidEmailException { 75 | String email = "roc@hotmail.fr"; 76 | assertTrue(ev.hasGoodSyntax(email)); 77 | assertEquals(email, es.getSuggestedEmail(email)); 78 | } 79 | 80 | @Test 81 | public void shouldBeValidAndUnsuggested5() throws InvalidEmailException { 82 | String email = "roc@mail.ru"; 83 | assertTrue(ev.hasGoodSyntax(email)); 84 | assertEquals(email, es.getSuggestedEmail(email)); 85 | } 86 | 87 | @Test 88 | public void shouldBeValidAndUnsuggested6() throws InvalidEmailException { 89 | String email = "roc@web.de"; 90 | assertTrue(ev.hasGoodSyntax(email)); 91 | assertEquals(email, es.getSuggestedEmail(email)); 92 | } 93 | 94 | @Test 95 | public void shouldBeValidAndUnsuggested7() throws InvalidEmailException { 96 | String email = "roc@outlook.com"; 97 | assertTrue(ev.hasGoodSyntax(email)); 98 | assertEquals(email, es.getSuggestedEmail(email)); 99 | } 100 | 101 | @Test 102 | public void shouldBeValidAndUnsuggested8() throws InvalidEmailException { 103 | String email = "roc@gmx.de"; 104 | assertTrue(ev.hasGoodSyntax(email)); 105 | assertEquals(email, es.getSuggestedEmail(email)); 106 | } 107 | 108 | @Test 109 | public void shouldBeValidAndUnsuggested9() throws InvalidEmailException { 110 | String email = "roc@live.com"; 111 | assertTrue(ev.hasGoodSyntax(email)); 112 | assertEquals(email, es.getSuggestedEmail(email)); 113 | } 114 | 115 | @Test 116 | public void shouldBeValidAndUnsuggested10() throws InvalidEmailException { 117 | String email = "roc@hotmail.it"; 118 | assertTrue(ev.hasGoodSyntax(email)); 119 | assertEquals(email, es.getSuggestedEmail(email)); 120 | } 121 | 122 | @Test 123 | public void shouldBeValidAndUnsuggested11() throws InvalidEmailException { 124 | String email = "roc@googlemail.com"; 125 | assertTrue(ev.hasGoodSyntax(email)); 126 | assertEquals(email, es.getSuggestedEmail(email)); 127 | } 128 | 129 | @Test 130 | public void shouldBeValidAndUnsuggested12() throws InvalidEmailException { 131 | String email = "roc@aol.com"; 132 | assertTrue(ev.hasGoodSyntax(email)); 133 | assertEquals(email, es.getSuggestedEmail(email)); 134 | } 135 | 136 | @Test 137 | public void shouldBeValidAndUnsuggested13() throws InvalidEmailException { 138 | String email = "roc@libero.it"; 139 | assertTrue(ev.hasGoodSyntax(email)); 140 | assertEquals(email, es.getSuggestedEmail(email)); 141 | } 142 | 143 | @Test 144 | public void shouldBeValidAndUnsuggested14() throws InvalidEmailException { 145 | String email = "roc@yahoo.fr"; 146 | assertTrue(ev.hasGoodSyntax(email)); 147 | assertEquals(email, es.getSuggestedEmail(email)); 148 | } 149 | 150 | @Test 151 | public void shouldBeValidAndUnsuggested15() throws InvalidEmailException { 152 | String email = "roc@live.nl"; 153 | assertTrue(ev.hasGoodSyntax(email)); 154 | assertEquals(email, es.getSuggestedEmail(email)); 155 | } 156 | 157 | @Test 158 | public void shouldBeValidAndUnsuggested16() throws InvalidEmailException { 159 | String email = "roc@yahoo.de"; 160 | assertTrue(ev.hasGoodSyntax(email)); 161 | assertEquals(email, es.getSuggestedEmail(email)); 162 | } 163 | 164 | @Test 165 | public void shouldBeValidAndUnsuggested17() throws InvalidEmailException { 166 | String email = "roc@hotmail.co"; 167 | assertTrue(ev.hasGoodSyntax(email)); 168 | assertEquals(email, es.getSuggestedEmail(email)); 169 | } 170 | 171 | @Test 172 | public void shouldBeValidAndUnsuggested18() throws InvalidEmailException { 173 | String email = "roc@icloud.com"; 174 | assertTrue(ev.hasGoodSyntax(email)); 175 | assertEquals(email, es.getSuggestedEmail(email)); 176 | } 177 | 178 | @Test 179 | public void shouldBeValidAndUnsuggested19() throws InvalidEmailException { 180 | String email = "roc@yandex.ru"; 181 | assertTrue(ev.hasGoodSyntax(email)); 182 | assertEquals(email, es.getSuggestedEmail(email)); 183 | } 184 | 185 | @Test 186 | public void shouldBeValidAndUnsuggested20() throws InvalidEmailException { 187 | String email = "roc@live.fr"; 188 | assertTrue(ev.hasGoodSyntax(email)); 189 | assertEquals(email, es.getSuggestedEmail(email)); 190 | } 191 | 192 | @Test 193 | public void shouldBeValidAndUnsuggested21() throws InvalidEmailException { 194 | String email = "fewlaps@something.com.pe"; 195 | assertTrue(ev.hasGoodSyntax(email)); 196 | assertEquals(email, es.getSuggestedEmail(email)); 197 | } 198 | 199 | @Test 200 | public void emailWithNumbersShouldBeValid() throws InvalidEmailException { 201 | String email = "fewlaps1fewlaps@yahoo.com"; 202 | assertTrue(ev.hasGoodSyntax(email)); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /src/test/java/com/fewlaps/quitnowemailsuggester/EmailValidatorTest.java: -------------------------------------------------------------------------------- 1 | package com.fewlaps.quitnowemailsuggester; 2 | 3 | import com.fewlaps.quitnowemailsuggester.exception.InvalidEmailException; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import java.security.InvalidParameterException; 8 | 9 | import static junit.framework.Assert.assertFalse; 10 | import static junit.framework.TestCase.assertTrue; 11 | 12 | public class EmailValidatorTest { 13 | 14 | EmailValidator ev; 15 | 16 | @Before 17 | public void init() { 18 | ev = new EmailValidator(); 19 | } 20 | 21 | //region isValidEmailSyntax 22 | @Test 23 | public void shouldSayFalseForNull() { 24 | assertFalse(ev.hasGoodSyntax(null)); 25 | } 26 | 27 | @Test 28 | public void shouldSayFalseForEmpty() { 29 | assertFalse(ev.hasGoodSyntax("")); 30 | } 31 | 32 | @Test 33 | public void shouldSayOK1() { 34 | assertTrue(ev.hasGoodSyntax("roc@rocboron.at")); 35 | } 36 | 37 | @Test 38 | public void shouldSayOK2() { 39 | assertTrue(ev.hasGoodSyntax("email@example.com")); 40 | } 41 | 42 | @Test 43 | public void shouldSayOK3() { 44 | assertTrue(ev.hasGoodSyntax("firstname.lastname@example.com")); 45 | } 46 | 47 | @Test 48 | public void shouldSayOK4() { 49 | assertTrue(ev.hasGoodSyntax("email@subdomain.example.com")); 50 | } 51 | 52 | @Test 53 | public void shouldSayOK5() { 54 | assertTrue(ev.hasGoodSyntax("firstname+lastname@example.com")); 55 | } 56 | 57 | @Test 58 | public void shouldSayOK6() { 59 | assertTrue(ev.hasGoodSyntax("1234567890@example.com")); 60 | } 61 | 62 | @Test 63 | public void shouldSayOK7() { 64 | assertTrue(ev.hasGoodSyntax("email@example-one.com")); 65 | } 66 | 67 | @Test 68 | public void shouldSayOK8() { 69 | assertTrue(ev.hasGoodSyntax("_______@example.com")); 70 | } 71 | 72 | @Test 73 | public void shouldSayOK9() { 74 | assertTrue(ev.hasGoodSyntax("email@example.name")); 75 | } 76 | 77 | @Test 78 | public void shouldSayOK10() { 79 | assertTrue(ev.hasGoodSyntax("email@example.museum")); 80 | } 81 | 82 | @Test 83 | public void shouldSayOK11() { 84 | assertTrue(ev.hasGoodSyntax("email@example.co.jp")); 85 | } 86 | 87 | @Test 88 | public void shouldSayOK12() { 89 | assertTrue(ev.hasGoodSyntax("firstname-lastname@example.com")); 90 | } 91 | 92 | @Test 93 | public void shouldSayKO1() { 94 | assertFalse(ev.hasGoodSyntax("plainaddress")); 95 | } 96 | 97 | @Test 98 | public void shouldSayKO2() { 99 | assertFalse(ev.hasGoodSyntax("#@%^%#$@#$@#.com")); 100 | } 101 | 102 | @Test 103 | public void shouldSayKO3() { 104 | assertFalse(ev.hasGoodSyntax("@example.com")); 105 | } 106 | 107 | @Test 108 | public void shouldSayKO4() { 109 | assertFalse(ev.hasGoodSyntax("Joe Smith ")); 110 | } 111 | 112 | @Test 113 | public void shouldSayKO5() { 114 | assertFalse(ev.hasGoodSyntax("email.example.com")); 115 | } 116 | 117 | @Test 118 | public void shouldSayKO6() { 119 | assertFalse(ev.hasGoodSyntax("email@example@example.com")); 120 | } 121 | 122 | @Test 123 | public void shouldSayKO7() { 124 | assertTrue(ev.hasGoodSyntax(".email@example.com")); 125 | } 126 | 127 | @Test 128 | public void shouldSayKO8() { 129 | assertTrue(ev.hasGoodSyntax("email.@example.com")); 130 | } 131 | 132 | @Test 133 | public void shouldSayKO9() { 134 | assertTrue(ev.hasGoodSyntax("email..email@example.com")); 135 | } 136 | 137 | @Test 138 | public void shouldSayKO10() { 139 | assertFalse(ev.hasGoodSyntax("?????@example.com")); 140 | } 141 | 142 | @Test 143 | public void shouldSayKO11() { 144 | assertFalse(ev.hasGoodSyntax("email@example.com (Joe Smith)")); 145 | } 146 | 147 | @Test 148 | public void shouldSayKO12() { 149 | assertFalse(ev.hasGoodSyntax("email@example")); 150 | } 151 | 152 | @Test 153 | public void shouldSayKO13() { 154 | assertTrue(ev.hasGoodSyntax("email@111.222.333.44444")); 155 | } 156 | 157 | @Test 158 | public void shouldSayKO14() { 159 | assertFalse(ev.hasGoodSyntax("email@example..com")); 160 | } 161 | 162 | @Test 163 | public void shouldSayKO15() { 164 | assertTrue(ev.hasGoodSyntax("Abc..123@example.com")); 165 | } 166 | 167 | @Test 168 | public void shouldSayKO16() { 169 | assertFalse(ev.hasGoodSyntax("�(),:;<>[\\]@example.com")); 170 | } 171 | 172 | @Test 173 | public void shouldSayKO17() { 174 | assertFalse(ev.hasGoodSyntax("just\"not\"right@example.com")); 175 | } 176 | 177 | @Test 178 | public void shouldSayKO18() { 179 | assertFalse(ev.hasGoodSyntax("this\\ is\"really\"not\\allowed@example.com")); 180 | } 181 | //endregion 182 | 183 | //region .isAlias() 184 | @Test 185 | public void aliasTest01() { 186 | assertTrue(ev.isAlias("alias+test@example.com")); 187 | } 188 | 189 | @Test 190 | public void aliasTest02() { 191 | assertTrue(ev.isAlias("alias+test+me@example.com")); 192 | } 193 | 194 | @Test 195 | public void aliasTest03() { 196 | assertTrue(ev.isAlias("alias+e@example.com")); 197 | } 198 | 199 | @Test 200 | public void aliasTest04() { 201 | assertFalse(ev.isAlias("alias@example.com")); 202 | } 203 | 204 | @Test 205 | public void aliasTest05() { 206 | assertFalse(ev.isAlias("alias+me@.example.com")); 207 | } 208 | //endregion 209 | 210 | //region .hasValidTld 211 | @Test 212 | public void checkValidTld01() throws InvalidEmailException { 213 | assertTrue(ev.hasValidTld("something@fewlaps.co.uk")); 214 | } 215 | 216 | @Test 217 | public void checkValidTld02() throws InvalidEmailException { 218 | assertTrue(ev.hasValidTld("something@fewlaps.com")); 219 | } 220 | 221 | @Test 222 | public void checkValidTldBarcelona() throws InvalidEmailException { 223 | assertTrue(ev.hasValidTld("something@fewlaps.barcelona")); 224 | } 225 | 226 | @Test 227 | public void shouldReturnFalse_forInvalidCon() throws InvalidEmailException { 228 | assertFalse(ev.hasValidTld("something@fewlaps.con")); 229 | } 230 | 231 | @Test(expected = InvalidParameterException.class) 232 | public void shouldLaunchAnInvalidParameterException_forBlank() throws InvalidEmailException { 233 | ev.hasValidTld(""); 234 | } 235 | 236 | @Test(expected = InvalidParameterException.class) 237 | public void shouldLaunchAnInvalidParameterException_forNull() throws InvalidEmailException { 238 | ev.hasValidTld(null); 239 | } 240 | //endregion 241 | 242 | //region .isDisposable() 243 | @Test 244 | public void shouldSayTrue_fakeInboxCom() throws InvalidEmailException { 245 | String email = "something@fakeinbox.com"; 246 | boolean result = ev.isDisposable(email); 247 | assertTrue(result); 248 | } 249 | 250 | @Test 251 | public void shouldSayFalse_fewlapsCom() throws InvalidEmailException { 252 | String email = "something@fewlaps.com"; 253 | boolean result = ev.isDisposable(email); 254 | assertFalse(result); 255 | } 256 | 257 | @Test(expected = InvalidParameterException.class) 258 | public void shouldLaunchAnException_whenEmailIsNull() throws InvalidEmailException { 259 | String email = null; 260 | ev.isDisposable(email); 261 | } 262 | 263 | @Test(expected = InvalidParameterException.class) 264 | public void shouldLaunchAnException_whenEmailIsBlank() throws InvalidEmailException { 265 | String email = ""; 266 | ev.isDisposable(email); 267 | } 268 | //endregion 269 | } 270 | -------------------------------------------------------------------------------- /src/test/java/com/fewlaps/quitnowemailsuggester/EmailSuggestorBadEmailsTest.java: -------------------------------------------------------------------------------- 1 | package com.fewlaps.quitnowemailsuggester; 2 | 3 | import com.fewlaps.quitnowemailsuggester.exception.InvalidEmailException; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import static junit.framework.TestCase.assertEquals; 8 | 9 | public class EmailSuggestorBadEmailsTest { 10 | 11 | EmailSuggester es; 12 | 13 | @Before 14 | public void init() { 15 | es = new EmailSuggester(); 16 | } 17 | 18 | @Test 19 | public void shouldLaunchAnInvalidEmailExceptionForNull() throws InvalidEmailException { 20 | try { 21 | es.getSuggestedEmail(null); 22 | } catch (InvalidEmailException e) { 23 | return; //This is what we expect 24 | } 25 | } 26 | 27 | @Test 28 | public void shouldLaunchAnInvalidEmailExceptionForEmpty() throws InvalidEmailException { 29 | try { 30 | es.getSuggestedEmail(""); 31 | } catch (InvalidEmailException e) { 32 | return; //This is what we expect 33 | } 34 | } 35 | 36 | @Test 37 | public void shouldLaunchAnInvalidEmailExceptionForAnInvalidEmail() throws InvalidEmailException { 38 | try { 39 | es.getSuggestedEmail("roc@roc@roc"); 40 | } catch (InvalidEmailException e) { 41 | return; //This is what we expect 42 | } 43 | } 44 | 45 | @Test 46 | public void shouldFixDotConIssue1() throws InvalidEmailException { 47 | assertEquals("roc@rocboronat.com", es.getSuggestedEmail("roc@rocboronat.con")); 48 | 49 | } 50 | 51 | @Test 52 | public void shouldFixDotConIssue2() throws InvalidEmailException { 53 | assertEquals("roc@fewlaps.com", es.getSuggestedEmail("roc@fewlaps.con")); 54 | 55 | } 56 | 57 | @Test 58 | public void shouldFixDotConIssue3() throws InvalidEmailException { 59 | assertEquals("a@b.com", es.getSuggestedEmail("a@b.con")); 60 | 61 | } 62 | 63 | @Test 64 | public void shouldFixDotNeyIssue() throws InvalidEmailException { 65 | assertEquals("a@b.net", es.getSuggestedEmail("a@b.ney")); 66 | 67 | } 68 | 69 | @Test 70 | public void shouldFixGnailIssue() throws InvalidEmailException { 71 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gnail.com")); 72 | 73 | } 74 | 75 | @Test 76 | public void shouldFixGmailDotOmIssue() throws InvalidEmailException { 77 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmail.om")); 78 | 79 | } 80 | 81 | @Test 82 | public void shouldFixGnailAndConIssue() throws InvalidEmailException { 83 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gnail.con")); 84 | 85 | } 86 | 87 | @Test 88 | public void shouldFixGmialIssue() throws InvalidEmailException { 89 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmial.com")); 90 | 91 | } 92 | 93 | @Test 94 | public void shouldFixGmialAndConIssue() throws InvalidEmailException { 95 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmial.con")); 96 | 97 | } 98 | 99 | @Test 100 | public void shouldFixDotCpmIssue() throws InvalidEmailException { 101 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmial.cpm")); 102 | 103 | } 104 | 105 | @Test 106 | public void shouldFixDotCpnIssue() throws InvalidEmailException { 107 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmial.cpn")); 108 | 109 | } 110 | 111 | @Test 112 | public void shouldFixGmailDotCxomIssue() throws InvalidEmailException { 113 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmail.cxom")); 114 | 115 | } 116 | 117 | @Test 118 | public void shouldFixGmailDotCoIssue() throws InvalidEmailException { 119 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmail.co")); 120 | 121 | } 122 | 123 | @Test 124 | public void shouldNotDoNothingWithYahooDotCo() throws InvalidEmailException { 125 | assertEquals("roc@yahoo.co", es.getSuggestedEmail("roc@yahoo.co")); 126 | 127 | } 128 | 129 | @Test 130 | public void shouldFixYahooDotOm() throws InvalidEmailException { 131 | assertEquals("roc@yahoo.com", es.getSuggestedEmail("roc@yahoo.om")); 132 | 133 | } 134 | 135 | @Test 136 | public void shouldFixGmailDotCommIssue() throws InvalidEmailException { 137 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmail.comm")); 138 | } 139 | 140 | @Test 141 | public void shouldFixGmailDotColIssue() throws InvalidEmailException { 142 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmail.col")); 143 | } 144 | 145 | @Test 146 | public void shouldFixGmaiDotComIssue() throws InvalidEmailException { 147 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmai.com")); 148 | } 149 | 150 | @Test 151 | public void shouldFixGimailDotComIssue() throws InvalidEmailException { 152 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gimail.com")); 153 | } 154 | 155 | @Test 156 | public void shouldFixGmaailDotComIssue() throws InvalidEmailException { 157 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmaail.com")); 158 | } 159 | 160 | @Test 161 | public void shouldFixGamilDotComIssue() throws InvalidEmailException { 162 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gamil.com")); 163 | } 164 | 165 | @Test 166 | public void shouldFixGmalDotComIssue() throws InvalidEmailException { 167 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmal.com")); 168 | } 169 | 170 | @Test 171 | public void shouldFixYgmailDotComIssue() throws InvalidEmailException { 172 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@ygmail.com")); 173 | } 174 | 175 | @Test 176 | public void shouldFixHotmaiDotComIssue() throws InvalidEmailException { 177 | assertEquals("roc@hotmail.com", es.getSuggestedEmail("roc@hotmai.com")); 178 | } 179 | 180 | @Test 181 | public void shouldFixHotmalDotComIssue() throws InvalidEmailException { 182 | assertEquals("roc@hotmail.com", es.getSuggestedEmail("roc@hotmal.com")); 183 | } 184 | 185 | @Test 186 | public void shouldFixHotmaliDotComIssue() throws InvalidEmailException { 187 | assertEquals("roc@hotmail.com", es.getSuggestedEmail("roc@hotmali.com")); 188 | } 189 | 190 | @Test 191 | public void shouldFixHitmailDotComIssue() throws InvalidEmailException { 192 | assertEquals("roc@hotmail.com", es.getSuggestedEmail("roc@hitmail.com")); 193 | } 194 | 195 | @Test 196 | public void shouldFixHotmialDotComIssue() throws InvalidEmailException { 197 | assertEquals("roc@hotmail.com", es.getSuggestedEmail("roc@hotmial.com")); 198 | } 199 | 200 | @Test 201 | public void shouldFixHotmaleDotComIssue() throws InvalidEmailException { 202 | assertEquals("roc@hotmail.com", es.getSuggestedEmail("roc@hotmale.com")); 203 | } 204 | 205 | @Test 206 | public void shouldFixHitmailDotItIssue() throws InvalidEmailException { 207 | assertEquals("roc@hotmail.it", es.getSuggestedEmail("roc@hitmail.it")); 208 | } 209 | 210 | @Test 211 | public void shouldFixYahooDotConIssue() throws InvalidEmailException { 212 | assertEquals("roc@yahoo.com", es.getSuggestedEmail("roc@yahoo.con")); 213 | } 214 | 215 | @Test 216 | public void shouldFixYaooDotComIssue() throws InvalidEmailException { 217 | assertEquals("roc@yahoo.com", es.getSuggestedEmail("roc@yaoo.com")); 218 | } 219 | 220 | @Test 221 | public void shouldFixYaooDotConIssue() throws InvalidEmailException { 222 | assertEquals("roc@yahoo.com", es.getSuggestedEmail("roc@yaoo.con")); 223 | } 224 | 225 | @Test 226 | public void shouldFixYabooDotConIssue() throws InvalidEmailException { 227 | assertEquals("roc@yahoo.com", es.getSuggestedEmail("roc@yaboo.con")); 228 | } 229 | 230 | @Test 231 | public void shouldFixYabooDotComlIssue() throws InvalidEmailException { 232 | assertEquals("roc@yahoo.com", es.getSuggestedEmail("roc@yaboo.coml")); 233 | } 234 | 235 | @Test 236 | public void shouldFixYaboDotConIssue() throws InvalidEmailException { 237 | assertEquals("roc@yahoo.com", es.getSuggestedEmail("roc@yaho.com")); 238 | } 239 | 240 | @Test 241 | public void shouldFixOutllokIssue() throws InvalidEmailException { 242 | assertEquals("roc@outlook.com", es.getSuggestedEmail("roc@outllok.com")); 243 | } 244 | 245 | @Test 246 | public void shouldFixComaIssue() throws InvalidEmailException { 247 | assertEquals("roc@fewlaps.com", es.getSuggestedEmail("roc@fewlaps.coma")); 248 | } 249 | 250 | @Test 251 | public void shouldFixCombIssue() throws InvalidEmailException { 252 | assertEquals("roc@fewlaps.com", es.getSuggestedEmail("roc@fewlaps.comb")); 253 | } 254 | 255 | @Test 256 | public void shouldFixComcIssue() throws InvalidEmailException { 257 | assertEquals("roc@fewlaps.com", es.getSuggestedEmail("roc@fewlaps.comc")); 258 | } 259 | 260 | @Test 261 | public void shouldFixComxIssue() throws InvalidEmailException { 262 | assertEquals("roc@fewlaps.com", es.getSuggestedEmail("roc@fewlaps.comx")); 263 | } 264 | 265 | @Test 266 | public void shouldFixComyIssue() throws InvalidEmailException { 267 | assertEquals("roc@fewlaps.com", es.getSuggestedEmail("roc@fewlaps.comy")); 268 | } 269 | 270 | @Test 271 | public void shouldFixComzIssue() throws InvalidEmailException { 272 | assertEquals("roc@fewlaps.com", es.getSuggestedEmail("roc@fewlaps.comz")); 273 | } 274 | 275 | @Test 276 | public void shouldFixAcomIssue() throws InvalidEmailException { 277 | assertEquals("roc@fewlaps.com", es.getSuggestedEmail("roc@fewlaps.acom")); 278 | } 279 | 280 | @Test 281 | public void shouldFixBcomIssue() throws InvalidEmailException { 282 | assertEquals("roc@fewlaps.com", es.getSuggestedEmail("roc@fewlaps.bcom")); 283 | } 284 | 285 | @Test 286 | public void shouldFixCcomIssue() throws InvalidEmailException { 287 | assertEquals("roc@fewlaps.com", es.getSuggestedEmail("roc@fewlaps.ccom")); 288 | } 289 | 290 | @Test 291 | public void shouldFixXcomIssue() throws InvalidEmailException { 292 | assertEquals("roc@fewlaps.com", es.getSuggestedEmail("roc@fewlaps.xcom")); 293 | } 294 | 295 | @Test 296 | public void shouldFixYcomIssue() throws InvalidEmailException { 297 | assertEquals("roc@fewlaps.com", es.getSuggestedEmail("roc@fewlaps.ycom")); 298 | } 299 | 300 | @Test 301 | public void shouldFixZcomIssue() throws InvalidEmailException { 302 | assertEquals("roc@fewlaps.com", es.getSuggestedEmail("roc@fewlaps.zcom")); 303 | } 304 | 305 | @Test 306 | public void shouldFixNteIssue() throws InvalidEmailException { 307 | assertEquals("roc@rocboronat.net", es.getSuggestedEmail("roc@rocboronat.nte")); 308 | } 309 | 310 | @Test 311 | public void shouldFixOutilookDotCom() throws InvalidEmailException { 312 | assertEquals("roc@outlook.com", es.getSuggestedEmail("roc@outilook.com")); 313 | } 314 | 315 | @Test 316 | public void shouldFixGmailDotComu() throws InvalidEmailException { 317 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmail.comu")); 318 | } 319 | 320 | @Test 321 | public void shouldFixHotnailDotCom() throws InvalidEmailException { 322 | assertEquals("roc@hotmail.com", es.getSuggestedEmail("roc@hotnail.com")); 323 | } 324 | 325 | @Test 326 | public void shouldFixHormailDotCom() throws InvalidEmailException { 327 | assertEquals("roc@hotmail.com", es.getSuggestedEmail("roc@hormail.com")); 328 | } 329 | 330 | @Test 331 | public void shouldReplaceFtToFr() throws InvalidEmailException { 332 | assertEquals("roc@hotmail.fr", es.getSuggestedEmail("roc@hotmail.ft")); 333 | } 334 | 335 | @Test 336 | public void shouldReplaceFeToFr() throws InvalidEmailException { 337 | assertEquals("roc@hotmail.fr", es.getSuggestedEmail("roc@hotmail.fe")); 338 | } 339 | 340 | @Test 341 | public void shouldFixGmaikDotCom() throws InvalidEmailException { 342 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmaik.com")); 343 | } 344 | 345 | @Test 346 | public void shouldFixYahou() throws InvalidEmailException { 347 | assertEquals("roc@yahoo.com", es.getSuggestedEmail("roc@yahou.com")); 348 | } 349 | 350 | @Test 351 | public void shouldFixGmailDotVom() throws InvalidEmailException { 352 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmail.vom")); 353 | } 354 | 355 | @Test 356 | public void shouldFixHotmmailDotCom() throws InvalidEmailException { 357 | assertEquals("roc@hotmail.com", es.getSuggestedEmail("roc@hotmmail.com")); 358 | } 359 | 360 | @Test 361 | public void shouldFixUahooDotCom() throws InvalidEmailException { 362 | assertEquals("roc@yahoo.com", es.getSuggestedEmail("roc@uahoo.com")); 363 | } 364 | 365 | @Test 366 | public void shouldFixGmaliDotCom() throws InvalidEmailException { 367 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmali.com")); 368 | } 369 | 370 | @Test 371 | public void shouldFixHotmailDotCm() throws InvalidEmailException { 372 | assertEquals("roc@hotmail.com", es.getSuggestedEmail("roc@hotmail.cm")); 373 | } 374 | 375 | @Test 376 | public void shouldFixYhooDotCom() throws InvalidEmailException { 377 | assertEquals("roc@yahoo.com", es.getSuggestedEmail("roc@yhoo.com")); 378 | } 379 | 380 | @Test 381 | public void shouldFixGemalDotCom() throws InvalidEmailException { 382 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gemail.com")); 383 | } 384 | 385 | @Test 386 | public void shouldFixGmailDotClm() throws InvalidEmailException { 387 | assertEquals("roc@gmail.com", es.getSuggestedEmail("roc@gmail.clm")); 388 | } 389 | } 390 | --------------------------------------------------------------------------------