Skip to content
Starten Sie mit 100 kostenlosen Verifizierungs-Credits
Qualisend
Alle Artikel
Engineering / 14. Juni 2026

E-Mail-Adresse in Java validieren

6 minutes read

Qualisend team
Ein Java-Code-Fenster, das eine E-Mail über Syntax-, DNS- und SMTP-Schichten bis zu einem Zustellbarkeitsurteil validiert

Eine E-Mail-Adresse in Java zu validieren, sind eigentlich drei Prüfungen, die sich einen Namen teilen. Die meisten Tutorials greifen zu einer Regex, bestätigen, dass die Zeichenkette wie eine Adresse geformt ist, und erklären es damit für erledigt — doch die Form ist das am wenigsten nützliche der drei Dinge, die Sie eigentlich wissen wollen. Echte Validierung ist geschichtet: eine günstige Formatprüfung, ein DNS-Lookup für die Mail-Route der Domain und eine SMTP-Postfachprüfung. Javas Standardbibliothek und Jakarta Mail decken die ersten beiden sauber ab; die dritte ist ein Netzwerkproblem, das man besser auslagert. Dieser Leitfaden baut jede Schicht mit lauffähigem Code auf und zeigt genau, wo jede von ihnen aufhört.

Die kurze Antwort#

Verwenden Sie jakarta.mail.internet.InternetAddress (oder Apache Commons Validator) für die Syntax, den in das JDK integrierten JNDI-DNS-Provider für den MX-Lookup und eine Verifizierungs-API für die SMTP-Postfachprüfung — das Günstigste zuerst, mit Kurzschluss, sobald eine Prüfung entscheidend ist. Öffnen Sie keine SMTP-Verbindungen von Ihrer Anwendung aus, um Postfächer selbst zu prüfen: Der ausgehende Port 25 ist auf den meisten Hosts blockiert, und die Antwort hängt von der Reputation der Sende-IP und vom Greylisting ab, das Sie nicht neu implementieren wollen. Jede Schicht schließt Adressen günstiger aus als die vorherige; nur die letzte kann eine Adresse einschließen.

Schicht 1: Syntax mit Jakarta Mail#

Jakarta Mail — die Bibliothek, die von javax.mail umbenannt wurde, als sie in den Namensraum von Jakarta EE wechselte — liefert einen Adress-Parser, auf den Sie sich statt auf eine selbst gebastelte Regex stützen können. Konstruieren Sie eine InternetAddress und rufen Sie validate() auf: Der Konstruktor parst die Adresse, und validate() erzwingt die RFC-822-Syntax und wirft bei allem Fehlerhaften eine AddressException.

import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;

public static boolean isValidSyntax(String email) {
    if (email == null || email.length() > 320) {
        return false;
    }
    try {
        InternetAddress address = new InternetAddress(email);
        address.validate();
        return true;
    } catch (AddressException e) {
        return false;
    }
}

Eines sollten Sie wissen: validate() ist bei der Domain nachsichtig. Es akzeptiert jane@localhost und jane@example — kein Punkt erforderlich — weil RFC 822 punktlose Domains erlaubt. Das ist hier in Ordnung. Schicht 1 ist ein Formattor, keine Zustellbarkeitsprüfung, und der DNS-Lookup von Schicht 2 ist das, was tatsächlich entscheidet, ob die Domain Mail empfangen kann. Halten Sie diese Prüfung nachsichtig und lassen Sie DNS das Aussortieren übernehmen; der formalen Perfektion mit einer größeren Regex hinterherzujagen, ist ohnehin ein aussichtsloses Spiel.

Wenn Sie eine ältere javax.mail-JAR verwenden, ist der Code identisch bis auf den Paketnamen. Und wenn Sie ohnehin bereits von Apache Commons Validator abhängen, ist dessen EmailValidator eine gute Alternative für Schicht eins — er ist eine Spur strenger (er lehnt punktlose Domains standardmäßig ab):

import org.apache.commons.validator.routines.EmailValidator;

boolean valid = EmailValidator.getInstance().isValid(email);

Bevorzugen Sie Jakarta Mail, wenn Sie es ohnehin zum Versenden von Mail nutzen — eine Abhängigkeit weniger. Beide Bibliotheken beantworten immer nur die Syntaxfrage.

Schicht 2: Kann die Domain überhaupt Mail empfangen?#

Eine Domain ohne MX-Einträge kann für niemanden Mail annehmen, also eliminiert ein einziger MX-Lookup tote Domains, falsch geschriebene Firmennamen und erfundene TLDs. Java erledigt das ganz ohne externe Abhängigkeit: Das JDK bringt einen DNS-Service-Provider für JNDI mit, sodass Sie das MX-Attribut über einen DirContext auflösen.

import java.util.Hashtable;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

