Untitled
import pandas as pd import smtplib import tkinter as tk import os from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from docx import Document from tkinter import filedialog from tkinter import messagebox from tkinter import ttk from dotenv import load_dotenv # Function to read text from a Word document and convert custom HTML-like tags to real HTML tags def extract_text_from_word(docx_file_path): doc = Document(docx_file_path) extracted_text = "" for para in doc.paragraphs: para_text = para.text extracted_text += para_text + "\n" return extracted_text # Function to convert a DataFrame to styled HTML def dataframe_to_styled_html(df, merge_first_row=False): table_style = ( "border-collapse: collapse; width: 65%; font-family: Arial, sans-serif; " "font-size: 14px; text-align: center;" ) header_style = ( "background-color: #6A0DAD; color: white; padding: 10px; border: 1px solid black;" ) cell_style = "padding: 10px; border: 1px solid black;" row_alt_style = "background-color: #f2f2f2;" html_table = f'<table style="{table_style}">' # Merge first row if requested if merge_first_row: html_table += f'<tr><td colspan="{len(df.columns)}" style="{header_style}">{df.columns[0]}</td></tr>' else: # Add table headers html_table += "<tr>" for col in df.columns: html_table += f'<th style="{header_style}">{col}</th>' html_table += "</tr>" # Add table rows for i, row in df.iterrows(): row_style = row_alt_style if i % 2 == 1 else "" html_table += f'<tr style="{row_style}">' for cell in row: if pd.isna(cell): cell_content = "" else: if isinstance(cell, float): cell_content = f"{cell:.2%}" if 0 <= cell <= 1 else cell else: cell_content = cell html_table += f'<td style="{cell_style}">{cell_content}</td>' html_table += "</tr>" html_table += "</table>" return html_table # Function to send bulk emails with text and tables def send_bulk_emails_with_text_and_tables( sender_email, sender_password, smtp_server, smtp_port, email_list_file, table1_file, table2_file, text_file, log_text_widget, log_file ): log_serial_number = 1 with open(log_file, 'a') as log_file_obj: # Read the email list from an Excel file email_data = pd.read_excel(email_list_file) if "Email" not in email_data.columns or "Salutations" not in email_data.columns or "CC" not in email_data.columns: log_text_widget.insert(tk.END, "The email list file must contain columns: 'Email', 'Salutations', and 'CC'.\n") return email_details = email_data[["Email", "Salutations", "CC"]] if text_file.endswith(".docx"): email_text = extract_text_from_word(text_file) else: log_text_widget.insert(tk.END, "Unsupported file format. Use a .docx file for the text.\n") return table1_df = pd.read_excel(table1_file) table2_df = pd.read_excel(table2_file) table1_html = dataframe_to_styled_html(table1_df) table2_html = dataframe_to_styled_html(table2_df, merge_first_row=True) if "{{ TABLE_1 }}" in email_text: email_text = email_text.replace("{{ TABLE_1 }}", table1_html) else: log_text_widget.insert(tk.END, "Placeholder {{ TABLE_1 }} not found in the text.\n") if "{{ TABLE_2 }}" in email_text: email_text = email_text.replace("{{ TABLE_2 }}", table2_html) else: log_text_widget.insert(tk.END, "Placeholder {{ TABLE_2 }} not found in the text.\n") email_body_html = f""" <html> <body> {email_text} </body> </html> """ try: with smtplib.SMTP(smtp_server, smtp_port) as server: server.starttls() server.login(sender_email, sender_password) for _, row in email_details.iterrows(): try: recipients = row["Email"].split(",") salutation = row["Salutations"] cc_list = row["CC"].split(",") if pd.notna(row["CC"]) else [] personalized_text = email_body_html.replace("{{ Salutations }}", salutation) msg = MIMEMultipart() msg["From"] = sender_email msg["To"] = ", ".join(recipients) msg["Cc"] = ", ".join(cc_list) msg["Subject"] = "Your Wealth Management Summary" msg.attach(MIMEText(personalized_text, "html")) all_recipients = recipients + cc_list server.sendmail(sender_email, all_recipients, msg.as_string()) log_text_widget.insert(tk.END, f"{log_serial_number}. Email sent successfully to {', '.join(recipients)}, CC: {', '.join(cc_list)}\n") log_text_widget.yview(tk.END) log_file_obj.write(f"{log_serial_number}. Email sent successfully to {', '.join(recipients)}, CC: {', '.join(cc_list)}\n") except Exception as e: log_text_widget.insert(tk.END, f"{log_serial_number}. Failed to send email to {', '.join(recipients)}: {e}\n") log_text_widget.yview(tk.END) log_file_obj.write(f"{log_serial_number}. Failed to send email to {', '.join(recipients)}: {e}\n") log_serial_number += 1 except Exception as e: log_text_widget.insert(tk.END, f"Failed to connect to the SMTP server: {e}\n") log_text_widget.yview(tk.END) log_file_obj.write(f"Failed to connect to the SMTP server: {e}\n") # Remaining code (UI setup) remains the same. # Function to browse file def browse_file(entry): # Open file dialog to select a file and set the path to the entry file_path = filedialog.askopenfilename(title="Select a file", filetypes=[("Excel files", "*.xlsx"), ("Text files", "*.txt"), ("PDF files", "*.pdf"), ("Word files", "*.docx")]) if file_path: entry.delete(0, tk.END) # Clear existing content entry.insert(0, file_path) # Insert selected file path # Function to handle the send email button click def send_email_ui(): sender_email = sender_email_entry.get() sender_password = sender_password_entry.get() email_list_file = email_list_entry.get() table1_file = table1_entry.get() table2_file = table2_entry.get() text_file = text_file_entry.get() smtp_server = "smtp.gmail.com" smtp_port = 587 log_file = "email_log.txt" # Log file path if not all([sender_email, sender_password, email_list_file, table1_file, table2_file, text_file]): messagebox.showerror("Missing Information", "Please fill in all fields before sending.") else: # Call the send_bulk_emails_with_text_and_tables function with the inputs send_bulk_emails_with_text_and_tables( sender_email, sender_password, smtp_server, smtp_port, email_list_file, table1_file, table2_file, text_file, log_text_widget, log_file ) messagebox.showinfo("Task Complete", "All emails have been sent successfully!") #env load_dotenv() sender_password = os.getenv("SENDER_PASSWORD", "") sender_email = os.getenv("SENDER_EMAIL", "") #print(os.getenv("SENDER_PASSWORD","")) # Create the main window root = tk.Tk() root.title("Pygmalion Wealth") # Set the window title # Sender Email tk.Label(root, text="Sender Email:").grid(row=0, column=0, padx=10, pady=5) sender_email_entry = tk.Entry(root, width=40) sender_email_entry.insert(0, sender_email) sender_email_entry.grid(row=0, column=1, padx=10, pady=5) # Sender Password tk.Label(root, text="Sender Password:").grid(row=1, column=0, padx=10, pady=5) sender_password_entry = tk.Entry(root, width=40, show="*") sender_password_entry.insert(0,sender_password) sender_password_entry.grid(row=1, column=1, padx=10, pady=5) # Email List File tk.Label(root, text="Email List File:").grid(row=2, column=0, padx=10, pady=5) email_list_entry = tk.Entry(root, width=40) email_list_entry.grid(row=2, column=1, padx=10, pady=5) tk.Button(root, text="Browse", command=lambda: browse_file(email_list_entry)).grid(row=2, column=2, padx=10, pady=5) # Table 1 File tk.Label(root, text="Table 1 File:").grid(row=3, column=0, padx=10, pady=5) table1_entry = tk.Entry(root, width=40) table1_entry.grid(row=3, column=1, padx=10, pady=5) tk.Button(root, text="Browse", command=lambda: browse_file(table1_entry)).grid(row=3, column=2, padx=10, pady=5) # Table 2 File tk.Label(root, text="Table 2 File:").grid(row=4, column=0, padx=10, pady=5) table2_entry = tk.Entry(root, width=40) table2_entry.grid(row=4, column=1, padx=10, pady=5) tk.Button(root, text="Browse", command=lambda: browse_file(table2_entry)).grid(row=4, column=2, padx=10, pady=5) # Text File tk.Label(root, text="Text File:").grid(row=5, column=0, padx=10, pady=5) text_file_entry = tk.Entry(root, width=40) text_file_entry.grid(row=5, column=1, padx=10, pady=5) tk.Button(root, text="Browse", command=lambda: browse_file(text_file_entry)).grid(row=5, column=2, padx=10, pady=5) # Log Text Widget (for display) log_text_widget = tk.Text(root, height=10, width=80, wrap=tk.WORD, font=("Arial", 10)) log_text_widget.grid(row=6, column=0, columnspan=3, padx=10, pady=5) # Send Email Button send_button = tk.Button(root, text="Send Emails", command=send_email_ui) send_button.grid(row=7, column=0, padx=10, pady=10) #exit program button exit_button = tk.Button(root, text="Exit", command=root.quit) exit_button.grid(row=7, column=3, padx=10, pady=10) # Start the Tkinter event loop root.mainloop()
Leave a Comment