Spaces:
Running
Running
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="[email protected]" | |
), | |
outputs=gr.Textbox(label="κ²μ¦ κ²°κ³Ό"), | |
title="μ΄λ©μΌ μ£Όμ κ²μ¦ λꡬ", | |
description=""" | |
μ΄ λꡬλ λ€μ μ¬νλ€μ κ²μ¦ν©λλ€: | |
1. μ΄λ©μΌ μ£Όμ νμ κ²μ¬ (RFC 5322 νμ€ μ€μ) | |
2. λλ©μΈμ λ©μΌ μλ²(MX λ μ½λ) μ‘΄μ¬ μ¬λΆ νμΈ | |
3. λλ©μΈμ μ€μ μ‘΄μ¬ μ¬λΆ νμΈ | |
4. μμ μ΄λ©μΌ λλ©μΈ νν°λ§ | |
""", | |
examples=[ | |
["[email protected]"], | |
["[email protected]"], | |
["[email protected]"], | |
["malformed@@email.com"], | |
["[email protected]"], | |
["test@domain"], | |
["[email protected]"] | |
], | |
theme=gr.themes.Soft() | |
) | |
# μ ν리μΌμ΄μ μ€ν | |
if __name__ == "__main__": | |
iface.launch() |