📨 用 Python 与 Tkinter 构建电子邮件验证工具(一步一步)

发布: (2026年2月2日 GMT+8 10:56)
6 min read
原文: Dev.to

Source: Dev.to

请提供您希望翻译的正文内容,我将为您将其翻译成简体中文。

📦 步骤 1:导入所需库

import sys
import os
import re
import threading
import tkinter as tk
from tkinter import ttk, messagebox, filedialog

import dns.resolver          # MX record lookup
import sv_ttk                # Modern Tkinter theme

安装缺失的包

pip install dnspython sv-ttk

🛠 第2步:辅助函数

解析文件路径(对后续打包有用)

def resource_path(file_name):
    """Return absolute path to a resource, works for PyInstaller bundles."""
    base_path = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, file_name)

状态栏更新

def set_status(msg):
    """Update the status bar text."""
    status_var.set(msg)
    root.update_idletasks()

这些辅助函数保持 UI 响应,并在后台任务运行时向用户提供信息。

🖥 第3步:创建主应用窗口

root = tk.Tk()
root.title("Email Validation Tool")
root.geometry("720x680")
sv_ttk.set_theme("light")          # Light theme by default

🌍 第4步:全局状态变量

dark_mode_var          = tk.BooleanVar(value=False)
email_var              = tk.StringVar()
validation_result_var  = tk.StringVar(value="Result: —")
email_history          = []          # List of validated emails

这些变量将:

  • 跟踪暗模式状态
  • 存储用户输入的电子邮件地址
  • 显示验证结果
  • 保留所有已验证电子邮件的历史记录

🌗 第5步:暗模式切换

def toggle_theme():
    """Switch between light and dark themes."""
    bg = "#2E2E2E" if dark_mode_var.get() else "#FFFFFF"
    fg = "white"   if dark_mode_var.get() else "black"

    root.configure(bg=bg)

    for w in ["TFrame", "TLabel", "TLabelframe",
              "TLabelframe.Label", "TCheckbutton"]:
        style.configure(w, background=bg, foreground=fg)

    email_entry.configure(background=bg, foreground=fg)

该函数在用户切换暗模式时手动更新小部件的颜色。

📧 第 6 步:电子邮件验证逻辑

6.1 检查电子邮件格式(正则)

def is_valid_email_format(email):
    """Return True if the email matches a simple pattern."""
    regex = r"^[\w\.-]+@[\w\.-]+\.\w+$"
    return re.match(regex, email) is not None

6.2 检查域名 MX 记录

def has_mx_record(domain):
    """Return True if the domain has at least one MX record."""
    try:
        records = dns.resolver.resolve(domain, "MX")
        return bool(records)
    except Exception:
        return False

6.3 开始验证(UI 线程)

def validate_email():
    """Validate the email entered by the user."""
    email = email_var.get().strip()

    if not email:
        messagebox.showwarning("Error", "Please enter an email address.")
        return

    set_status("Validating email...")
    threading.Thread(
        target=_validate_email_thread,
        args=(email,),
        daemon=True
    ).start()

繁重的工作在后台线程中执行,确保 UI 保持响应。

6.4 验证工作线程

def _validate_email_thread(email):
    """Background worker that performs the actual checks."""
    if not is_valid_email_format(email):
        validation_result_var.set("Result: ❌ Invalid format")
        set_status("Validation complete")
        return

    domain = email.split("@")[1]

    if has_mx_record(domain):
        validation_result_var.set("Result: ✅ Valid email")
    else:
        validation_result_var.set("Result: ⚠ Domain may not receive emails")

    add_to_history(email)
    set_status("Validation complete")

🗂 第 7 步:电子邮件历史管理

添加到历史列表

def add_to_history(email):
    """Append email to history and update the Listbox."""
    email_history.append(email)
    history_list.insert(tk.END, f"{len(email_history)}{email}")

导出历史为 .txt

def export_history_txt():
    """Save the email‑validation history to a text file."""
    if not email_history:
        messagebox.showinfo("Empty History", "No emails to export.")
        return

    file_path = filedialog.asksaveasfilename(
        defaultextension=".txt",
        filetypes=[("Text Files", "*.txt")],
        title="Export Email History"
    )
    if not file_path:
        return

    try:
        with open(file_path, "w", encoding="utf-8") as f:
            f.write("Email Validation History\n")
            f.write("=" * 30 + "\n\n")
            for i, email in enumerate(email_history, 1):
                f.write(f"{i}. {email}\n")

        set_status("Email history exported")
        messagebox.showinfo("Export Successful", "Email history saved successfully.")
    except Exception as e:
        messagebox.showerror("Export Failed", str(e))

