Skip to content

Instantly share code, notes, and snippets.

@robotdan
Created May 21, 2021 19:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robotdan/32b281c60c605033594cb6734e782655 to your computer and use it in GitHub Desktop.
Save robotdan/32b281c60c605033594cb6734e782655 to your computer and use it in GitHub Desktop.
FusionAuth Email Validator
/*
* Copyright (c) 2021, Inversoft Inc., All Rights Reserved
*/
package com.inversoft.validator;
/**
* @author Daniel DeGroff
*/
public class EmailValidator {
/**
* Validation an email address.
*
* @param email the email address
* @return true if the email is valid
*/
public static boolean isValid(String email) {
if (email == null) {
return false;
}
boolean valid = false;
// An email address has two parts, a local and a domain.
String[] parts = email.split("@");
if (parts.length == 2) {
// Validate local
char[] local = parts[0].toCharArray();
valid = validateLocal(local);
// Validate domain
if (valid) {
char[] domain = parts[1].toCharArray();
valid = validateDomain(domain);
}
}
return valid;
}
private static boolean validateDomain(char[] ca) {
// Cannot begin with a dash.
if (ca[0] == '-') {
return false;
}
int alpha = -1;
int dot = -1;
for (int i = 0; i < ca.length; i++) {
if (ca[i] == '.') {
// A dot cannot be sequential
if (i == dot + 1 || i == dot - 1) {
return false;
}
dot = i;
} else {
// Allowed characters are [0-9A-Za-Z-]
boolean isHyphen = ca[i] == 45;
boolean isDigit = ca[i] >= 48 && ca[i] <= 57;
boolean isAlpha = (ca[i] >= 65 && ca[i] <= 90) || (ca[i] >= 97 && ca[i] <= 122);
if (!isHyphen && !isDigit && !isAlpha) {
// If this is the first or last position and is a square bracket, don't fail yet.
if (i == 0 && ca[i] == '[' || ((i == ca.length - 1) && ca[i] == ']')) {
continue;
}
return false;
}
if (isAlpha) {
alpha = i;
}
}
}
if (dot == -1) {
return false;
}
// This is allowed if we think it is an IP address. This is a naive check, but it is likely close enough.
// Email deliver-ability is still the only true test to see if it is valid.
if (alpha == -1) {
return ca[0] == '[' && ca[ca.length - 1] == ']';
}
return true;
}
private static boolean validateLocal(char[] ca) {
// Cannot begin or end with a '.'
if (ca[0] == '.' || ca[ca.length - 1] == '.') {
return false;
}
// Max local length of 64
if (ca.length > 64) {
return false;
}
int dot = -1;
for (int i = 0; i < ca.length; i++) {
if (ca[i] == '.') {
// A dot cannot be sequential
if (i == dot + 1 || i == dot - 1) {
return false;
}
dot = i;
}
}
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment