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)