python Utilities

Email Sender with Templates

SMTP email sender supporting HTML templates, attachments, and batch sending with rate limiting.

Apex Logic 0 copies
python
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
from pathlib import Path
from string import Template
from typing import List, Optional
import time

class EmailSender:
    def __init__(self, host: str, port: int, username: str, password: str):
        self.host = host
        self.port = port
        self.username = username
        self.password = password

    def _connect(self) -> smtplib.SMTP:
        server = smtplib.SMTP(self.host, self.port)
        server.starttls()
        server.login(self.username, self.password)
        return server

    def send(self, to: str, subject: str, html_body: str,
             attachments: Optional[List[str]] = None) -> bool:
        msg = MIMEMultipart()
        msg["From"] = self.username
        msg["To"] = to
        msg["Subject"] = subject
        msg.attach(MIMEText(html_body, "html"))

        for filepath in (attachments or []):
            path = Path(filepath)
            if path.exists():
                part = MIMEBase("application", "octet-stream")
                part.set_payload(path.read_bytes())
                encoders.encode_base64(part)
                part.add_header("Content-Disposition", f"attachment; filename={path.name}")
                msg.attach(part)

        try:
            server = self._connect()
            server.sendmail(self.username, to, msg.as_string())
            server.quit()
            return True
        except Exception as e:
            print(f"Failed to send to {to}: {e}")
            return False

    def send_template(self, to: str, subject: str, template_path: str,
                      variables: dict) -> bool:
        template = Template(Path(template_path).read_text())
        html = template.safe_substitute(variables)
        return self.send(to, subject, html)

    def send_batch(self, recipients: List[str], subject: str,
                   html_body: str, delay: float = 1.0) -> dict:
        results = {"sent": 0, "failed": 0}
        for email in recipients:
            if self.send(email, subject, html_body):
                results["sent"] += 1
            else:
                results["failed"] += 1
            time.sleep(delay)
        return results

Tags

email smtp automation templates

Related Snippets

javascript

File Upload Handler with Validation

python

Web Scraper with BeautifulSoup

python

CSV Data Processor

python

REST API Client with Retry