← Blog

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.com and 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_performed so 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.

Frequently asked questions

How do I validate an email address in Java?

In plain Java you typically start with a syntax check using a regular expression or the jakarta.mail InternetAddress class, which confirms the address is well-formed but nothing more. To go further you can do a DNS lookup for the domain's MX records (via javax.naming) or call a validation API from your Java code over HTTP. Boundstone's email endpoint does exactly this layered check for you and returns valid_syntax, mx_found, disposable, role_account, and free_provider, so you get more than a format check with one call.

Does a valid email address in Java mean the mailbox actually exists?

No. A "valid" result from a syntax check, or even from a service like Boundstone, means the address is correctly formatted and, when checked, that the domain publishes MX records and accepts mail; it does not prove the specific mailbox exists. Boundstone is deliberate about this: it performs syntax, MX, disposable-list, and role-account checks, and it explicitly does not perform SMTP mailbox verification or catch-all detection, reporting those as not_performed rather than guessing. That honesty is the point, because a tool that claims to confirm a mailbox exists by SMTP probing is often unreliable and can get your sending IP blocked.

How can I check if an email domain can receive mail from Java without running my own SMTP server?

You can query the domain's MX records directly in Java using the JNDI DNS provider (javax.naming.directory), or call an API that does it for you. Boundstone's email verify resolves MX over DNS and returns mx_found, along with flags for disposable domains, role accounts like info@ or support@, and free providers, all as a single JSON response you can consume from Java. It confirms the domain is set up to accept mail, but note it does not attempt SMTP mailbox verification or catch-all detection, so treat mx_found as domain-level capability, not a guarantee that one specific address is live.

Thomas Tsui

Founder of Boundstone — building phone, email and IP validation you can actually verify.

One honest API for email, phone and IP — every response lists what it checked and what it didn't claim to. Free tier: 250 credits/month, no card, credits never expire.

More from Boundstone — API documentation · Benchmark methodology · The benchmark series · Buyer's checklist