public static boolean hasMailRoute(String domain) {
    Hashtable<String, String> env = new Hashtable<>();
    env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
    env.put("com.sun.jndi.dns.timeout.initial", "2000"); // don't hang on a slow resolver
    env.put("com.sun.jndi.dns.timeout.retries", "1");

    DirContext ctx = null;
    try {
        ctx = new InitialDirContext(env);
        Attributes attrs = ctx.getAttributes(domain, new String[] { "MX" });
        Attribute mx = attrs.get("MX");
        return mx != null && mx.size() > 0;
    } catch (NamingException e) {
        // NameNotFoundException → domain doesn't exist; no MX attribute → no mail route
        return false;
    } finally {
        if (ctx != null) {
            try { ctx.close(); } catch (NamingException ignored) { }
        }
    }
}

Trennen Sie die Domain am letzten @ von der Adresse ab, damit Sie zitierte lokale Teile nicht aus dem Tritt bringen:

String domain = email.substring(email.lastIndexOf('@') + 1);

hasMailRoute("gmail.com");               // true
hasMailRoute("company-that-folded.com"); // false

Ein fehlendes oder leeres MX-Attribut bedeutet, dass die Domain keine Mail-Route veröffentlicht; eine NameNotFoundException (eine Unterklasse von NamingException) bedeutet, dass sie sich überhaupt nicht auflöst. Manche Domains nehmen Mail über einen A-Eintrag mit implizitem MX an — wenn Sie diesen Sonderfall berücksichtigen wollen, greifen Sie ersatzweise auf eine Abfrage von "A" zurück, wenn das MX-Set leer zurückkommt. Für die überwältigende Mehrheit echter Adressen ist eine MX-Prüfung der richtige Filter. Da der Lookup auf einem DNS-Resolver blockiert, behalten Sie die obigen Timeouts in einem Anmeldepfad bei und behandeln Sie einen vorübergehenden Fehler als „später erneut prüfen", nicht als harte Ablehnung — ein DNS-Schluckauf sollte einen echten Kunden nicht abweisen.

Schicht 3: Existiert das Postfach tatsächlich?#

Die Schichten 1 und 2 können eine Adresse nur ausschließen. Eine Domain kann perfekte MX-Einträge veröffentlichen und trotzdem kein Postfach unter der Adresse haben, die Sie in Händen halten — noreply-9f2x@gmail.com ist syntaktisch gültig auf einer Domain mit aktiver Mail-Route, und es ist trotzdem ein Postfach, das nie angelegt wurde. Die Bestätigung, dass ein bestimmtes Postfach existiert, erfordert die SMTP-Zustellkonversation: Verbindung zum Mail-Host aufbauen, RCPT TO ausgeben, die Antwort lesen und die Verbindung trennen, bevor irgendetwas gesendet wird. Es steckt mehr dahinter — Catch-all- Domains akzeptieren jede Adresse und hebeln eine naive Prüfung aus — wie E-Mail-Verifizierung funktioniert durchläuft die gesamte Pipeline.

Sie können SMTP in Java mit einem rohen Socket skripten, aber Sie sollten es nicht aus Ihrer Anwendung heraus ausführen. Die meisten Cloud-Anbieter blockieren den ausgehenden Port 25, die Antwort hängt von der Reputation der IP ab, von der aus Sie sich verbinden, und empfangende Server greylisten unbekannte Absender und drosseln deren Rate — sodass eine Prüfung, die in einem lokalen Test besteht, in der Produktion still fehlschlägt oder Sie auf eine Blockliste bringt. Das ist die Schicht, die es sich zu delegieren lohnt.

Qualisends POST /verify durchläuft die gesamte Pipeline — Syntax, DNS und die SMTP-Postfachprüfung — von einer reputationsgeführten Infrastruktur, die genau dafür gebaut ist, und liefert ein Urteil zurück. Java 11+ bringt java.net.http.HttpClient mit, sodass Sie keine HTTP-Abhängigkeit brauchen; kombinieren Sie es mit Jackson (oder Gson), um das JSON zu lesen. Bewahren Sie Ihren Schlüssel in einer Umgebungsvariablen auf und codieren Sie ihn niemals fest:

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Map;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class QualisendClient {
    // Placeholder endpoint — check /developers for the current base URL and shape.
    private static final String ENDPOINT = "https://api.qualisend.com/v1/verify";

    private final HttpClient http = HttpClient.newHttpClient();
    private final ObjectMapper mapper = new ObjectMapper();

    public JsonNode verify(String email) throws IOException, InterruptedException {
        String apiKey = System.getenv("QUALISEND_API_KEY"); // holds YOUR_API_KEY
        String payload = mapper.writeValueAsString(Map.of("email", email));

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(ENDPOINT))
            .header("Authorization", "Bearer " + apiKey)
            .header("Content-Type", "application/json")
            .timeout(Duration.ofSeconds(10))
            .POST(HttpRequest.BodyPublishers.ofString(payload))
            .build();

        HttpResponse<String> response =
            http.send(request, HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() >= 400) {
            throw new IOException("Qualisend responded " + response.statusCode());
        }
        // The verdict lives inside a `result` envelope.
        return mapper.readTree(response.body()).get("result");
    }
}

Lesen Sie die Felder, die Sie interessieren, aus dem result-Knoten heraus:

JsonNode result = client.verify("jane@example.com");

String  status     = result.get("status").asText();  // deliverable | risky | undeliverable | unknown
int     score      = result.path("score").asInt();    // 0–100 confidence
String  reason     = result.hasNonNull("reason")
                         ? result.get("reason").asText()  // machine-readable reason, may be null
                         : null;
