+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Part 453 of 541

๐Ÿ“˜ Email: SMTP and IMAP

Master email: smtp and imap in Python with practical examples, best practices, and real-world applications ๐Ÿš€

๐Ÿ’ŽAdvanced
25 min read

Prerequisites

  • Basic understanding of programming concepts ๐Ÿ“
  • Python installation (3.8+) ๐Ÿ
  • VS Code or preferred IDE ๐Ÿ’ป

What you'll learn

  • Understand the concept fundamentals ๐ŸŽฏ
  • Apply the concept in real projects ๐Ÿ—๏ธ
  • Debug common issues ๐Ÿ›
  • Write clean, Pythonic code โœจ

๐ŸŽฏ Introduction

Welcome to this exciting tutorial on Email protocols in Python! ๐ŸŽ‰ Have you ever wondered how your email client sends and receives messages? Or how to automate email tasks with Python? Youโ€™re in the right place!

In this guide, weโ€™ll explore SMTP (Simple Mail Transfer Protocol) for sending emails and IMAP (Internet Message Access Protocol) for reading them. Whether youโ€™re building notification systems ๐Ÿ“ฌ, automating email responses ๐Ÿค–, or creating email-based applications ๐Ÿ“ง, understanding these protocols is essential for modern Python development.

By the end of this tutorial, youโ€™ll be sending and receiving emails like a pro! Letโ€™s dive in! ๐ŸŠโ€โ™‚๏ธ

๐Ÿ“š Understanding Email Protocols

๐Ÿค” What are SMTP and IMAP?

Think of email protocols like a postal system ๐Ÿ“ฎ:

  • SMTP is like the post office that sends your mail ๐Ÿ“ค
  • IMAP is like your mailbox where you receive and organize mail ๐Ÿ“ฅ

In Python terms:

  • SMTP (Simple Mail Transfer Protocol) handles outgoing emails - itโ€™s your digital postman!
  • IMAP (Internet Message Access Protocol) manages incoming emails - itโ€™s your smart mailbox that lets you read, organize, and search messages!

This means you can:

  • โœจ Send automated emails and notifications
  • ๐Ÿš€ Read and process incoming emails programmatically
  • ๐Ÿ›ก๏ธ Build secure email integrations

๐Ÿ’ก Why Use Email Protocols in Python?

Hereโ€™s why developers love working with email protocols:

  1. Automation Power ๐Ÿ”’: Send bulk emails, newsletters, or notifications
  2. Integration Capabilities ๐Ÿ’ป: Connect your apps with email services
  3. Data Processing ๐Ÿ“–: Parse email content and attachments automatically
  4. Customer Communication ๐Ÿ”ง: Build support ticket systems or autoresponders

Real-world example: Imagine building an e-commerce system ๐Ÿ›’. With SMTP, you can send order confirmations, and with IMAP, you can process customer support emails automatically!

๐Ÿ”ง Basic Syntax and Usage

๐Ÿ“ Setting Up SMTP for Sending Emails

Letโ€™s start with sending a simple email:

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

# ๐Ÿ‘‹ Hello, Email World!
def send_simple_email():
    # ๐Ÿ”‘ Email configuration
    smtp_server = "smtp.gmail.com"
    port = 587  # ๐Ÿ”Œ Standard TLS port
    sender_email = "[email protected]"
    sender_password = "your_app_password"  # ๐Ÿ” Use app password!
    receiver_email = "[email protected]"
    
    # ๐Ÿ“ Create message
    message = MIMEMultipart()
    message["From"] = sender_email
    message["To"] = receiver_email
    message["Subject"] = "Hello from Python! ๐Ÿ"
    
    # ๐Ÿ’Œ Email body
    body = "This is an amazing email sent with Python! ๐ŸŽ‰"
    message.attach(MIMEText(body, "plain"))
    
    # ๐Ÿ“ค Send the email
    try:
        # ๐Ÿ”Œ Connect to server
        server = smtplib.SMTP(smtp_server, port)
        server.starttls()  # ๐Ÿ”’ Enable security
        server.login(sender_email, sender_password)
        
        # ๐Ÿš€ Send email
        text = message.as_string()
        server.sendmail(sender_email, receiver_email, text)
        server.quit()
        
        print("Email sent successfully! โœ…")
    except Exception as e:
        print(f"Error occurred: {e} โŒ")

