import gradio as gr import re import dns.resolver from typing import Tuple from dns.exception import DNSException def check_syntax(mail_address: str) -> Tuple[bool, str]: """이메일 주소 구문 검사""" # RFC 5322 표준을 기반으로 한 더 엄격한 이메일 정규식 패턴 pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' # 기본 패턴 검사 if not re.match(pattern, mail_address): return False, "❌ 이메일 주소 형식이 올바르지 않습니다." # 추가 유효성 검사 local_part, domain = mail_address.split('@') # 로컬 파트 검사 if len(local_part) > 64: return False, "❌ 이메일 주소의 @ 앞부분이 너무 깁니다." if local_part.startswith('.') or local_part.endswith('.'): return False, "❌ 이메일 주소의 @ 앞부분이 점(.)으로 시작하거나 끝날 수 없습니다." if '..' in local_part: return False, "❌ 이메일 주소의 @ 앞부분에 연속된 점(..)이 있을 수 없습니다." # 도메인 파트 검사 if len(domain) > 255: return False, "❌ 도메인이 너무 깁니다." if domain.startswith('-') or domain.endswith('-'): return False, "❌ 도메인은 하이픈(-)으로 시작하거나 끝날 수 없습니다." if not all(part.isalnum() or '-' in part for part in domain.split('.')): return False, "❌ 도메인에 허용되지 않는 문자가 포함되어 있습니다." return True, "✅ 이메일 주소 형식이 올바릅니다." def is_disposable_domain(domain: str) -> bool: """임시 이메일 도메인 체크""" disposable_domains = { 'tempmail.com', 'throwawaymail.com', 'mailinator.com', 'temp-mail.org', 'fake-email.com', 'temporary-mail.net' } return domain.lower() in disposable_domains def check_dns(domain: str) -> Tuple[bool, str]: """DNS MX 레코드 검사""" try: # 임시 이메일 도메인 체크 if is_disposable_domain(domain): return False, "❌ 임시 이메일 도메인은 사용할 수 없습니다." # DNS MX 레코드 확인 records = dns.resolver.resolve(domain, 'MX') if not records: return False, "❌ 도메인의 메일 서버를 찾을 수 없습니다." # 실제 MX 레코드 내용 확인 mx_records = [str(r.exchange).rstrip('.') for r in records] if not mx_records: return False, "❌ 유효한 메일 서버 정보가 없습니다." # A 레코드도 확인 try: dns.resolver.resolve(domain, 'A') except DNSException: try: dns.resolver.resolve(domain, 'AAAA') except DNSException: return False, "❌ 도메인이 실제로 존재하지 않습니다." return True, "✅ 도메인의 메일 서버가 존재합니다." except dns.resolver.NXDOMAIN: return False, "❌ 존재하지 않는 도메인입니다." except dns.resolver.NoAnswer: return False, "❌ 도메인에 메일 서버 정보가 없습니다." except dns.resolver.NoNameservers: return False, "❌ DNS 서버에 연결할 수 없습니다." except Exception as e: return False, f"❌ DNS 확인 중 오류 발생: {str(e)}" def validate_email(mail_address: str) -> str: """이메일 주소 종합 검증""" results = [] # 1. 기본 입력값 검사 if not mail_address or not isinstance(mail_address, str): return "❌ 유효하지 않은 입력입니다." mail_address = mail_address.strip() if not mail_address: return "❌ 이메일 주소를 입력해주세요." # 2. 구문 검사 syntax_valid, syntax_msg = check_syntax(mail_address) results.append(syntax_msg) if not syntax_valid: return "\n".join(results) # 3. 도메인 추출 및 DNS 검사 try: domain = mail_address.split('@')[1] dns_valid, dns_msg = check_dns(domain) results.append(dns_msg) if not dns_valid: return "\n".join(results) # 모든 검증 통과 results.append("✅ 이메일 주소가 유효합니다.") except Exception as e: results.append(f"❌ 검증 중 오류 발생: {str(e)}") return "\n".join(results) # Gradio 인터페이스 구성 iface = gr.Interface( fn=validate_email, inputs=gr.Textbox( label="이메일 주소를 입력하세요", placeholder="example@domain.com" ), outputs=gr.Textbox(label="검증 결과"), title="이메일 주소 검증 도구", description=""" 이 도구는 다음 사항들을 검증합니다: 1. 이메일 주소 형식 검사 (RFC 5322 표준 준수) 2. 도메인의 메일 서버(MX 레코드) 존재 여부 확인 3. 도메인의 실제 존재 여부 확인 4. 임시 이메일 도메인 필터링 """, examples=[ ["user@gmail.com"], ["test@yahoo.com"], ["invalid@nonexistent.domain"], ["malformed@@email.com"], ["user@tempmail.com"], ["test@domain"], ["user.name@subdomain.example.com"] ], theme=gr.themes.Soft() ) # 애플리케이션 실행 if __name__ == "__main__": iface.launch()