boolean disposable = result.path("sub_flags").path("disposable").asBoolean();

Die genaue Struktur der Antwort — jeder sub_flags-Schlüssel und jeder reason-Code — steht in der API-Referenz. Für die Live-Validierung bei der Anmeldung reicht der status meist aus, um zu handeln: undeliverable ablehnen, risky und unknown nach Richtlinie behandeln und disposable-Adressen am Eingabefeld kennzeichnen.

Die Schichten zusammensetzen, um eine E-Mail-Adresse in Java zu validieren#

Das Günstigste zuerst, aufhören, sobald Sie eine Antwort haben. Ein kleines Record hält das Urteil (Records gibt es ab Java 16; auf 11–15 verwenden Sie eine einfache Klasse):

public record Verdict(String status, String reason) {}

public Verdict validate(String email) throws IOException, InterruptedException {
    if (!isValidSyntax(email)) {
        return new Verdict("undeliverable", "invalid_email");
    }
    String domain = email.substring(email.lastIndexOf('@') + 1);
    if (!hasMailRoute(domain)) {
        return new Verdict("undeliverable", "invalid_domain");
    }
    JsonNode result = client.verify(email); // client is a QualisendClient
    return new Verdict(
        result.get("status").asText(),
        result.hasNonNull("reason") ? result.get("reason").asText() : null);
}

Die beiden lokalen Schichten kosten nichts und fangen den meisten Müll sofort ab; die API läuft nur auf Adressen, die den Netzwerk-Roundtrip wert sind. Diese Reihenfolge ist der ganze Trick — dieselbe Form finden Sie auch in den Versionen dieses Leitfadens für Node.js, Python und PHP, denn es ist die Schichtung, nicht die Sprache, die Validierung funktionieren lässt.

Häufig gestellte Fragen#

Reicht InternetAddress.validate() aus, um eine E-Mail in Java zu validieren?#

Für die Syntax ist es das richtige Werkzeug der ersten Schicht — jakarta.mail.internet.InternetAddress mit validate() ist besser getestet als eine selbst geschriebene Regex und erspart Ihnen die Neuimplementierung von RFC 822. Aber es prüft nur die Form: Es löst niemals DNS auf und kontaktiert keinen Mailserver, und es ist nachsichtig genug, um punktlose Domains wie jane@localhost zu akzeptieren. Kombinieren Sie es mit einem MX-Lookup und einer SMTP-Postfachprüfung, bevor Sie der Adresse vertrauen.

Wie prüfe ich MX-Einträge in Java ohne externe Bibliothek?#

Verwenden Sie den in das JDK integrierten JNDI-DNS-Provider. Erstellen Sie einen InitialDirContext, bei dem java.naming.factory.initial auf com.sun.jndi.dns.DnsContextFactory gesetzt ist, rufen Sie dann getAttributes(domain, new String[] {"MX"}) auf und prüfen Sie das zurückgegebene MX-Attribut. Es benötigt keine Drittanbieter-Abhängigkeit und sagt Ihnen sauber, ob eine Domain eine Mail-Route veröffentlicht. Fangen Sie NamingException ab und behandeln Sie einen fehlenden MX-Eintrag als nicht zustellbar.

Kann ich in Java ein Postfach ohne API verifizieren?#

Teilweise. Jakarta Mail und JNDI bestätigen, dass die Adresse wohlgeformt ist und die Domain Mail annimmt — beides kostenlos und mit geringem Abhängigkeitsaufwand. Die Bestätigung des Postfachs selbst erfordert eine SMTP-Konversation, die Sie mit einem rohen Socket versuchen können, aber nicht von Ihrem Anwendungsserver aus ausführen sollten: Port 25 ist weithin blockiert und das Ergebnis hängt von der Reputation Ihrer Sende-IP ab. Genau diese letzte Schicht übernimmt ein Verifizierungsdienst.

Sollte ich E-Mails bei der Anmeldung oder beim Bereinigen einer Liste validieren?#

Beides, in unterschiedlicher Tiefe. Führen Sie die Syntax- und MX-Schichten bei der Anmeldung synchron aus — sie sind schnell genug, um die Anfrage zu blockieren und sofortiges Feedback zu geben — und handeln Sie auch dort nach dem status der API. Reservieren Sie tiefergehende Batch-Arbeit für die Listenbereinigung; der Leitfaden zur serverlosen Anmeldung zeigt das Echtzeit-Muster und der Leitfaden zur Listenbereinigung behandelt die Batch-Seite.


Bereit, die SMTP-Schicht hinzuzufügen? Lassen Sie eine beliebige Adresse durch den kostenlosen E-Mail-Checker laufen, um zuzusehen, wie eine syntaktisch perfekte Zeichenkette mit einem echten Urteil zurückkommt, oder lesen Sie die API-Referenz für den /verify-Endpunkt, das vollständige result-Envelope und Copy-Paste-Beispiele in jeder oben genannten Sprache.

Your reputation, protected.

Clean your first list in minutes. 100 free credits, no card required.

Get started