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