언어 및 프레임워크/JAVA

JAVA - 이메일 검증 코드

개발참치 2022. 2. 8.
이메일 검증 기능을 JAVA를 활용하여 처리할 수 있습니다.

 

 

기능 구현 코드

 

  • 관련 이메일 검증을 위한 코드 
  • DNS 에 MX 레코드로 등록되어 있는 메일의 특징을 이용한 이메일 검증 로직
  • naver와 같이 대표적인 이메일 주소가 아닐 경우 조금 느린 경향이 보임
  • 임시 이메일 처리 로직 미 구현 상태

 

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;
        int res = 0;
 
        while ((line = in.readLine()) != null) {
            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();
    }
 
    private static ArrayList<String> getMX(String hostName) throws NamingException {
 
        Hashtable<String, String> 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<String> 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;
    }
 
    private static Map<String, Object> returnResult(Boolean valid, String message) {
 
        Map<String, Object> result = new HashMap<>();
 
        if (valid) {
            result.put("resultCode", "이메일 검증 확인");
        } else {
            result.put("resultCode", "이메일 검증 실패");
            result.put("failMessage", message);
        }
 
        return result;
    }
 
    public static Map<String, Object> isAddressValid(String address) {
 
        int pos = address.indexOf('@');
 
        if (pos == -1) {
            return returnResult(false, "이메일 형식이 아닙니다.");
        }
 
        String domain = address.substring(++pos);
        ArrayList<String> mxList;
        try {
            mxList = getMX(domain);
        } catch (NamingException ex) {
            return returnResult(false, "정식 등록된 이메일 도메인이 아닙니다.");
        }
 
        if (mxList.size() == 0) {
            return returnResult(false, "정식 등록된 이메일 도메인이 아닙니다.");
        }
 
        for (String o : mxList) {
            try {
                int res;
 
                Socket skt = new Socket(o, 25);
                BufferedReader rdr = new BufferedReader(new InputStreamReader(skt.getInputStream()));
                BufferedWriter wtr = new BufferedWriter(new OutputStreamWriter(skt.getOutputStream()));
 
                res = hear(rdr);
                if (res != 220) {
                    return returnResult(false, "잘못된 주소입니다.");
                    // throw new Exception("Invalid header");
                }
                say(wtr, "EHLO <도메인>");
 
                res = hear(rdr);
                if (res != 250) {
                    return returnResult(false, "ESMTP가 아닙니다.");
                    // throw new Exception("Not ESMTP");
                }
 
                say(wtr, "MAIL FROM: <<이메일>>");
                res = hear(rdr);
                if (res != 250) {
                    return returnResult(false, "메일 체크가 거절 당했습니다.");
                    //  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) {
                    return returnResult(false, "주소가 유효하지 않습니다.");
                    // throw new Exception("Address is not valid!");
                }
 
                rdr.close();
                wtr.close();
                skt.close();
 
            } catch (Exception ex) {
                ex.printStackTrace();
                return returnResult(false, "정의되지 않은 에러 발생.");
            }
        }
        return returnResult(true, "");
    }
 
    public static void main(String[] args) {
 
        String testData = "<이메일>";
 
        Map<String, Object> result = isAddressValid(testData);
 
        System.out.println(result.get("resultCode"));
        if (result.get("failMessage") != null) {
            System.out.println(result.get("failMessage"));
        }
 
    }
}

 

댓글