import smtplib
import ssl
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import csv
from datetime import datetime
import os
class NewsletterSender:
def __init__(self, smtp_server, smtp_port, email, password):
self.smtp_server = smtp_server
self.smtp_port = smtp_port
self.email = email
self.password = password
def send_newsletter(self, recipients_csv, subject, html_template_path, attachments=None):
"""
Send HTML newsletter to recipients from CSV file
Args:
recipients_csv (str): Path to CSV file with 'name' and 'email' columns
subject (str): Email subject line
html_template_path (str): Path to HTML template file
attachments (list): List of file paths to attach (optional)
"""
# Read HTML template
with open(html_template_path, 'r', encoding='utf-8') as f:
html_content = f.read()
# Read recipients from CSV
recipients = []
with open(recipients_csv, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
recipients.append({
'name': row['name'],
'email': row['email']
})
# Create secure SSL context
context = ssl.create_default_context()
# Connect to SMTP server
with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:
server.starttls(context=context)
server.login(self.email, self.password)
for recipient in recipients:
# Create message
msg = MIMEMultipart('alternative')
msg['Subject'] = subject
msg['From'] = self.email
msg['To'] = recipient['email']
msg['Date'] = datetime.now().strftime("%a, %d %b %Y %H:%M:%S %z")
# Personalize HTML content
personalized_html = html_content.replace('', recipient['name'])
# Add HTML part
html_part = MIMEText(personalized_html, 'html', 'utf-8')
msg.attach(html_part)
# Add attachments if provided
if attachments:
for file_path in attachments:
if os.path.isfile(file_path):
with open(file_path, "rb") as attachment:
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header(
'Content-Disposition',
f'attachment; filename= {os.path.basename(file_path)}'
)
msg.attach(part)
# Send email
server.send_message(msg)
print(f"Sent newsletter to {recipient['name']} <{recipient['email']}>")
print(f"Newsletter sent to {len(recipients)} recipients")
# Example usage
if __name__ == "__main__":
# Configuration
SENDER_EMAIL = "your_email@gmail.com"
SENDER_PASSWORD = "your_app_password" # Use app password for Gmail
SMTP_SERVER = "smtp.gmail.com"
SMTP_PORT = 587
# Initialize sender
newsletter = NewsletterSender(
smtp_server=SMTP_SERVER,
smtp_port=SMTP_PORT,
email=SENDER_EMAIL,
password=SENDER_PASSWORD
)
# Send newsletter
newsletter.send_newsletter(
recipients_csv="recipients.csv",
subject="Monthly Newsletter - January 2026",
html_template_path="newsletter_template.html",
attachments=["company_report.pdf", "special_offer.jpg"]
)
This Python script implements an automatic email newsletter sender that can personalize messages, include attachments, and send HTML emails to multiple recipients from a CSV file. Here’s what it does:
recipients.csv):
name,email
John Doe,john@example.com
Jane Smith,jane@example.com
newsletter_template.html):
<!DOCTYPE html>
<html>
<head><title>Newsletter</title></head>
<body>
<h1>Hello !</h1>
<p>Thank you for subscribing to our newsletter.</p>
</body>
</html>
python newsletter_sender.py
This solution is ideal for businesses, organizations, or content creators who need to send regular newsletters with personalized content to their subscriber lists. The attachment feature makes it especially useful for sending reports, promotional materials, or other relevant files along with the newsletter content.