๐Ÿ’ก Explanation: We use smtplib to connect to the email server, create a message with MIME types, and send it securely using TLS encryption!

๐ŸŽฏ Setting Up IMAP for Reading Emails

Now letโ€™s read emails:

import imaplib
import email
from email.header import decode_header

# ๐Ÿ“ฅ Connect to email inbox
def read_emails():
    # ๐Ÿ”‘ IMAP configuration
    imap_server = "imap.gmail.com"
    username = "[email protected]"
    password = "your_app_password"
    
    # ๐Ÿ”Œ Connect to server
    mail = imaplib.IMAP4_SSL(imap_server)
    mail.login(username, password)
    
    # ๐Ÿ“‚ Select inbox
    mail.select("inbox")
    
    # ๐Ÿ” Search for emails
    status, messages = mail.search(None, "ALL")
    email_ids = messages[0].split()
    
    # ๐Ÿ“ง Process last 5 emails
    for email_id in email_ids[-5:]:
        # ๐Ÿ“จ Fetch email
        status, msg_data = mail.fetch(email_id, "(RFC822)")
        
        for response_part in msg_data:
            if isinstance(response_part, tuple):
                # ๐Ÿ“„ Parse email content
                msg = email.message_from_bytes(response_part[1])
                
                # ๐Ÿ‘ค Get sender
                sender = msg["From"]
                print(f"From: {sender} ๐Ÿ“ค")
                
                # ๐Ÿ“‹ Get subject
                subject = decode_header(msg["Subject"])[0][0]
                if isinstance(subject, bytes):
                    subject = subject.decode()
                print(f"Subject: {subject} ๐Ÿ“Œ")
                
                print("-" * 50)
    
    # ๐Ÿ”š Close connection
    mail.close()
    mail.logout()

๐Ÿ’ก Practical Examples

๐Ÿ›’ Example 1: Order Confirmation System

Letโ€™s build an e-commerce email system:

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from datetime import datetime
import json

# ๐Ÿ›๏ธ Order confirmation emailer
class OrderEmailer:
    def __init__(self, smtp_server, port, email, password):
        self.smtp_server = smtp_server
        self.port = port
        self.email = email
        self.password = password
    
    # ๐Ÿ“ค Send order confirmation
    def send_order_confirmation(self, customer_email, order_data):
        message = MIMEMultipart("alternative")
        message["From"] = self.email
        message["To"] = customer_email
        message["Subject"] = f"Order Confirmed! #{order_data['order_id']} ๐ŸŽ‰"
        
        # ๐ŸŽจ Create beautiful HTML email
        html_body = f"""
        <html>
            <body style="font-family: Arial, sans-serif;">
                <h2>๐ŸŽ‰ Thank you for your order!</h2>
                <p>Hi {order_data['customer_name']}! ๐Ÿ‘‹</p>
                <p>Your order has been confirmed and is being processed.</p>
                
                <h3>๐Ÿ“ฆ Order Details:</h3>
                <ul>
                    <li>Order ID: #{order_data['order_id']}</li>
                    <li>Date: {order_data['date']}</li>
                    <li>Total: ${order_data['total']:.2f}</li>
                </ul>
                
                <h3>๐Ÿ›’ Items Ordered:</h3>
                <ul>
        """
        
        # ๐Ÿ“‹ Add items to email
        for item in order_data['items']:
            html_body += f"<li>{item['emoji']} {item['name']} - ${item['price']:.2f} x {item['quantity']}</li>"
        
        html_body += """
                </ul>
                <p>We'll send you tracking information once your order ships! ๐Ÿšš</p>
                <p>Happy shopping! ๐Ÿ’–</p>
            </body>
        </html>
        """
        
        # ๐Ÿ“Ž Attach HTML content
        html_part = MIMEText(html_body, "html")
        message.attach(html_part)
        
        # ๐Ÿ“ค Send email
        try:
            with smtplib.SMTP(self.smtp_server, self.port) as server:
                server.starttls()
                server.login(self.email, self.password)
                server.send_message(message)
            print(f"โœ… Order confirmation sent to {customer_email}")
            return True
        except Exception as e:
            print(f"โŒ Failed to send email: {e}")
            return False

