Validate email address exists or not by Java Code

The best you can do to verify if an email address is real is to verify if there is a mail server registered to the domain name.

There are other methods by which to validate an email address to a higher degree than just the mail server.

Method One:
Use the VRFY command (see RFCs 821/2821). Because this was abused by spammers, it has typically been disabled on most mail servers. Some recent servers don’t even support this command as they are so frequently shut off.

When it works, connect to the server, issue the HELO command and then send ‘VRFY ‘. If it is enabled, and the address is valid, you should get a 250 if the address is valid and a 550 if it isn’t. Note that some servers (Gmail) return 252 as a means of pleading the fifth. Others will return a failure even if the address exists but the command has been disabled (although this is typically a 450 error).

Method Two (better method):
Connect to the servers determined by your code snippet. BUT (and the code below doesn’t do this) they must be tried from lowest preference to highest to be absolutely correct.

Once you have connected, you create the SMTP envelope, but you don’t put anything in it. This is the point at which most servers will give up the dirt on whether or not an address is valid. If an envelope cannot be built, we know that the address is invalid.

The reason for connecting in order of preference:

Imagine ABC company has an Internet connection and runs their own mail server for abc.com. To prevent bounces and other mail errors if their connection or server should be down, their provider isp.com agrees to set up a ‘store and forward scheme for their mail. If abc.com is not available, then isp.com gets the message and when abc.com is again available, the message gets forwarded. The MX records would look something like this:

MX 1 abc.com
MX 2 isp.com

Now, imagine that you connect to isp.com and try to send a message. The mail server at isp.com doesn’t have the actual user list to know which addresses are valid, it just accepts everything and relies on abc.com to sort out the bounces.
If these are not checked in the proper order, there will be no errors for invalid addresses.

Yahoo appears to use a store and forward mechanism to its own internal servers, thus conclusively verifying a yahoo address is not possible. I suspect that Hotmail is the same.

It is not possible to verify an address on a domain that uses a catch-all account as the catch account will receive the mail (it does, however, mean that someone will at least SEE the message).

package com.maixuanviet.email;

import java.io.*;
import java.net.*;
import java.util.*;
import javax.naming.*;
import javax.naming.directory.*;

public class SMTPMXLookup {
    private static int hear(BufferedReader in) throws IOException {
        String line = null;
        int res = 0;

        while ((line = in.readLine()) != null) {
            System.out.println("Head Line = " + line);
            String pfx = line.substring(0, 3);
            try {
                res = Integer.parseInt(pfx);
            } catch (Exception ex) {
                res = -1;
            }
            if (line.charAt(3) != '-') break;
        }

        return res;
    }

    private static void say(BufferedWriter wr, String text)
            throws IOException {
        wr.write(text + "\r\n");
        wr.flush();

        return;
    }

    private static ArrayList getMX(String hostName)
            throws NamingException {
        // Perform a DNS lookup for MX records in the domain
        Hashtable env = new Hashtable();
        env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
        DirContext ictx = new InitialDirContext(env);
        Attributes attrs = ictx.getAttributes(hostName, new String[]{"MX"});
        Attribute attr = attrs.get("MX");

        if ((attr == null) || (attr.size() == 0)) {
            attrs = ictx.getAttributes(hostName, new String[]{"A"});
            attr = attrs.get("A");
            if (attr == null)
                throw new NamingException("No match for name '" + hostName + "'");
        }

        ArrayList res = new ArrayList();
        NamingEnumeration en = attr.getAll();

        while (en.hasMore()) {
            String mailHost;
            String x = (String) en.next();
            String f[] = x.split(" ");

            if (f.length == 1) {
                mailHost = f[0];
            } else if (f[1].endsWith(".")) {
                mailHost = f[1].substring(0, (f[1].length() - 1));
            } else {
                mailHost = f[1];
            }

            res.add(mailHost);
        }
        return res;
    }

    public static boolean isAddressValid(String address) {

        int pos = address.indexOf('@');
        if (pos == -1) return false;

        String domain = address.substring(++pos);
        ArrayList mxList = null;
        try {
            mxList = getMX(domain);
        } catch (NamingException ex) {
            return false;
        }

        if (mxList.size() == 0) return false;

        // Now, do the SMTP validation, try each mail exchanger until we get
        // a positive acceptance. It *MAY* be possible for one MX to allow
        // a message [store and forwarder for example] and another [like
        // the actual mail server] to reject it. This is why we REALLY ought
        // to take the preference into account.
        for (int mx = 0; mx < mxList.size(); mx++) {
            boolean valid = false;
            try {
                int res = 0;

                Socket skt = new Socket((String) mxList.get(mx), 25);
                BufferedReader rdr = new BufferedReader(new InputStreamReader(skt.getInputStream()));
                BufferedWriter wtr = new BufferedWriter(new OutputStreamWriter(skt.getOutputStream()));

                res = hear(rdr);
                if (res != 220) throw new Exception("Invalid header");

                say(wtr, "EHLO maixuanviet.com");
                res = hear(rdr);
                if (res != 250) throw new Exception("Not ESMTP");


                say(wtr, "MAIL FROM: <info@maixuanviet.com>");
                res = hear(rdr);
                if (res != 250) throw new Exception("Sender rejected");

                say(wtr, "RCPT TO: <" + address + ">");
                res = hear(rdr);

                say(wtr, "RSET");
                hear(rdr);

                say(wtr, "QUIT");
                hear(rdr);
                if (res != 250) throw new Exception( "Address is not valid!" );

                valid = true;
                rdr.close();
                wtr.close();
                skt.close();
            } catch (Exception ex) {
                // Do nothing but try next host
                ex.printStackTrace();
            } finally {
                if (valid) return true;
            }
        }
        return false;
    }

    public static void main(String args[]) {
        System.out.println("maixuanviet.com@gmail.com " + " is valid? " +
                isAddressValid("maixuanviet.com@gmail.com"));
    }
}

Done! Happy coding!

Related posts:

Spring Boot - Internationalization
The Thread.join() Method in Java
Java Program to Perform Right Rotation on a Binary Search Tree
Java Program to Remove the Edges in a Given Cyclic Graph such that its Linear Extension can be Found
Java Program to Implement Ternary Search Tree
A Guide to TreeSet in Java
Exploring the Spring 5 WebFlux URL Matching
Number Formatting in Java
Simplify the DAO with Spring and Java Generics
Java Program for Douglas-Peucker Algorithm Implementation
Jackson – Unmarshall to Collection/Array
Introduction to Spring Data REST
Spring 5 and Servlet 4 – The PushBuilder
Mệnh đề Switch-case trong java
Converting between an Array and a List in Java
Quick Guide to Spring MVC with Velocity
Giới thiệu Java Service Provider Interface (SPI) – Tạo các ứng dụng Java dễ mở rộng
Java Program to Implement Hash Tables with Double Hashing
An Introduction to ThreadLocal in Java
Hướng dẫn Java Design Pattern – Prototype
Sorting in Java
Spring Data MongoDB Transactions
Java Program to Implement Insertion Sort
SOAP Web service: Upload và Download file sử dụng MTOM trong JAX-WS
Java Program to Implement Max Heap
Retrieve User Information in Spring Security
Spring Boot - Zuul Proxy Server and Routing
Java Program to Implement wheel Sieve to Generate Prime Numbers Between Given Range
Mệnh đề if-else trong java
Base64 encoding và decoding trong Java 8
Returning Custom Status Codes from Spring Controllers
Các chương trình minh họa sử dụng Cấu trúc điều khiển trong Java