2026-07-15

How to send email to multiple recipients using python smtplib?

Stefan Bogdanescu

Stefan Bogdanescu

Founder & Senior Architect

How to send email to multiple recipients using python smtplib?

How to Send Email to Multiple Recipients Using Python smtplib

Sending emails programmatically is a common requirement in building backend services, whether you are developing internal tools or customer-facing applications. While the Python standard library's smtplib module provides the necessary tools to communicate with SMTP servers, handling multiple recipients within a single message can often lead to confusion regarding how email headers and body content must be formatted.

Many developers run into issues where sending an email to several addresses results only the first recipient receiving the message, or the headers become corrupted. This usually stems from a mismatch between how the email package constructs the MIME structure and what the raw SMTP command expects for address lists.

This guide will walk you through the correct, robust way to send emails to multiple recipients using Python's smtplib, focusing on correctly structuring the message data.

Understanding the Email Structure Challenge

The core difficulty lies in bridging the gap between the structured object-oriented approach of the email module (like MIMEMultipart) and the raw string format required by the underlying SMTP protocol. When using methods like sendmail(), you are essentially sending a raw command to the mail server, which requires specific header formatting.

The confusion often arises because properties like "To" and "Cc" in an email message object expect a single address or a potentially complex list, but the final payload sent via sendmail needs a simple, comma-separated string of addresses directly following the sender information.

The Correct Approach: Formatting Headers for sendmail

The most reliable method involves constructing the full content (including headers and body) as a single, properly formatted string before sending it via smtp.sendmail(). We will use MIMEMultipart to build our message parts, but we must carefully manage how these details are extracted for the final command.

Here is a detailed example demonstrating how to handle multiple recipients correctly:

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib

def send_multi_recipient_email(smtp_server, port, sender_email, recipients, subject, body):
    # 1. Create the container message
    msg = MIMEMultipart()
    msg["From"] = sender_email
    msg["Subject"] = subject

    # 2. Handle multiple recipients by splitting the list into comma-separated strings
    # We combine 'To' and 'Cc' for simplicity in this example
    recipient_list = ", ".join(recipients)
    msg["To"] = recipient_list
    
    body_text = body
    msg.attach(MIMEText(body_text, "plain"))

    # 3. Prepare the headers and message content for sendmail()
    # The 'From' address is the sender. The addresses we want to reach are in the To field.
    # Note: We use msg.as_string() which formats the entire MIME structure correctly.
    
    # For raw SMTP sendmail, we often need specific header lines separated by newlines.
    # We will construct the full message content string here:
    
    full_message = f"From: {sender_email}\r\n"
    full_message += f"To: {recipient_list}\r\n"  # List all recipients in To field
    full_message += f"Subject: {subject}\r\n"
    full_message += "\r\n" # Blank line separates headers from the body
    full_message += body_text

    try:
        # Connect to the SMTP server
        smtp = smtplib.SMTP(smtp_server, port)
        smtp.ehlo()
        smtp.starttls()  # Secure the connection
        smtp.ehlo()
        
        # Send the raw message string
        smtp.sendmail(sender_email, [recipient_list], full_message)
        print("Email sent successfully to all recipients.")
        
    except Exception as e:
        print(f"An error occurred: {e}")
    finally:
        smtp.quit()

# Example Usage
SMTP_HOST = "mailhost.example.com"
SMTP_PORT = 25
SENDER = "me@example.com"
RECIPIENTS = ["malcom@example.com", "reynolds@example.com", "firefly@example.com"]
SUBJECT = "Multi-Recipient Test"
BODY = "This is the body of the email sent to multiple people."

send_multi_recipient_email(SMTP_HOST, SMTP_PORT, SENDER, RECIPIENTS, SUBJECT, BODY)

Best Practices and Context

Notice how we shifted from trying to pass fragmented lists directly into sendmail() to constructing a complete, newline-separated message string (full_message). This ensures that the server receives all necessary headers (From, To, Subject) clearly separated by line breaks before the main body content.

When developing complex services, like those built on frameworks where robust communication is paramount—think about the architecture behind tools like Laravel, which emphasizes clean service separation and reliable data handling—it is crucial to treat external protocols like SMTP with precision. Relying on raw string construction for sendmail ensures that regardless of how many recipients are involved, the email remains correctly parsed by the receiving mail server.

Conclusion

Sending emails to multiple recipients via Python’s smtplib requires a clear understanding of the distinction between object-oriented message building and raw protocol commands. By leveraging the email package to structure the content and then carefully assembling that content into a properly formatted string for the sendmail() function, you can reliably distribute messages to any number of addresses. Always prioritize clarity in your data formatting to ensure interoperability across different mail servers.

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.