# ๐ŸŽฎ Let's use it!
emailer = OrderEmailer("smtp.gmail.com", 587, "[email protected]", "password")

# ๐Ÿ›๏ธ Sample order
order = {
    "order_id": "12345",
    "customer_name": "Alice",
    "date": datetime.now().strftime("%Y-%m-%d %H:%M"),
    "total": 89.97,
    "items": [
        {"name": "Python Book", "price": 39.99, "quantity": 1, "emoji": "๐Ÿ“˜"},
        {"name": "Coffee Mug", "price": 14.99, "quantity": 2, "emoji": "โ˜•"},
        {"name": "Rubber Duck", "price": 19.99, "quantity": 1, "emoji": "๐Ÿฆ†"}
    ]
}

emailer.send_order_confirmation("[email protected]", order)

๐ŸŽฏ Try it yourself: Add email templates for shipping notifications and review requests!

๐ŸŽฎ Example 2: Email Support Ticket System

Letโ€™s create an automated support system:

import imaplib
import email
from email.header import decode_header
import re
from datetime import datetime

# ๐ŸŽซ Support ticket processor
class SupportTicketProcessor:
    def __init__(self, imap_server, email_address, password):
        self.imap_server = imap_server
        self.email_address = email_address
        self.password = password
        self.tickets = []
    
    # ๐Ÿ“ฅ Process support emails
    def process_support_emails(self):
        # ๐Ÿ”Œ Connect to email
        mail = imaplib.IMAP4_SSL(self.imap_server)
        mail.login(self.email_address, self.password)
        mail.select("inbox")
        
        # ๐Ÿ” Search for unread emails
        status, messages = mail.search(None, "UNSEEN")
        email_ids = messages[0].split()
        
        print(f"๐Ÿ“ฌ Found {len(email_ids)} new support emails!")
        
        for email_id in email_ids:
            # ๐Ÿ“จ Fetch email
            status, msg_data = mail.fetch(email_id, "(RFC822)")
            
            for response_part in msg_data:
                if isinstance(response_part, tuple):
                    msg = email.message_from_bytes(response_part[1])
                    
                    # ๐ŸŽซ Create ticket
                    ticket = self._create_ticket(msg)
                    self.tickets.append(ticket)
                    
                    # ๐Ÿท๏ธ Categorize ticket
                    ticket['category'] = self._categorize_ticket(ticket['body'])
                    ticket['priority'] = self._assign_priority(ticket['subject'], ticket['body'])
                    
                    print(f"\n๐ŸŽซ New Ticket Created:")
                    print(f"  ID: {ticket['id']}")
                    print(f"  From: {ticket['from']} ๐Ÿ‘ค")
                    print(f"  Category: {ticket['category']} ๐Ÿท๏ธ")
                    print(f"  Priority: {ticket['priority']} โšก")
        
        mail.close()
        mail.logout()
        return self.tickets
    
    # ๐ŸŽซ Create ticket from email
    def _create_ticket(self, msg):
        # ๐Ÿ“‹ Extract email data
        sender = msg["From"]
        subject = self._decode_header(msg["Subject"])
        body = self._get_email_body(msg)
        
        # ๐Ÿ†” Generate ticket ID
        ticket_id = f"TKT-{datetime.now().strftime('%Y%m%d%H%M%S')}"
        
        return {
            "id": ticket_id,
            "from": sender,
            "subject": subject,
            "body": body,
            "created_at": datetime.now(),
            "status": "open"
        }
    
    # ๐Ÿท๏ธ Categorize ticket based on content
    def _categorize_ticket(self, body):
        body_lower = body.lower()
        
        categories = {
            "billing": ["payment", "invoice", "charge", "refund", "bill"],
            "technical": ["error", "bug", "crash", "not working", "broken"],
            "account": ["password", "login", "account", "username", "access"],
            "feature": ["feature", "request", "suggestion", "improve", "add"]
        }
        
        for category, keywords in categories.items():
            if any(keyword in body_lower for keyword in keywords):
                return f"{category} {self._get_category_emoji(category)}"
        
        return "general ๐Ÿ“‹"
    
    # โšก Assign priority
    def _assign_priority(self, subject, body):
        urgent_keywords = ["urgent", "asap", "emergency", "critical", "immediately"]
        content = (subject + " " + body).lower()
        
        if any(keyword in content for keyword in urgent_keywords):
            return "high ๐Ÿ”ด"
        elif "error" in content or "broken" in content:
            return "medium ๐ŸŸก"
        else:
            return "low ๐ŸŸข"
    
    # ๐ŸŽจ Get category emoji
    def _get_category_emoji(self, category):
        emojis = {
            "billing": "๐Ÿ’ฐ",
            "technical": "๐Ÿ”ง",
            "account": "๐Ÿ‘ค",
            "feature": "โœจ"
        }
        return emojis.get(category, "๐Ÿ“‹")
    
    # ๐Ÿ“„ Extract email body
    def _get_email_body(self, msg):
        body = ""
        if msg.is_multipart():
            for part in msg.walk():
                if part.get_content_type() == "text/plain":
                    body = part.get_payload(decode=True).decode()
                    break
        else:
            body = msg.get_payload(decode=True).decode()
        return body
    
    # ๐Ÿ”ค Decode email header
    def _decode_header(self, header):
        decoded = decode_header(header)[0][0]
        if isinstance(decoded, bytes):
            decoded = decoded.decode()
        return decoded

