Keywords: Python | HTML Email | smtplib | email module | MIMEMultipart
Abstract: This article provides a comprehensive guide on sending HTML formatted emails using Python's smtplib and email modules. It covers basic HTML email sending, multi-format content support, multiple recipients handling, attachment management, image embedding, and includes complete code examples with best practices.
Fundamentals of Sending HTML Emails with Python
Python provides comprehensive email sending capabilities through its built-in smtplib and email modules. The smtplib module handles connection establishment with SMTP servers and email transmission, while the email module constructs structured email content.
Core Module Overview
The smtplib module is part of Python's standard library and supports communication with SMTP servers. Configuration requires server address, port, and authentication details.
The email.mime.multipart and email.mime.text submodules create multipart emails that can contain both plain text and HTML content simultaneously.
Basic HTML Email Implementation
Below is the fundamental code example for sending HTML emails:
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# Configure sender and recipient
sender = "my@email.com"
recipient = "your@email.com"
# Create multipart message container
msg = MIMEMultipart('alternative')
msg['Subject'] = "Test Email"
msg['From'] = sender
msg['To'] = recipient
# Create plain text version
text_content = "Hi!\nHow are you?\nHere is the link you wanted:\nhttp://www.python.org"
# Create HTML version
html_content = """<html>
<head></head>
<body>
<p>Hi!<br>
How are you?<br>
Here is the <a href="http://www.python.org">link</a> you wanted.
</p>
</body>
</html>"""
# Convert content to MIME objects
text_part = MIMEText(text_content, 'plain')
html_part = MIMEText(html_content, 'html')
# Attach to message container
msg.attach(text_part)
msg.attach(html_part)
# Send email
with smtplib.SMTP('localhost') as server:
server.sendmail(sender, recipient, msg.as_string())Multi-format Content Support
Using MIMEMultipart('alternative') creates emails containing multiple content versions. According to RFC 2046 standards, email clients prioritize displaying the last attached part (typically HTML version), falling back to previous plain text versions if display fails.
SMTP Server Configuration
Real-world applications require actual SMTP server configuration:
# SMTP server configuration
smtp_server = "smtp.example.com"
port = 587
username = "your_username"
password = "your_password"
with smtplib.SMTP(smtp_server, port) as server:
server.starttls() # Enable TLS encryption
server.login(username, password)
server.sendmail(sender, recipient, msg.as_string())Advanced Functionality
Multiple Recipients Support
Specify multiple recipients using comma-separated strings or lists:
recipients = ["user1@example.com", "user2@example.com", "user3@example.com"]
msg['To'] = ", ".join(recipients)Adding CC and BCC
msg['Cc'] = "cc1@example.com, cc2@example.com"
msg['Bcc'] = "bcc1@example.com, bcc2@example.com"Attachment Handling
Use email.mime.base.MIMEBase to add various attachment types:
from email import encoders
from email.mime.base import MIMEBase
# Add PDF attachment
filename = "document.pdf"
with open(filename, "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={filename}")
msg.attach(part)Image Embedding
Embed images in HTML using CID references:
from email.mime.image import MIMEImage
# HTML content referencing CID
html_with_image = '''<html>
<body>
<img src="cid:embedded_image">
</body>
</html>'''
# Add image attachment and set CID
with open("image.jpg", "rb") as img_file:
img_part = MIMEImage(img_file.read())
img_part.add_header('Content-ID', '<embedded_image>')
msg.attach(img_part)Best Practices
Always provide plain text fallback versions for compatibility. Reasonably control email size, recommending individual emails not exceed 10MB total. Use TLS encryption to protect authentication information. In production environments, consider using professional email sending services or APIs for better scalability and delivery rates.
Error Handling
Implement proper error handling in practical applications:
try:
with smtplib.SMTP(smtp_server, port) as server:
server.starttls()
server.login(username, password)
server.sendmail(sender, recipient, msg.as_string())
print("Email sent successfully")
except smtplib.SMTPException as e:
print(f"Email sending failed: {e}")