DEV Community

Mate Technologies
Mate Technologies

Posted on

πŸ“¨ Build an Email Validation Tool with Python & Tkinter (Step-by-Step)

In this tutorial, we’ll build a desktop Email Validation Tool using Python + Tkinter.

By the end, your app will:

Validate email format using regex

Check if the domain has MX records (can receive email)

Keep a history of validated emails

Export results to a .txt file

Support light/dark mode

Stay responsive using threading

No advanced GUI knowledge required β€” we’ll go step by step.

πŸ“¦ Step 1: Import Required Libraries

Let’s start by importing everything we need.

import sys
import os
import re
import threading
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import dns.resolver
import sv_ttk
Enter fullscreen mode Exit fullscreen mode

What these are for:

tkinter / ttk β†’ GUI components

re β†’ email format validation

threading β†’ prevent UI freezing

dns.resolver β†’ MX record lookup

sv_ttk β†’ modern Tkinter theme

πŸ“Œ Install missing packages:

pip install dnspython sv-ttk

πŸ›  Step 2: Helper Functions
Resolve file paths (useful for packaging later)

def resource_path(file_name):
    base_path = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, file_name)
Enter fullscreen mode Exit fullscreen mode

Status bar updates

def set_status(msg):
    status_var.set(msg)
    root.update_idletasks()
Enter fullscreen mode Exit fullscreen mode

This keeps users informed while background tasks run.

πŸ–₯ Step 3: Create the Main Application Window

root = tk.Tk()
root.title("Email Validation Tool")
root.geometry("720x680")
sv_ttk.set_theme("light")
Enter fullscreen mode Exit fullscreen mode

Creates the main window

Sets size and title

Applies a modern light theme

🌍 Step 4: Global State Variables

dark_mode_var = tk.BooleanVar(value=False)
email_var = tk.StringVar()
validation_result_var = tk.StringVar(value="Result: β€”")
email_history = []
Enter fullscreen mode Exit fullscreen mode

These variables help us:

Track dark mode

Read email input

Display validation results

Store history

πŸŒ— Step 5: Dark Mode Toggle

def toggle_theme():
    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)
Enter fullscreen mode Exit fullscreen mode

This manually updates widget colors when dark mode is toggled.

πŸ“§ Step 6: Email Validation Logic
6.1 Check Email Format (Regex)

def is_valid_email_format(email):
    regex = r"^[\w\.-]+@[\w\.-]+\.\w+$"
    return re.match(regex, email) is not None
Enter fullscreen mode Exit fullscreen mode

This ensures the email looks valid.

6.2 Check Domain MX Records

def has_mx_record(domain):
    try:
        records = dns.resolver.resolve(domain, 'MX')
        return bool(records)
    except Exception:
        return False
Enter fullscreen mode Exit fullscreen mode

MX records indicate whether a domain can receive email.

6.3 Start Validation (UI Thread)

def validate_email():
    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()
Enter fullscreen mode Exit fullscreen mode

We run validation in a background thread so the UI doesn’t freeze.

6.4 Validation Worker Thread

def _validate_email_thread(email):
    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")
Enter fullscreen mode Exit fullscreen mode

πŸ—‚ Step 7: Email History Management
Add to history list

def add_to_history(email):
    email_history.append(email)
    history_list.insert(tk.END, f"{len(email_history)} β€’ {email}")
Enter fullscreen mode Exit fullscreen mode

Export History to .txt

def export_history_txt():
    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))
Enter fullscreen mode Exit fullscreen mode

🎨 Step 8: Styling

style = ttk.Style()
style.theme_use("clam")
style.configure("Action.TButton",
                font=("Segoe UI", 11, "bold"),
                padding=8)
Enter fullscreen mode Exit fullscreen mode

Creates bold action buttons.

πŸ“Š Step 9: Status Bar

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

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

🧱 Step 10: Build the UI Layout
Main Container

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

Title & Input

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)

Result Display
ttk.Label(
    main,
    textvariable=validation_result_var,
    font=("Segoe UI", 12, "bold")
).pack(pady=4)
Enter fullscreen mode Exit fullscreen mode

πŸŽ› Step 11: Controls

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)
Enter fullscreen mode Exit fullscreen mode

πŸ—„ Step 12: Email History Vault

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)
Enter fullscreen mode Exit fullscreen mode

βš™ Step 13: App Options

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

Enter fullscreen mode Exit fullscreen mode

β–Ά Step 14: Run the App

root.mainloop()
Enter fullscreen mode Exit fullscreen mode

This starts the Tkinter event loop and launches your application.

πŸŽ‰ Final Thoughts

You now have a fully functional email validation desktop app with:

Regex validation

MX record checking

Multithreading

History tracking

Export functionality

Dark mode

Email Validation Tool

Top comments (0)