Python Snippets

Automatic Email Newsletter Sender with HTML Templates and Attachments

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"]
    )

Explanation

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:

  1. Configuration: Set up SMTP server details and authentication credentials
  2. Template Personalization: Replaces placeholders like `` in HTML templates with recipient-specific information
  3. CSV Recipient Import: Reads recipient names and email addresses from a CSV file
  4. HTML Email Creation: Builds multipart emails with properly formatted HTML content
  5. Attachment Support: Optionally adds file attachments to all emails
  6. Secure Delivery: Uses TLS encryption for secure email transmission
  7. Batch Sending: Efficiently sends personalized emails to all recipients

Setup Instructions

  1. Create Recipients CSV File (recipients.csv):
    name,email
    John Doe,john@example.com
    Jane Smith,jane@example.com
    
  2. Create HTML Template (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>
    
  3. Configure Email Settings:
    • For Gmail, use App Passwords instead of regular password
    • Enable 2-factor authentication first
    • Generate an app password in Google Account settings
  4. Run the Script:
    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.