Spaces:
Runtime error
Runtime error
import smtplib | |
import pandas as pd | |
import time | |
import openpyxl | |
from email.mime.multipart import MIMEMultipart | |
from email.mime.text import MIMEText | |
from email.mime.image import MIMEImage | |
from email.utils import formataddr | |
import streamlit as st | |
import os | |
import base64 | |
# Set Streamlit app title and page configuration | |
st.set_page_config(page_title="Email Sender and Tracker", layout="wide") | |
# Email Sender Function | |
def send_email(server, sender_email, sender_password, receiver_email, subject, email_content): | |
message = MIMEMultipart() | |
message["From"] = formataddr(("AI Consultant", sender_email)) | |
message["To"] = receiver_email | |
message["Subject"] = subject | |
email_content_formatted = email_content.replace("\n", "<br><br>") | |
html_content = f""" | |
<html> | |
<head> | |
<style> | |
body {{ | |
font-family: Arial, sans-serif; | |
font-size: 14px; | |
line-height: 1.6; | |
margin: 0; | |
padding: 0; | |
}} | |
.email-container {{ | |
max-width: 600px; | |
margin: 0 auto; | |
padding: 20px; | |
}} | |
.email-header {{ | |
text-align: center; | |
margin-bottom: 20px; | |
}} | |
.email-header h2 {{ | |
color: #333333; | |
font-size: 24px; | |
font-weight: 700; | |
line-height: 1.2; | |
margin: 0; | |
}} | |
.email-content {{ | |
background-color: #f9f9f9; | |
padding: 20px; | |
text-align: justify; | |
}} | |
.email-content p {{ | |
color: #555555; | |
font-size: 16px; | |
line-height: 1.6; | |
margin: 0 0 10px; | |
}} | |
.email-content hr {{ | |
border: none; | |
border-top: 1px solid #dddddd; | |
margin: 20px 0; | |
}} | |
.logo {{ | |
display: block; | |
margin: 0 auto; | |
width: 60px; | |
}} | |
</style> | |
</head> | |
<body> | |
<div class="email-container"> | |
<div class="email-header"> | |
<h2>{subject}</h2> | |
</div> | |
<div class="email-content"> | |
{email_content_formatted} | |
<hr> | |
</div> | |
<img src="cid:logo_image" alt="Logo" class="logo"> | |
</div> | |
</body> | |
</html> | |
""" | |
# Attach the logo image | |
logo_path = "AIConsultantBlackSmall.png" | |
with open(logo_path, "rb") as logo_file: | |
logo_image = MIMEImage(logo_file.read()) | |
logo_image.add_header("Content-ID", "<logo_image>") | |
message.attach(logo_image) | |
message.attach(MIMEText(html_content, "html")) | |
email_message = message.as_string().encode("utf-8") | |
try: | |
server.sendmail(sender_email, receiver_email, email_message) | |
return True | |
except smtplib.SMTPException: | |
return False | |
# Main Function | |
def main(): | |
st.title("Email Sender and Tracker") | |
# Sidebar Inputs | |
sender_email = st.sidebar.text_input("Your Email") | |
sender_password = st.sidebar.text_input("Your Email Password", type="password") | |
subject = st.sidebar.text_input("Subject") | |
email_content = st.sidebar.text_area("Email Content", height=400) | |
# Recipients File Selection | |
recipients_file_path = st.sidebar.file_uploader("Select Excel file with recipient emails", type=["xlsx", "xls"]) | |
# Send Button | |
if st.sidebar.button("Send"): | |
if not sender_email or not sender_password or not subject or not email_content: | |
st.warning("Incomplete Information. Please fill in all the required fields.") | |
elif not recipients_file_path: | |
st.warning("Missing Recipients File. Please select an Excel file with recipient emails.") | |
else: | |
st.info("Sending emails...") | |
df = pd.read_excel(recipients_file_path) | |
receiver_emails = df.iloc[:, 0].tolist() | |
successful_emails = [] | |
with smtplib.SMTP("smtp.gmail.com", 587) as server: | |
server.starttls() | |
try: | |
server.login(sender_email, sender_password) | |
except smtplib.SMTPAuthenticationError: | |
st.error("Authentication Failed. Username and password not accepted.") | |
return | |
progress_bar = st.progress(0) | |
progress_text = st.empty() | |
for i, receiver_email in enumerate(receiver_emails[:1000], 1): # Send at most 200 emails from the list | |
if send_email(server, sender_email, sender_password, receiver_email, subject, email_content): | |
successful_emails.append(receiver_email) | |
time.sleep(0.1) # Delay between sending emails | |
progress_bar.progress(i / 1000) | |
progress_text.text(f"Sending email {i}") | |
st.success("Emails sent successfully!") | |
# Save Successful Emails | |
if successful_emails: | |
try: | |
workbook = openpyxl.Workbook() | |
worksheet = workbook.active | |
for email in successful_emails: | |
worksheet.append([email]) | |
# Specify the custom file name | |
custom_file_name = "successful_emails.xlsx" | |
excel_file_path = custom_file_name | |
workbook.save(excel_file_path) | |
workbook.close() | |
# Get the absolute file path | |
absolute_file_path = os.path.abspath(excel_file_path) | |
# Rename the file | |
new_file_name = "successful_emails.xlsx" | |
os.rename(absolute_file_path, new_file_name) | |
st.info(f"Successful emails saved to Excel file: {new_file_name}") | |
# Add button to save or download the Excel file | |
download_button_str = create_download_button(new_file_name, new_file_name) | |
st.markdown(download_button_str, unsafe_allow_html=True) | |
except Exception as e: | |
st.error(f"Error saving successful emails: {str(e)}") | |
else: | |
st.warning("No successful emails to save.") | |
# Helper function to create download button HTML string | |
def create_download_button(file_path, file_name): | |
button_str = f'<a href="data:application/octet-stream;base64,{get_base64_encoded(file_path)}" download="{file_name}" class="stButton">Download Successful Emails</a>' | |
return button_str | |
# Helper function to encode the file to base64 | |
def get_base64_encoded(file_path): | |
with open(file_path, "rb") as file: | |
encoded = base64.b64encode(file.read()).decode() | |
return encoded | |
# Run the Streamlit app | |
if __name__ == "__main__": | |
main() | |