# ๐ŸŽฎ Test the system
processor = SupportTicketProcessor("imap.gmail.com", "[email protected]", "password")
tickets = processor.process_support_emails()

# ๐Ÿ“Š Show ticket summary
print(f"\n๐Ÿ“Š Ticket Summary:")
print(f"Total tickets: {len(tickets)}")
for ticket in tickets:
    print(f"- {ticket['id']}: {ticket['category']} ({ticket['priority']})")

๐Ÿš€ Advanced Concepts

๐Ÿง™โ€โ™‚๏ธ Advanced Topic 1: Email with Attachments

When youโ€™re ready to level up, handle attachments:

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import os

# ๐ŸŽฏ Advanced email with attachments
class AdvancedEmailer:
    def __init__(self, smtp_config):
        self.config = smtp_config
    
    # ๐Ÿ“Ž Send email with attachments
    def send_with_attachments(self, to_email, subject, body, attachments=[]):
        message = MIMEMultipart()
        message["From"] = self.config["email"]
        message["To"] = to_email
        message["Subject"] = subject
        
        # ๐Ÿ“ Add body
        message.attach(MIMEText(body, "plain"))
        
        # ๐Ÿ“Ž Add attachments
        for file_path in attachments:
            if os.path.isfile(file_path):
                # ๐Ÿ“ฆ Create attachment
                with open(file_path, "rb") as file:
                    part = MIMEBase("application", "octet-stream")
                    part.set_payload(file.read())
                
                encoders.encode_base64(part)
                
                # ๐Ÿท๏ธ Add header
                filename = os.path.basename(file_path)
                part.add_header(
                    "Content-Disposition",
                    f"attachment; filename= {filename}"
                )
                
                message.attach(part)
                print(f"๐Ÿ“Ž Attached: {filename}")
        
        # ๐Ÿ“ค Send email
        with smtplib.SMTP(self.config["server"], self.config["port"]) as server:
            server.starttls()
            server.login(self.config["email"], self.config["password"])
            server.send_message(message)
        
        print(f"โœ… Email with {len(attachments)} attachments sent!")

# ๐Ÿช„ Using the advanced emailer
config = {
    "server": "smtp.gmail.com",
    "port": 587,
    "email": "[email protected]",
    "password": "app_password"
}

