|
| 1 | +import sys |
| 2 | +import os |
| 3 | +import tkinter as tk |
| 4 | +from tkinter import ttk, messagebox, scrolledtext, filedialog |
| 5 | +import sv_ttk |
| 6 | +import re |
| 7 | +import csv |
| 8 | + |
| 9 | +# ========================= |
| 10 | +# App Setup |
| 11 | +# ========================= |
| 12 | +root = tk.Tk() |
| 13 | +root.title("Advanced Email Slicer") |
| 14 | +root.geometry("950x650") |
| 15 | +root.iconbitmap("") # Add path to your icon if needed |
| 16 | + |
| 17 | +sv_ttk.set_theme("light") # Default theme |
| 18 | + |
| 19 | +# ========================= |
| 20 | +# Globals |
| 21 | +# ========================= |
| 22 | +sliced_emails = [] # List of tuples (username, domain) |
| 23 | + |
| 24 | +# ========================= |
| 25 | +# Helpers |
| 26 | +# ========================= |
| 27 | +def slice_email(email): |
| 28 | + """Return username and domain if valid, else None""" |
| 29 | + email = email.strip() |
| 30 | + pattern = r"^[\w\.\-]+@[\w\.\-]+\.\w+$" |
| 31 | + if re.match(pattern, email): |
| 32 | + username, domain = email.split("@") |
| 33 | + return username, domain |
| 34 | + return None |
| 35 | + |
| 36 | +def check_emails(): |
| 37 | + input_text = email_entry.get("1.0", tk.END).strip() |
| 38 | + if not input_text: |
| 39 | + messagebox.showerror("Invalid Input", "Enter at least one email address.") |
| 40 | + return |
| 41 | + |
| 42 | + emails = re.split(r"[,\s]+", input_text) |
| 43 | + invalid_emails = [] |
| 44 | + count_new = 0 |
| 45 | + |
| 46 | + for email in emails: |
| 47 | + if email: |
| 48 | + result = slice_email(email) |
| 49 | + if result: |
| 50 | + sliced_emails.append(result) |
| 51 | + count_new += 1 |
| 52 | + else: |
| 53 | + invalid_emails.append(email) |
| 54 | + |
| 55 | + update_results() |
| 56 | + email_entry.delete("1.0", tk.END) |
| 57 | + |
| 58 | + if invalid_emails: |
| 59 | + messagebox.showwarning( |
| 60 | + "Invalid Emails", |
| 61 | + f"The following emails are invalid and were skipped:\n{', '.join(invalid_emails)}" |
| 62 | + ) |
| 63 | + elif count_new > 0: |
| 64 | + messagebox.showinfo("Success", f"{count_new} emails processed successfully!") |
| 65 | + |
| 66 | +def update_results(): |
| 67 | + result_text.configure(state="normal") |
| 68 | + result_text.delete("1.0", tk.END) |
| 69 | + for username, domain in sliced_emails: |
| 70 | + result_text.insert(tk.END, f"📧 Username: {username} | Domain: {domain}\n") |
| 71 | + result_text.configure(state="disabled") |
| 72 | + |
| 73 | +def clear_history(): |
| 74 | + sliced_emails.clear() |
| 75 | + update_results() |
| 76 | + |
| 77 | +def copy_results(): |
| 78 | + root.clipboard_clear() |
| 79 | + root.clipboard_append(result_text.get("1.0", tk.END)) |
| 80 | + messagebox.showinfo("Copied", "Results copied to clipboard.") |
| 81 | + |
| 82 | +def export_to_csv(): |
| 83 | + if not sliced_emails: |
| 84 | + messagebox.showwarning("No Data", "No emails to export. Please slice some emails first.") |
| 85 | + return |
| 86 | + |
| 87 | + file_path = filedialog.asksaveasfilename( |
| 88 | + defaultextension=".csv", |
| 89 | + filetypes=[("CSV files", "*.csv")], |
| 90 | + title="Save CSV" |
| 91 | + ) |
| 92 | + if file_path: |
| 93 | + try: |
| 94 | + with open(file_path, "w", newline="", encoding="utf-8") as csvfile: |
| 95 | + writer = csv.writer(csvfile) |
| 96 | + writer.writerow(["Username", "Domain"]) |
| 97 | + for username, domain in sliced_emails: |
| 98 | + writer.writerow([username, domain]) |
| 99 | + messagebox.showinfo("Exported", f"Results successfully exported to {file_path}") |
| 100 | + except Exception as e: |
| 101 | + messagebox.showerror("Error", f"Failed to export CSV:\n{str(e)}") |
| 102 | + |
| 103 | +# ========================= |
| 104 | +# Styles |
| 105 | +# ========================= |
| 106 | +style = ttk.Style() |
| 107 | +style.theme_use("clam") |
| 108 | + |
| 109 | +style.configure("Action.TButton", font=("Segoe UI", 11, "bold"), |
| 110 | + foreground="white", background="#4CAF50", padding=8) |
| 111 | +style.map("Action.TButton", background=[("active", "#45a049"), ("disabled", "#a5d6a7")]) |
| 112 | + |
| 113 | +style.configure("Secondary.TButton", font=("Segoe UI", 11, "bold"), |
| 114 | + foreground="white", background="#2196F3", padding=8) |
| 115 | +style.map("Secondary.TButton", background=[("active", "#1976D2"), ("disabled", "#90caf9")]) |
| 116 | + |
| 117 | +# ========================= |
| 118 | +# Layout |
| 119 | +# ========================= |
| 120 | +top_frame = ttk.Frame(root, padding=20) |
| 121 | +top_frame.pack(fill="x") |
| 122 | + |
| 123 | +ttk.Label(top_frame, text="Advanced Email Slicer", font=("Segoe UI", 20, "bold")).pack(anchor="w") |
| 124 | +ttk.Label( |
| 125 | + top_frame, |
| 126 | + text="Enter one or more email addresses (comma, space, or newline separated) to slice username and domain.", |
| 127 | + font=("Segoe UI", 11) |
| 128 | +).pack(anchor="w", pady=(0,10)) |
| 129 | + |
| 130 | +input_frame = ttk.Frame(root, padding=10) |
| 131 | +input_frame.pack(fill="x") |
| 132 | + |
| 133 | +ttk.Label(input_frame, text="Emails:", font=("Segoe UI", 12)).pack(anchor="w", pady=(0,5)) |
| 134 | +email_entry = scrolledtext.ScrolledText(input_frame, height=6, font=("Segoe UI", 12)) |
| 135 | +email_entry.pack(fill="x", pady=(0,5)) |
| 136 | + |
| 137 | +button_frame = ttk.Frame(root, padding=10) |
| 138 | +button_frame.pack(fill="x") |
| 139 | +ttk.Button(button_frame, text="Slice Emails", command=check_emails, style="Action.TButton").pack(side="left", padx=5) |
| 140 | +ttk.Button(button_frame, text="Clear History", command=clear_history, style="Secondary.TButton").pack(side="left", padx=5) |
| 141 | +ttk.Button(button_frame, text="Copy Results", command=copy_results, style="Secondary.TButton").pack(side="left", padx=5) |
| 142 | +ttk.Button(button_frame, text="Export CSV", command=export_to_csv, style="Secondary.TButton").pack(side="left", padx=5) |
| 143 | + |
| 144 | +result_frame = ttk.LabelFrame(root, text="Results", padding=15) |
| 145 | +result_frame.pack(fill="both", expand=True, padx=20, pady=20) |
| 146 | + |
| 147 | +result_text = scrolledtext.ScrolledText(result_frame, state="disabled", font=("Consolas", 12)) |
| 148 | +result_text.pack(fill="both", expand=True) |
| 149 | + |
| 150 | +# ========================= |
| 151 | +# Run App |
| 152 | +# ========================= |
| 153 | +root.mainloop() |
0 commit comments