2026-07-15

Python how do i send multiple files in the email. I can send 1 file but how to send more than 1

Stefan Bogdanescu

Stefan Bogdanescu

Founder & Senior Architect

Python how do i send multiple files in the email. I can send 1 file but how to send more than 1

Python: How to Send Multiple Files in an Email – A Developer's Guide

Sending emails is a fundamental task in almost every application, and while sending a single text or HTML report is straightforward, handling multiple file attachments requires understanding the underlying structure of email protocols. As developers, we often deal with complex data serialization; the principle remains the same—we need to correctly package our data into a format the recipient system understands.

If you are familiar with using Python's built-in smtplib, you know that sending an email is essentially handing off a message structure over an SMTP server. The challenge when adding files is moving beyond simple text (MIMEText) to constructing a multipart MIME message that correctly encodes the binary file data alongside the textual content.

This guide will walk you through the correct, practical way to attach multiple files to an email in Python, building upon your existing knowledge of sending a single HTML report.

Understanding Email Attachments: The Role of MIME

Email messages are structured using the MIME (Multipurpose Internet Mail Extensions) standard. When you send an email with attachments, you are creating a "multipart" message—a container that holds different parts (the body text, headers, and the files themselves).

When sending files via SMTP, you don't just send plain text; you must encode the file content as binary data and attach it using specific MIME headers. In Python, this is handled by reading the file in binary mode ('rb') and attaching that stream to the message object correctly.

Implementing Multiple File Attachments in Python

To successfully send multiple files, we need to modify our approach from simply creating MIMEText to properly constructing a combined message where each file is treated as a separate attachment part. We will use the email package—specifically classes like MIMEMultipart and MIMEBase—to handle this complexity gracefully.

In the example below, we will read three separate HTML files and attach them to the email.

import smtplib
from email import msg, Message
from email import policy
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
import os

# --- Configuration (Replace with your actual settings) ---
SMTP_SERVER = "smtp.example.com"  # e.g., smtp.gmail.com
SMTP_PORT = 587
SENDER = "system@company.com"
RECIPIENT = "4_server_dev@company.com"

# Define the files to send
files_to_send = [
    r"G:\test_runners\selenium_regression_test_5_1_1\TestReport\SeleniumTestReport_part1.html",
    r"G:\test_runners\selenium_regression_test_5_1_1\TestReport\SeleniumTestReport_part2.html",
    r"G:\test_runners\selenium_regression_test_5_1_1\TestReport\SeleniumTestReport_part3.html"
]

def send_multiple_reports():
    # 1. Create the main container message
    msg = MIMEMultipart()
    msg['From'] = SENDER
    msg['To'] = RECIPIENT
    msg['Subject'] = "Selenium ClearCore_Regression_Test_Report_Results"

    # 2. Attach the text body (optional, but good practice)
    body = "Please find the attached Selenium test reports for review."
    msg.attach(MIMEText(body, "plain"))

    # 3. Attach each file individually
    for file_path in files_to_send:
        try:
            # Open the file in binary read mode ('rb')
            with open(file_path, "rb") as f:
                # Use MIMEBase to create a MIME attachment object
                part = MIMEBase('application', 'octet-stream')
                part.set_payload(f.read())

            # Encode the file content to base64 for safe transmission
            with open(file_path, "rb") as f:
                encoded_file = f.read()
            
            part.add_header('Content-Disposition', f'attachment; filename="{os.path.basename(file_path)}"')
            
            # Attach the file part to the main message
            msg.attach(part)
            print(f"Successfully attached: {os.path.basename(file_path)}")

        except FileNotFoundError:
            print(f"Error: File not found at {file_path}")
        except Exception as e:
            print(f"An error occurred while processing {file_path}: {e}")


    # 4. Send the email via SMTP
    try:
        print("\nConnecting to server...")
        s = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
        s.starttls()  # Secure the connection
        # NOTE: You would typically log in here if authentication is required (s.login(user, password))
        s.sendmail(SENDER, RECIPIENT, msg.as_string())
        s.quit()
        print("\nEmail sent successfully!")
    except Exception as e:
        print(f"\nFailed to send email. Error: {e}")

if __name__ == "__main__":
    send_multiple_reports()

Best Practices for Robust File Sending

When dealing with file attachments, robustness is key. Here are a few best practices derived from experience in building reliable systems:

  1. Binary Mode is Non-Negotiable: Always open files in binary read mode ('rb') when reading content intended for MIME attachment. Attempting to read binary data as text will corrupt the file integrity.
  2. Use MIMEBase: Instead of trying to manually build complex headers, leveraging classes like MIMEBase allows Python’s email library to handle the complex Base64 encoding and header formatting automatically. This is crucial for ensuring compliance with email standards.
  3. Error Handling: As demonstrated above, wrap file operations and network communication in comprehensive try...except blocks. If one file fails to attach or the SMTP connection drops, you need to know exactly which step failed so you can debug the issue without losing the entire process.
  4. Consider Alternatives for Large Files: For extremely large files (many megabytes), sending them directly via email attachments is often inefficient and unreliable. A better architectural pattern, especially when building larger enterprise systems that might interact with services like those offered by Laravel Company, is to upload the files to a cloud storage service (like S3) and send the recipient a single email containing links to those files instead of embedding the large payloads directly in the email body.

Conclusion

Sending multiple files in Python requires shifting your focus from simple text formatting to mastering the MIME structure. By utilizing the email package—specifically MIMEMultipart and MIMEBase—you can correctly serialize binary file data into a format that SMTP servers understand, allowing you to attach reports, documents, or any other files reliably. Mastering this is a step toward building robust applications where data transmission is handled with precision and integrity.

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.