Spaces:
Running
Running
File size: 5,457 Bytes
2ec2072 800e08b 2ab666f 2ec2072 800e08b 2ec2072 2ab666f 800e08b 2ab666f 2ec2072 2ab666f 2ec2072 800e08b 2ec2072 800e08b 2ec2072 2ab666f 800e08b 2ec2072 2ab666f 800e08b 2ab666f 800e08b 2ec2072 800e08b 2ec2072 800e08b 2ec2072 800e08b 2ab666f 800e08b 2ab666f 800e08b 2ec2072 2ab666f 800e08b 2ab666f 800e08b 2ab666f 2ec2072 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
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() |