正規表現だけでメールアドレスチェックをして良しとするのは
あまり良くない。
メールアドレスが指すドメインだけでも、DNSサーバに問い合わせたい。
Java の場合、
以下を参考に、DNS lookUp で検証する。
https://docs.oracle.com/javase/jp/6/technotes/guides/jndi/jndi-dns.html
Java/JNDIのDNSサービスプロバイダによる名前解決 - Glamenv-Septzen.net
import java.util.Hashtable; import java.util.regex.Pattern; import javax.naming.NamingException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext;
/** * メールバリデーションチェック * @param mail メールアドレス文字列 * @return true=存在しないメールアドレス */ public static boolean validateMailAdress(String mail) { Pattern ptn = Pattern.compile("^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[A-Za-z]{2,3}){1}$"); if (ptn.matcher(mail).matches()){ Hashtable<String, String> env = new Hashtable<>(); env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory"); try{ DirContext ictx = new InitialDirContext(env); Attributes attrs = ictx.getAttributes(mail.split("@")[1], new String[]{"MX"}); Attribute attr = attrs.get("MX"); if (attr==null){ return true; } return attr.size() < 1; }catch(NamingException e){ return true; } } return true; }
正規表現チェックと組み合わせて問い合わせを行っている。
interface にした方がいいかな。。。
import java.util.Hashtable; import java.util.Objects; import java.util.regex.Pattern; import java.util.function.Function; 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 interface MailValidation{ Pattern ptn = Pattern.compile("^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[A-Za-z]{2,3}){1}$"); public static Function<String, Boolean> of(){ return s -> validate(s); } static boolean validate(String mail) { Objects.requireNonNull(mail); if (ptn.matcher(mail).matches()){ Hashtable<String, String> env = new Hashtable<>(); env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory"); try{ DirContext ictx = new InitialDirContext(env); Attributes attrs = ictx.getAttributes(mail.split("@")[1], new String[]{"MX"}); Attribute attr = attrs.get("MX"); if (attr==null){ return true; } return attr.size() < 1; }catch(NamingException e){ return true; } } return true; } }
Python の場合、
dnspython を使う方法(他のパッケージを使う方法もあると思うが)
以下を参考に、、、
www.tutorialspoint.com
pip install dnspython
バージョンにより差がある。
dnspython version 2.6.1 では、lookup の問い合わせ query は、
DeprecationWarning: please use dns.resolver.resolve() instead
の警告が出るので、dns.resolver.resolve() を使用する。
import dns.resolver from dns.resolver import NXDOMAIN try: res = dns.resolver.resolve("gmail.com","MX") for ipval in res: print('IP', ipval.to_text()) except NXDOMAIN as e: print(e)
結果
alt4.gmail-smtp-in.l.google.com. gmail-smtp-in.l.google.com. alt3.gmail-smtp-in.l.google.com. alt2.gmail-smtp-in.l.google.com. alt1.gmail-smtp-in.l.google.com.
email_validator と組み合わせて、
from email_validator import validate_email, EmailNotValidError, EmailUndeliverableError import dns.resolver from dns.resolver import NXDOMAIN import sys def validateMail(mail:str)->bool: try: validate_email(mail) dns.resolver.resolve(mail.split('@')[1], "MX") return False except NXDOMAIN as e: print(e, file=sys.stderr) return True except EmailUndeliverableError as e: print(e, file=sys.stderr) return True except EmailNotValidError as e: print(e, file=sys.stderr) return True