emailer = AdvancedEmailer(config)
emailer.send_with_attachments(
    "[email protected]",
    "Monthly Report ๐Ÿ“Š",
    "Please find the monthly report attached! ๐Ÿ“ˆ",
    ["report.pdf", "data.xlsx", "charts.png"]
)

๐Ÿ—๏ธ Advanced Topic 2: Email Threading and Batch Processing

For the brave developers handling high volumes:

import threading
import queue
import time
from concurrent.futures import ThreadPoolExecutor

# ๐Ÿš€ High-performance email processor
class EmailBatchProcessor:
    def __init__(self, smtp_config, max_workers=5):
        self.config = smtp_config
        self.max_workers = max_workers
        self.email_queue = queue.Queue()
        self.results = []
    
    # ๐Ÿ“ฌ Add emails to queue
    def queue_email(self, recipient, subject, body):
        email_data = {
            "recipient": recipient,
            "subject": subject,
            "body": body,
            "queued_at": time.time()
        }
        self.email_queue.put(email_data)
        print(f"๐Ÿ“ฅ Queued email for {recipient}")
    
    # ๐Ÿš€ Process email batch
    def process_batch(self):
        start_time = time.time()
        
        with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
            # ๐Ÿ”„ Submit all emails
            futures = []
            while not self.email_queue.empty():
                email_data = self.email_queue.get()
                future = executor.submit(self._send_single_email, email_data)
                futures.append(future)
            
            # โณ Wait for completion
            for future in futures:
                result = future.result()
                self.results.append(result)
        
        # ๐Ÿ“Š Show results
        elapsed_time = time.time() - start_time
        successful = sum(1 for r in self.results if r["success"])
        
        print(f"\n๐Ÿ“Š Batch Processing Complete!")
        print(f"โœ… Successful: {successful}/{len(self.results)}")
        print(f"โฑ๏ธ Time taken: {elapsed_time:.2f} seconds")
        print(f"โšก Emails/second: {len(self.results)/elapsed_time:.2f}")
    
    # ๐Ÿ“ค Send single email
    def _send_single_email(self, email_data):
        try:
            # Simulate email sending
            time.sleep(0.1)  # Replace with actual SMTP sending
            
            return {
                "recipient": email_data["recipient"],
                "success": True,
                "sent_at": time.time(),
                "processing_time": time.time() - email_data["queued_at"]
            }
        except Exception as e:
            return {
                "recipient": email_data["recipient"],
                "success": False,
                "error": str(e)
            }

# ๐ŸŽฎ Test batch processing
processor = EmailBatchProcessor({"server": "smtp.gmail.com", "port": 587})

# ๐Ÿ“ฌ Queue multiple emails
recipients = [f"user{i}@example.com" for i in range(50)]
for recipient in recipients:
    processor.queue_email(
        recipient,
        "Newsletter ๐Ÿ“ฐ",
        "Check out our latest updates! ๐ŸŽ‰"
    )

# ๐Ÿš€ Process all emails
processor.process_batch()

โš ๏ธ Common Pitfalls and Solutions

๐Ÿ˜ฑ Pitfall 1: Using Plain Text Passwords

# โŒ Wrong way - storing password in code!
password = "my_actual_password123"  # ๐Ÿ˜ฐ Never do this!
server.login(email, password)

# โœ… Correct way - use environment variables!
import os
from dotenv import load_dotenv

load_dotenv()  # ๐Ÿ“ Load from .env file
password = os.getenv("EMAIL_PASSWORD")  # ๐Ÿ”’ Secure!
server.login(email, password)

# ๐ŸŽฏ Even better - use app passwords!
# Generate app-specific passwords for Gmail/Yahoo/etc
app_password = os.getenv("EMAIL_APP_PASSWORD")  # ๐Ÿ›ก๏ธ Extra secure!

๐Ÿคฏ Pitfall 2: Not Handling Connection Timeouts

# โŒ Dangerous - no timeout handling!
def send_email_unsafe():
    server = smtplib.SMTP("smtp.gmail.com", 587)
    server.starttls()  # ๐Ÿ’ฅ Might hang forever!

