import pandas as pd import re import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart import streamlit as st import os from datetime import datetime # Function to validate email using regular expression def is_valid_email(email): pattern = r'^[a-zA-Z0-9._%+-]+@[a-zAZ0-9.-]+\.[a-zA-Z]{2,}$' return re.match(pattern, email) is not None # Function to validate email via SMTP server def check_smtp_validity(email, smtp_server='smtp.gmail.com', smtp_port=587, sender_email='your_email@example.com', sender_password='your_email_password'): try: server = smtplib.SMTP(smtp_server, smtp_port) server.starttls() server.login(sender_email, sender_password) msg = MIMEMultipart() msg['From'] = sender_email msg['To'] = email msg['Subject'] = 'Congratulations! You’ve won a prize!' body = 'Click this link to claim your prize: http://example.com' msg.attach(MIMEText(body, 'plain')) server.sendmail(sender_email, email, msg.as_string()) server.quit() return 'valid' except smtplib.SMTPRecipientsRefused: return 'invalid' except Exception as e: return 'invalid' # Function to read different types of files def read_file(file): if file.name.endswith('.xls') or file.name.endswith('.xlsx'): return pd.read_excel(file) elif file.name.endswith('.csv'): return pd.read_csv(file) elif file.name.endswith('.ods'): return pd.read_excel(file, engine="odf") else: st.error("Unsupported file format. Please upload a valid Excel (.xls, .xlsx), CSV, or ODS file.") return None # Function to validate emails and save results to a new file def verify_emails(input_df, output_file, sender_email, sender_password, batch_start, batch_size=500): try: # Process only a batch of 500 emails per day batch_df = input_df.iloc[batch_start:batch_start + batch_size] # Validate the emails in the batch batch_df['status'] = batch_df['emails'].apply(lambda email: check_smtp_validity(email, sender_email=sender_email, sender_password=sender_password)) # Save the result to output file if output_file.endswith('.csv'): batch_df.to_csv(output_file, index=False) elif output_file.endswith('.ods'): batch_df.to_excel(output_file, index=False, engine='odf') else: batch_df.to_excel(output_file, index=False) return batch_df, batch_start + len(batch_df) except Exception as e: st.error(f"Error: {e}") return None, batch_start # Function to send email with results as attachment def send_email_result(output_file, recipient_email, sender_email, sender_password): try: # Create the email message msg = MIMEMultipart() msg['From'] = sender_email msg['To'] = recipient_email msg['Subject'] = 'Email Validation Results' body = 'Please find the attached email validation results.' msg.attach(MIMEText(body, 'plain')) # Attach the output file (Excel with validation results) with open(output_file, 'rb') as attachment: part = MIMEText(attachment.read(), 'base64', 'utf-8') part.add_header('Content-Disposition', 'attachment', filename=os.path.basename(output_file)) msg.attach(part) # Send the email with smtplib.SMTP('smtp.gmail.com', 587) as server: server.starttls() server.login(sender_email, sender_password) server.sendmail(sender_email, recipient_email, msg.as_string()) st.success(f"Results successfully sent to {recipient_email}") except Exception as e: st.error(f"Error sending email: {e}") # Function to load settings (sender email, app password, recipient email) def load_settings(): if os.path.exists("settings.txt"): with open("settings.txt", "r") as f: settings = f.read().splitlines() return settings return None # Function to save settings (sender email, app password, recipient email) def save_settings(sender_email, sender_password, recipient_email): with open("settings.txt", "w") as f: f.write(f"{sender_email}\n{sender_password}\n{recipient_email}") # Function to load progress (last processed email index) def load_progress(): if os.path.exists("progress.txt"): with open("progress.txt", "r") as f: return int(f.read().strip()) return 0 # Function to save progress (last processed email index) def save_progress(progress): with open("progress.txt", "w") as f: f.write(str(progress)) # Streamlit App def main(): st.title("Email Validation App") # Display instructions to create a Gmail App Password st.markdown(""" **To send emails using your Gmail account, you need to generate an App Password:** 1. Go to [Google App Passwords](https://myaccount.google.com/apppasswords). 2. Sign in to your Google account if prompted. 3. Under "Select App," choose **Other (Custom name)** from the dropdown list. 4. Enter a name for the app (e.g., "Email Validation App") and click **Generate**. 5. Copy the generated password and paste it into the "App Password" field in this app. 6. Use this App Password instead of your regular Gmail password when sending emails. """) # Load settings if they exist settings = load_settings() # Step 1: Upload the file (Excel, CSV, or ODS) only if settings are already saved if settings: st.info("Settings already saved. You can upload your email file to continue processing.") else: st.warning("No settings found. Please provide your Gmail credentials and recipient email first.") uploaded_file = st.file_uploader("Upload your file with emails (Excel, CSV, or ODS)", type=["xls", "xlsx", "csv", "ods"]) # Load the file and process emails only if it's uploaded if uploaded_file: input_df = read_file(uploaded_file) if input_df is None: return # Ensure the file contains an 'emails' column if 'emails' not in input_df.columns: st.error("Error: 'emails' column not found in the uploaded file.") return # Step 2: Input Gmail credentials if not already saved if not settings: sender_email = st.text_input("Enter temporary Gmail ID", type="default") sender_password = st.text_input("Enter Gmail App Password", type="password") recipient_email = st.text_input("Enter recipient email for results", type="default") if sender_email and sender_password and recipient_email: if st.button("Save Settings"): save_settings(sender_email, sender_password, recipient_email) st.success("Settings saved. You can now upload your email file and continue processing.") st.experimental_rerun() # Rerun the app to load the new settings and show the process button else: # Use saved settings sender_email, sender_password, recipient_email = settings # Process emails in batches of 500 batch_start = load_progress() output_file = f"output_results_{datetime.now().strftime('%Y%m%d_%H%M%S')}" if uploaded_file.name.endswith('.csv'): output_file += '.csv' elif uploaded_file.name.endswith('.ods'): output_file += '.ods' else: output_file += '.xlsx' # After saving settings, now show the "Process Next Batch" button if st.button("Process Next Batch"): batch_df, new_progress = verify_emails(input_df, output_file, sender_email, sender_password, batch_start) if batch_df is not None: save_progress(new_progress) send_email_result(output_file, recipient_email, sender_email, sender_password) st.success(f"Processed and sent results for batch {batch_start // 500 + 1}. Progress saved.") else: st.error("Error processing the batch.") if __name__ == "__main__": if not os.path.exists("uploaded_files"): os.makedirs("uploaded_files") main()