🎨 第 8 步:样式

style = ttk.Style()
style.theme_use("clam")                     # Base theme
style.configure(
    "Action.TButton",
    font=("Segoe UI", 11, "bold"),
    padding=8
)

创建粗体、间距适中的操作按钮。

📊 第9步:状态栏

status_var = tk.StringVar(value="Ready")

ttk.Label(
    root,
    textvariable=status_var,
    anchor="w"
).pack(side=tk.BOTTOM, fill="x")

状态栏位于窗口底部,显示诸如 ReadyValidating…Export successful 等信息。

🧩 将所有部分组合在一起(UI 布局)

下面是一个最小化的布局示例,将各个部件组合在一起。可以随意自定义外观和感觉。

# ----- Main Frame -------------------------------------------------
main_frame = ttk.Frame(root, padding=20)
main_frame.pack(fill="both", expand=True)

# Email entry
ttk.Label(main_frame, text="Enter email address:").grid(row=0, column=0, sticky="w")
email_entry = ttk.Entry(main_frame, textvariable=email_var, width=40)
email_entry.grid(row=0, column=1, padx=5, pady=5, sticky="ew")

# Validate button
validate_btn = ttk.Button(
    main_frame,
    text="Validate",
    style="Action.TButton",
    command=validate_email
)
validate_btn.grid(row=0, column=2, padx=5)

# Result label
result_lbl = ttk.Label(
    main_frame,
    textvariable=validation_result_var,
    font=("Segoe UI", 12)
)
result_lbl.grid(row=1, column=0, columnspan=3, pady=10, sticky="w")

# Dark‑mode toggle
dark_check = ttk.Checkbutton(
    main_frame,
    text="Dark mode",
    variable=dark_mode_var,
    command=toggle_theme
)
dark_check.grid(row=2, column=0, pady=5, sticky="w")

# History Listbox
history_frame = ttk.Labelframe(main_frame, text="Validation History")
history_frame.grid(row=3, column=0, columnspan=3, sticky="nsew", pady=10)

history_list = tk.Listbox(history_frame, height=8)
history_list.pack(fill="both", expand=True, padx=5, pady=5)

# Export button
export_btn = ttk.Button(
    main_frame,
    text="Export History",
    style="Action.TButton",
    command=export_history_txt
)
export_btn.grid(row=4, column=0, columnspan=3, pady=5)

# Make columns expand nicely
main_frame.columnconfigure(1, weight=1)
root.mainloop()

运行脚本,输入电子邮件地址,点击 Validate,即可看到结果显示。切换暗模式,查看历史记录,并在需要时导出。

祝你玩得开心,尽情构建并扩展自己的邮箱验证工具吧! 🚀

🧱 第10步:构建 UI 布局

主容器

main = ttk.Frame(root, padding=20)
main.pack(expand=True, fill="both")

标题与输入

ttk.Label(
    main,
    text="Email Validation Tool",
    font=("Segoe UI", 22, "bold")
).pack()

email_entry = ttk.Entry(
    main,
    textvariable=email_var,
    font=("Segoe UI", 14),
    justify="center"
)
email_entry.pack(fill="x", pady=8)

ttk.Label(
    main,
    textvariable=validation_result_var,
    font=("Segoe UI", 12, "bold")
).pack(pady=4)

🎛 第11步:控制

controls = ttk.Frame(main)
controls.pack(pady=8)

ttk.Button(
    controls,
    text="✅ Validate",
    command=validate_email,
    style="Action.TButton"
).pack(side="left", padx=4)

ttk.Button(
    controls,
    text="📤 Export History",
    command=export_history_txt,
    style="Action.TButton"
).pack(side="left", padx=4)

🗄 第12步:邮件历史库

vault = ttk.LabelFrame(
    main,
    text="Email History Vault",
    padding=10
)
vault.pack(fill="both", expand=True, pady=10)

history_list = tk.Listbox(
    vault,
    font=("Segoe UI", 10),
    height=10
)
history_list.pack(fill="both", expand=True)

⚙ 第13步:应用选项

ttk.Checkbutton(
    main,
    text="Dark Mode",
    variable=dark_mode_var,
    command=toggle_theme
).pack(pady=6)

▶ 第 14 步:运行应用

root.mainloop()

这将启动 Tkinter 事件循环并启动您的应用程序。

🎉 最终思考

您现在拥有一个功能完整的 电子邮件验证桌面应用,具备以下特性:

  • 正则表达式验证
  • MX 记录检查
  • 多线程
  • 历史记录追踪
  • 导出功能
  • 暗色模式

电子邮件验证工具

Back to Blog

相关文章

阅读更多 »