def send_bulk_email(recipients, subject, html_body): msg = MIMEMultipart('alternative') msg['From'] = 'sender@yourdomain.com' msg['Subject'] = subject msg.attach(MIMEText(html_body, 'html')) with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server: server.starttls() server.login(USERNAME, API_TOKEN) for recipient in recipients: msg['To'] = recipient server.send_message(msg) del msg['To'] # Remove for next iteration
Attachments
Code
def send_email_with_attachment(to_email, subject, body, file_path): msg = MIMEMultipart() msg['From'] = 'sender@yourdomain.com' msg['To'] = to_email msg['Subject'] = subject msg.attach(MIMEText(body, 'html')) # Add attachment 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) with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server: server.starttls() server.login(USERNAME, API_TOKEN) server.send_message(msg)
Lettermint Headers
Add Lettermint-specific headers for tags, metadata, and routing:
Code
from email.mime.text import MIMETextfrom email.mime.multipart import MIMEMultipartmsg = MIMEMultipart('alternative')msg['From'] = 'sender@yourdomain.com'msg['To'] = 'recipient@example.com'msg['Subject'] = 'Order Confirmation'# Tag for categorizationmsg['X-LM-Tag'] = 'order-confirmation'# Metadata for tracking (included in webhooks)msg['X-LM-Metadata-order_id'] = '12345'msg['X-LM-Metadata-customer_id'] = 'cust_789'# Route selectionmsg['X-Lettermint-Route'] = 'transactional'msg.attach(MIMEText('<p>Your order has been confirmed.</p>', 'html'))
Metadata headers are extracted by Lettermint and included in webhook payloads, but not added to the actual email sent to recipients.
See the SMTP Introduction for full details on available headers.