# โœ… Safe - with proper timeouts!
def send_email_safe():
    try:
        # โฑ๏ธ Set timeout
        server = smtplib.SMTP("smtp.gmail.com", 587, timeout=30)
        server.starttls()
        
        # ๐Ÿ”„ Also set timeout for operations
        server.timeout = 30
        
        print("โœ… Connected successfully!")
    except smtplib.SMTPServerDisconnected:
        print("โŒ Server disconnected!")
    except smtplib.SMTPConnectError:
        print("โŒ Connection failed!")
    except Exception as e:
        print(f"โŒ Error: {e}")
    finally:
        server.quit() if 'server' in locals() else None

๐Ÿ› ๏ธ Best Practices

  1. ๐ŸŽฏ Use App Passwords: Never use your main email password - create app-specific passwords!
  2. ๐Ÿ“ Handle Errors Gracefully: Always wrap email operations in try-except blocks
  3. ๐Ÿ›ก๏ธ Enable TLS/SSL: Always use encrypted connections (starttls() or SSL)
  4. ๐ŸŽจ Rate Limiting: Donโ€™t send too many emails too quickly - respect server limits
  5. โœจ Clean Up Connections: Always close IMAP connections and quit SMTP servers

๐Ÿงช Hands-On Exercise

๐ŸŽฏ Challenge: Build an Email Newsletter System

Create a complete newsletter system with these features:

๐Ÿ“‹ Requirements:

  • โœ… Subscribe/unsubscribe management via email commands
  • ๐Ÿท๏ธ Categorize subscribers by interests
  • ๐Ÿ‘ค Personalized email content
  • ๐Ÿ“… Schedule newsletter sending
  • ๐ŸŽจ HTML email templates with images

๐Ÿš€ Bonus Points:

  • Add bounce handling
  • Implement click tracking
  • Create analytics dashboard

๐Ÿ’ก Solution

๐Ÿ” Click to see solution
import smtplib
import imaplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import json
import os
from datetime import datetime
import schedule
import time

