Validate an email address in Java
Syntax and MX you can do with the JDK and one small library, no external service required; disposable and role detection is where an API earns its keep.
Contents
You typed "validate email in Java" into a search box because a form is accepting asdf@asdf or bouncing mail to addresses that looked fine. The good news: two of the three checks you actually want need no third-party service at all. The JDK and one small library cover them. The third check is the one worth paying for, and this post draws the line clearly between them.
Here is the honest split. Syntax is a library call. Whether the domain can receive mail is a DNS lookup you can run yourself. Whether the address is disposable or a shared role inbox is the part that needs a maintained list someone keeps current — that is where an API belongs.
Syntax: one library call, no network
Do not write your own email regex. RFC 5321/5322 address grammar is a genuinely nasty thing to parse, and every hand-rolled pattern gets user+tag@sub.example.co.uk wrong eventually. Apache Commons Validator has already done it:
import org.apache.commons.validator.routines.EmailValidator;
public class Syntax {
public static boolean isValidSyntax(String email) {
return EmailValidator.getInstance().isValid(email);
}
}
Add commons-validator:commons-validator to your build and you are done. If you already pull in Jakarta Mail, InternetAddress gives you the same answer — note that the constructor alone is lenient, so you must call validate():
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.AddressException;
public static boolean isValidSyntax(String email) {
try {
new InternetAddress(email).validate();
return true;
} catch (AddressException e) {
return false;
}
}
Either way: no external service, no API key, no network call. Syntax validation runs entirely in your process. For a lot of forms, this alone is enough — say so, and don't over-engineer it.
Does the domain accept mail? A JNDI MX lookup
Syntax being valid tells you the string is well-formed, not that @example.com is a real mail destination. To learn that, ask DNS whether the domain publishes MX records. The JDK ships a DNS provider through JNDI, so this too needs nothing external:
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import java.util.Hashtable;
public static boolean hasMxRecord(String domain) {
Hashtable<String, String> env = new Hashtable<>();
env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
try {
DirContext ctx = new InitialDirContext(env);
Attributes attrs = ctx.getAttributes(domain, new String[]{"MX"});
Attribute mx = attrs.get("MX");
ctx.close();
return mx != null && mx.size() > 0;
} catch (NamingException e) {
return false;
}
}
com.sun.jndi.dns.DnsContextFactory is the standard JNDI DNS provider that has been in the JDK for years. A non-empty MX attribute means the domain is set up to receive mail. Between Commons Validator and this, you have covered syntax and deliverable-domain checks without leaving the standard library plus one dependency. Prefer this to any paid call when it's all you need.
What syntax and MX still can't tell you
MX records prove the domain accepts mail. They say nothing about two things that break real signup lists:
- Disposable domains.
mailinator.comand thousands of throwaway providers publish perfectly good MX records. DNS will never flag them. - Role accounts.
admin@,support@,sales@are shared inboxes, not people — usually not who you want in a lead list.
Detecting these is not a DNS or regex problem. It requires a list of known disposable domains and role prefixes that someone maintains as new ones appear. That maintenance is the actual product, and it is what a validation API is for. This is where Boundstone fits: it runs the same syntax and MX checks you just wrote, then adds the disposable and role lists on top, behind one contract.
Calling Boundstone from Java
Use the JDK's built-in HttpClient (Java 11+) — no HTTP dependency needed:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.boundstone.io/v1/verify/email"))
.header("Authorization", "Bearer bs_live_YOUR_KEY")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"email\":\"you@example.com\"}"))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
The response returns valid_syntax, domain, mx_found, disposable, role_account, and free_provider — plus the part that makes a "valid" worth trusting, the checks object:
"checks": {
"performed": ["syntax", "mx", "disposable_list", "role_list"],
"not_performed": ["smtp_mailbox", "catch_all"]
}
Read not_performed before you trust performed. Boundstone does not do SMTP mailbox verification or catch-all detection — it will not open a connection to the mail server to probe whether a specific inbox exists, and it says so on every response rather than implying a certainty it can't deliver. Anyone claiming a live "mailbox exists" check is guessing from a handshake that many servers deliberately lie about. One more note: free_provider is a returned flag but is deliberately not in performed — it's information about the domain, not a pass/fail check.
Want to try it before writing any code? The keyless email validator tool runs the same checks in your browser.
The short version
- Syntax → Commons Validator or Jakarta Mail. No external service. Often all you need.
- Domain accepts mail → a JNDI MX lookup with the JDK's DNS provider. No external service.
- Disposable / role → needs a maintained list, so use the API. Read
checks.not_performedso you know exactly what a "valid" does and does not promise.
Same three-layer split in your other stack: validate email in Python and validate email in Node.js.