2026-07-15

Send HTML emails with Python

Stefan Bogdanescu

Stefan Bogdanescu

Founder & Senior Architect

Send HTML emails with Python

Send HTML Emails with Python: Mastering MIME for Rich Content

When sending emails, it’s easy to default to simple plain text. However, modern communication demands rich content—images, styled layouts, and complex formatting. Sending HTML requires a deeper understanding of email protocols than simply connecting to an SMTP server. As a developer, you need to understand the structure that allows an email client (like Gmail or Outlook) to correctly interpret and render your message as intended.

This guide will walk you through the developer-focused method for sending fully formatted HTML emails using Python, focusing on the necessary MIME structure.

The Challenge: Plain Text vs. HTML Emails

The core difficulty in sending HTML via standard Python libraries is that email protocols rely on the MIME (Multipurpose Internet Mail Extensions) format to delineate different parts of an email—the headers, the body, and any attachments. Simply attaching raw HTML text will result in a broken email where the recipient sees the source code instead of the styled content.

To solve this, we must construct a properly encoded MIME message where the HTML content is explicitly marked as text/html.

Python Implementation using the email Module

Python’s built-in email package provides all the necessary tools to craft these complex messages correctly. We will use the MIMEMultipart and MIMEText classes to manage the email structure.

Step 1: Preparing the HTML Content

First, define the HTML content you wish to send. This is the content that will be wrapped in the correct MIME type.

from email import message_fromemail, Namespace
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

# 1. Define the HTML content
html_content = """\
<html>
  <head>
    <style>
      body { font-family: Arial, sans-serif; color: #333; }
      h1 { color: navy; border-bottom: 2px solid lightgray; }
    </style>
  </head>
  <body>
    <h1>Welcome to the Python Email Service!</h1>
    <p>This email was successfully sent using Python and MIME structuring.</p>
    <p>We leverage robust backend logic, much like the principles found in modern frameworks like those powering services such as Laravel, to ensure reliable delivery.</p>
  </body>
</html>
"""

# Set up the message structure
msg = MIMEMultipart()
msg['From'] = "sender@example.com"
msg['To'] = "recipient@example.com"
msg['Subject'] = "HTML Email Test from Python"

# Attach the HTML content as a part of the email
text_part = MIMEText(html_content, 'html')
msg.attach(text_part)

Step 2: Sending the Email via SMTP

Once the message object is correctly assembled, we use Python’s smtplib to connect to an external mail server and transmit the MIME message.

import smtplib

smtp_server = "smtp.gmail.com"  # Example: Use your provider's SMTP server
port = 587
sender_email = "your_email@example.com"
password = "your_app_password" # Use environment variables for security!

try:
    # Connect to the server
    server = smtplib.SMTP(smtp_server, port)
    server.starttls()  # Secure the connection
    server.login(sender_email, password)

    # Send the message
    status = server.sendmail(sender_email, "recipient@example.com", msg.as_string())
    print(f"Email sent successfully. Status code: {status}")

    server.quit()

except Exception as e:
    print(f"An error occurred: {e}")

Best Practices for Robust Email Sending

  1. Security First: Never hardcode passwords or sensitive keys directly into your script. Use environment variables (as shown above) to manage credentials securely.
  2. Encoding: Always ensure your content is properly encoded (usually UTF-8). The email module handles much of this, but being aware of character sets is crucial for international compatibility.
  3. External Services: For high-volume or enterprise applications, consider using specialized email delivery platforms like SendGrid, Mailgun, or Amazon SES. These services handle the complex deliverability issues that come with sending emails over SMTP and often provide better analytics and security features than direct SMTP connections.

Conclusion

Sending HTML emails in Python is fundamentally about understanding data structuring—specifically MIME—rather than just string manipulation. By leveraging the email module, developers can build robust communication pipelines. As you build complex applications, remember that reliable data transmission requires attention to detail at every layer, a principle that aligns with the structured thinking emphasized in modern development ecosystems, similar to how well-architected systems are approached within frameworks like Laravel. Mastering these underlying protocols allows you to move beyond simple text and deliver rich, professional communications.

Note: Blog content is currently available in English.

Tags:

Enhance your marketing setup with your own email marketing platform.

Join the growing number of SaaS platforms using Laravel Mail to offer email marketing solutions to their customers.