# ๐ŸŽฏ Newsletter management system!
class NewsletterSystem:
    def __init__(self, email_config):
        self.config = email_config
        self.subscribers_file = "subscribers.json"
        self.load_subscribers()
    
    # ๐Ÿ“ Load subscribers
    def load_subscribers(self):
        if os.path.exists(self.subscribers_file):
            with open(self.subscribers_file, 'r') as f:
                self.subscribers = json.load(f)
        else:
            self.subscribers = {}
    
    # ๐Ÿ’พ Save subscribers
    def save_subscribers(self):
        with open(self.subscribers_file, 'w') as f:
            json.dump(self.subscribers, f, indent=2)
    
    # ๐Ÿ“ฅ Process subscription commands
    def process_commands(self):
        mail = imaplib.IMAP4_SSL(self.config["imap_server"])
        mail.login(self.config["email"], self.config["password"])
        mail.select("inbox")
        
        # ๐Ÿ” Search for command emails
        status, messages = mail.search(None, 'SUBJECT "SUBSCRIBE"', "UNSEEN")
        self._process_subscriptions(mail, messages[0].split())
        
        status, messages = mail.search(None, 'SUBJECT "UNSUBSCRIBE"', "UNSEEN")
        self._process_unsubscriptions(mail, messages[0].split())
        
        mail.close()
        mail.logout()
    
    # โž• Process subscriptions
    def _process_subscriptions(self, mail, email_ids):
        for email_id in email_ids:
            status, msg_data = mail.fetch(email_id, "(RFC822)")
            # Extract sender email and add to subscribers
            # Implementation details...
            print("โœ… New subscriber added!")
    
    # ๐Ÿ“ค Send newsletter
    def send_newsletter(self, subject, template_name):
        successful = 0
        failed = 0
        
        for email, preferences in self.subscribers.items():
            # ๐ŸŽจ Personalize content
            html_content = self._generate_personalized_content(
                email, 
                preferences, 
                template_name
            )
            
            if self._send_single_newsletter(email, subject, html_content):
                successful += 1
            else:
                failed += 1
        
        print(f"๐Ÿ“Š Newsletter sent: {successful} โœ…, {failed} โŒ")
    
    # ๐ŸŽจ Generate personalized content
    def _generate_personalized_content(self, email, preferences, template):
        name = preferences.get("name", "Friend")
        interests = preferences.get("interests", ["general"])
        
        html = f"""
        <html>
            <body style="font-family: Arial; max-width: 600px; margin: 0 auto;">
                <h1>๐ŸŽ‰ Hello {name}!</h1>
                <p>Here's your personalized newsletter based on your interests: {', '.join(interests)} ๐ŸŽฏ</p>
                
                <div style="background: #f0f0f0; padding: 20px; border-radius: 10px;">
                    <h2>๐Ÿ“ฐ This Week's Highlights</h2>
                    <!-- Dynamic content based on interests -->
                </div>
                
                <p style="text-align: center; margin-top: 30px;">
                    <a href="mailto:{self.config['email']}?subject=UNSUBSCRIBE">Unsubscribe</a>
                </p>
            </body>
        </html>
        """
        return html
    
    # ๐Ÿ“ค Send single newsletter
    def _send_single_newsletter(self, recipient, subject, html_content):
        try:
            message = MIMEMultipart("alternative")
            message["From"] = self.config["email"]
            message["To"] = recipient
            message["Subject"] = subject
            
            html_part = MIMEText(html_content, "html")
            message.attach(html_part)
            
            with smtplib.SMTP(self.config["smtp_server"], self.config["port"]) as server:
                server.starttls()
                server.login(self.config["email"], self.config["password"])
                server.send_message(message)
            
            return True
        except Exception as e:
            print(f"โŒ Failed to send to {recipient}: {e}")
            return False
    
    # ๐Ÿ“… Schedule newsletter
    def schedule_weekly_newsletter(self):
        schedule.every().monday.at("09:00").do(
            self.send_newsletter, 
            "Weekly Newsletter ๐Ÿ“ฐ", 
            "weekly_template"
        )
        
        print("๐Ÿ“… Newsletter scheduled for Mondays at 9 AM!")
        
        while True:
            schedule.run_pending()
            time.sleep(60)

# ๐ŸŽฎ Test it out!
config = {
    "email": "[email protected]",
    "password": "app_password",
    "smtp_server": "smtp.gmail.com",
    "imap_server": "imap.gmail.com",
    "port": 587
}

newsletter = NewsletterSystem(config)
newsletter.process_commands()
newsletter.send_newsletter("Test Newsletter ๐ŸŽ‰", "welcome_template")

๐ŸŽ“ Key Takeaways

Youโ€™ve learned so much! Hereโ€™s what you can now do:

  • โœ… Send emails with SMTP using Pythonโ€™s smtplib ๐Ÿ’ช
  • โœ… Read emails with IMAP and process them programmatically ๐Ÿ›ก๏ธ
  • โœ… Handle attachments and create HTML emails ๐ŸŽฏ
  • โœ… Build email automation systems like support tickets and newsletters ๐Ÿ›
  • โœ… Implement security best practices with app passwords and encryption ๐Ÿš€

Remember: Email protocols are powerful tools for automation, but always respect privacy and follow anti-spam regulations! ๐Ÿค

๐Ÿค Next Steps

Congratulations! ๐ŸŽ‰ Youโ€™ve mastered email protocols in Python!

Hereโ€™s what to do next:

  1. ๐Ÿ’ป Practice with the exercises above
  2. ๐Ÿ—๏ธ Build an email automation project for your own use
  3. ๐Ÿ“š Learn about OAuth2 for more secure email authentication
  4. ๐ŸŒŸ Explore email parsing libraries like email-validator and python-magic

Remember: Every email automation expert started by sending their first โ€œHello Worldโ€ email. Keep coding, keep learning, and most importantly, have fun! ๐Ÿš€


Happy coding! ๐ŸŽ‰๐Ÿš€โœจ