Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 151 additions & 0 deletions Automate Emails Daily/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# Guidebook: Email Automation Script with Advanced Features

# Overview

This Python script automates the process of sending emails to multiple recipients with enhanced features such as support for attachments and HTML-formatted emails. The script uses Python's built-in libraries (smtplib, ssl, and email) to send emails securely through Gmail's SMTP server. It also allows the user to customize the email's content, subject, recipients, and more via environment variables or in-script configuration.

# Features Added

1. Support for Attachments: You can now attach files to the email, making it more versatile for different use cases like sending reports, documents, or images.
2. HTML Email Support: You can send emails in HTML format, giving you more flexibility with rich text formatting, embedded links, and other styling options.

# Prerequisites

1. Python 3.x
2. A Gmail account (with less secure apps access enabled or an app-specific password if using 2FA)
3. Required libraries: smtplib, ssl, os, email (all built-in Python libraries)

# Environment Setup
To ensure security, it's recommended to store sensitive information like email credentials in environment variables. For this guide, we will store the Gmail password as an environment variable:

export EMAIL_PASSWORD='your_gmail_password'

# Code Breakdown
1. Import Required Modules

import smtplib
import ssl
import os
from email.message import EmailMessage
from email.utils import formataddr
-------------------------------------------------------------------------------------
smtplib: Used to create the connection to the Gmail SMTP server.
ssl: Provides a layer of security for the email communication.
os: Used to access environment variables (like the email password).
email.message: Allows crafting email messages, including text, HTML, and attachments.

**send_email Function**

This is the main function that sends the email.

Function Parameters:
sender_email (str): The email address sending the email.
sender_name (str): The sender's name that will appear in the email.
password (str): The sender's email password, pulled from environment variables.
receiver_emails (list): A list of email addresses to send the email to.
email_body (str): The body of the email, which can be in plain text or HTML.
email_subject (str): The subject line of the email. Default is "No subject."

**Example Function**

send_email(
sender_email="youremail@gmail.com",
sender_name="Your Name",
password=os.environ.get("EMAIL_PASSWORD"),
receiver_emails=["recipient1@gmail.com", "recipient2@gmail.com"],
email_body="Hello, this is a test email!",
email_subject="Test Email"
)

-------------------------------------------------------------------------------------

**Setting Up Email Headers**
The email headers include the subject, sender, recipient, and format:

msg["Subject"] = email_subject
msg["From"] = formataddr((f"{sender_name}", f"{sender_email}"))
msg["BCC"] = sender_email
msg.set_content(email_body) # This can also be an HTML body

-------------------------------------------------------------------------------------

**SMTP Server Connection**
Here we establish a connection to Gmail's SMTP server and use TLS (Transport Layer Security) to ensure a secure connection.

smtp_port = 587
smtp_server = "smtp.gmail.com"
ssl_context = ssl.create_default_context()

-------------------------------------------------------------------------------------

**Login and Sending the Email**
After logging in, the script loops through each recipient in the receiver_emails list and sends the email.

my_server = smtplib.SMTP(smtp_server, smtp_port)
my_server.starttls(context=ssl_context)
my_server.login(sender_email, password)

-------------------------------------------------------------------------------------

**Adding Attachments**
If you want to send attachments, use the following modification:

if attachments:
for file in attachments:
with open(file, "rb") as f:
file_data = f.read()
file_name = os.path.basename(file)
msg.add_attachment(file_data, maintype='application', subtype='octet-stream', filename=file_name)

-------------------------------------------------------------------------------------

**Sending HTML Emails**
To send HTML emails, modify the email body to contain HTML:

msg.add_alternative("""\
<html>
<body>
<p>Hello, <br>
This is an <b>HTML email</b>!</p>
</body>
</html>
""", subtype='html')

-------------------------------------------------------------------------------------

**Error Handling**
The script includes basic error handling to notify you if the connection or email-sending process fails:

except Exception as e:
print(f"ERROR: {e}")

--------------------------------------------------------------------------------------

**Full Example with Attachment and HTML Support**

send_email(
sender_email="youremail@gmail.com",
sender_name="Your Name",
password=os.environ.get("EMAIL_PASSWORD"),
receiver_emails=["recipient1@gmail.com", "recipient2@gmail.com"],
email_body="<h1>This is a Test Email with HTML</h1>",
email_subject="Test Email with HTML and Attachment",
attachments=["path/to/attachment1", "path/to/attachment2"]
)


--------------------------------------------------------------------------------------

# How to run the script

Ensure the required environment variable (EMAIL_PASSWORD) is set.
Customize the sender email, receiver emails, email body, and subject in the script.
Run the script from the command line:

python email_automation.py or main.py

You can also schedule the script to run daily using cron jobs or Task Scheduler (Windows).


# Thank You for reading this tutorial. I hope you found it helpful. If you have any questions or need further

50 changes: 40 additions & 10 deletions Automate Emails Daily/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,46 @@
import os
from email.message import EmailMessage
from email.utils import formataddr
from mimetypes import guess_type

def send_email(sender_email: str,
sender_name: str,
password:str,
receiver_emails: str ,
receiver_emails: list,
email_body: str,
email_subject: str="No subject",)-> None:
email_subject: str = "No subject",
is_html: bool = False,
attachments: list = None) -> None:

msg = EmailMessage()
msg["Subject"] = email_subject
msg["From"] = formataddr((f"{sender_name}", f"{sender_email}"))
msg["BCC"] = sender_email
msg.set_content(email_body)
msg["BCC"] = sender_email # Can add CC or BCC here if needed

# Support both plain text and HTML emails
if is_html:
msg.add_alternative(email_body, subtype='html')
else:
msg.set_content(email_body)

# Add attachments if provided
if attachments:
for file_path in attachments:
try:
with open(file_path, 'rb') as file:
file_data = file.read()
file_name = os.path.basename(file_path)
mime_type, _ = guess_type(file_path)
if mime_type:
mime_main, mime_subtype = mime_type.split('/')
else:
mime_main, mime_subtype = 'application', 'octet-stream'

msg.add_attachment(file_data, maintype=mime_main, subtype=mime_subtype, filename=file_name)
print(f"Attached file: {file_name}")
except Exception as e:
print(f"Failed to attach {file_path}: {e}")

smtp_port = 587
smtp_server = "smtp.gmail.com"

Expand Down Expand Up @@ -48,14 +74,18 @@ def send_email(sender_email: str,
finally:
my_server.quit()

# change these variables to suite your requirements
# Example usage
sender_email = "your-email@gmail.com"
sender_name = "your name"
password = os.environ.get("EMAIL_PASSWORD")

email_subject = "good morning"
email_body = "good morning, hope you have a wonderful day"

receiver_emails = ["receiver1-email@gmail.com", "receiver2-email@gmail.com", "receiver3-email@gmail.com"]
email_subject = "Good morning"
email_body = """
<h1>Good Morning!</h1>
<p>Hope you have a <strong>wonderful day</strong>.</p>
"""
receiver_emails = ["receiver1-email@gmail.com", "receiver2-email@gmail.com"]
attachments = ["path/to/attachment1.pdf", "path/to/attachment2.jpg"]

send_email(sender_email, sender_name, password, receiver_emails, email_body,email_subject)
# Sending the email as HTML with attachments
send_email(sender_email, sender_name, password, receiver_emails, email_body, email_subject, is_html=True, attachments=attachments)
23 changes: 23 additions & 0 deletions CSV to Excel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Explanation of Modifications

**Support for Multiple CSV Files:**

Modification: We now accept multiple CSV files, split by commas, in the csv_files list.

Sheet Name: For each CSV file, a new sheet is created, named after the CSV file (without the extension).

Loop: We loop over each CSV file in csv_files and process it individually.

**Automatic CSV Header Detection and Formatting:**

Modification: The first row of each CSV file is detected as the header.

Formatting: The header row is formatted with bold text (Font(bold=True)) and a yellow background (PatternFill).

Flag: A header_detected flag ensures that formatting is only applied to the first row

**Handling Empty or Invalid Files:**

Error handling remains in place for file not found and general exceptions.

#Thank You
81 changes: 53 additions & 28 deletions CSV to Excel/csv_excel.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,62 @@
import openpyxl
import os
from openpyxl.styles import Font, PatternFill

# Get the CSV and Excel file names from the user
csv_name = input("Name of the input CSV file with extension: ")
sep = input("Separator of the CSV file: ")
excel_name = input("Name of the output excel file with extension: ")
sheet_name = input("Name of the output excel sheet: ")
csv_files = input("Enter the CSV files separated by commas (e.g., file1.csv, file2.csv): ").split(',')
sep = input("Separator of the CSV files (default is ','): ") or ',' # Default to comma separator if not provided
excel_name = input("Name of the output Excel file with extension: ")

# Load the CSV file
# Load or create Excel workbook
if os.path.exists(excel_name):
workbook = openpyxl.load_workbook(excel_name)
sheet = workbook[sheet_name] if sheet_name in workbook.sheetnames else workbook.create_sheet(sheet_name)
else:
workbook = openpyxl.Workbook()
sheet = workbook.active
sheet.title = sheet_name

# Write the CSV data to the Excel sheet
try:
with open(csv_name, "r", encoding="utf-8") as file:
excel_row = 1
for line in file:
data = line.strip().split(sep)
excel_column = 1
for value in data:
sheet.cell(row=excel_row, column=excel_column, value=value)
excel_column += 1
excel_row += 1

# Save the Excel file
workbook.save(excel_name)

except FileNotFoundError:
print("Error: The CSV file was not found.")
except Exception as e:
print(f"An error occurred: {e}")

# Loop over multiple CSV files to write them into different sheets
for csv_name in csv_files:
csv_name = csv_name.strip() # Trim any whitespace
sheet_name = os.path.splitext(os.path.basename(csv_name))[0] # Sheet name based on the CSV filename

# Create a new sheet for each CSV file
if sheet_name in workbook.sheetnames:
sheet = workbook[sheet_name]
else:
sheet = workbook.create_sheet(sheet_name)

# Write CSV data to the Excel sheet
try:
with open(csv_name, "r", encoding="utf-8") as file:
excel_row = 1
header_detected = False # Flag to check if header formatting should be applied

for line in file:
data = line.strip().split(sep)
excel_column = 1

# Apply header formatting for the first row (headers)
if not header_detected:
for value in data:
cell = sheet.cell(row=excel_row, column=excel_column, value=value)
# Apply bold font and background color for the header row
cell.font = Font(bold=True)
cell.fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid")
excel_column += 1
header_detected = True # Mark the first row as header
else:
for value in data:
sheet.cell(row=excel_row, column=excel_column, value=value)
excel_column += 1

excel_row += 1

except FileNotFoundError:
print(f"Error: The CSV file '{csv_name}' was not found.")
except Exception as e:
print(f"An error occurred while processing {csv_name}: {e}")

# Save the Excel file with all sheets
workbook.save(excel_name)

print(f"All CSV files have been processed and saved to {excel_name}.")