2026-07-15

add excel file attachment when sending python email

Stefan Bogdanescu

Stefan Bogdanescu

Founder & Senior Architect

add excel file attachment when sending python email

Attaching Excel Files to Python Emails: A Developer's Guide

Sending emails programmatically is a common task in backend development, and while sending simple text messages is straightforward using libraries like Python’s smtplib, adding file attachments introduces a layer of complexity. You are correct that the basic server.sendmail() function, when used with plain text, handles the body well, but it doesn't inherently know how to attach binary files like Excel documents directly from your local filesystem.

As a senior developer, I can tell you that this requires moving beyond simple string manipulation and diving into the world of MIME (Multipurpose Internet Mail Extensions) formatting. We need to encode the file content so it can be safely transmitted as ASCII text within the email protocol.

Here is a comprehensive guide on how to attach an Excel file to your Python email, complete with a practical example.


The Challenge of File Attachments in Email

When sending an email via SMTP, you are essentially transmitting data formatted according to RFC standards. A standard email consists of headers (To, From, Subject) and the body. To include a file, you must package that file's binary content into a format the recipient can decode. The most common method for this is Base64 encoding.

Base64 converts binary data (like the bytes of an Excel file) into a sequence of printable ASCII characters. This allows the file content to be safely embedded within the email message body, making it readable by various email clients.

Step-by-Step Implementation with Python

To successfully attach a file, you need three main steps: reading the file, encoding the data, and constructing the full MIME message structure.

Step 1: Read and Encode the File Content

We must open the Excel file in binary read mode ('rb') and then encode its content into Base64.

import base64

file_path = 'your_document.xlsx'

try:
    with open(file_path, 'rb') as file:
        # Read the file content in binary mode
        file_content = file.read()
        # Encode the binary content to Base64
        encoded_content = base64.b64encode(file_content).decode('utf-8')
except FileNotFoundError:
    print(f"Error: File not found at {file_path}")
    exit()

# The encoded string is what we will attach later
attachment_data = encoded_content

Step 2: Construct the MIME Message

Instead of using server.sendmail() with a simple text body, we need to construct a full MIME message that includes both the text content and the attachment part. This involves setting specific headers for the attachment type (Content-Type).

For simplicity in this example, we will structure the email as a multipart message.

Step 3: Sending the Email with Attachment

The final step is to format the entire payload—the headers, the body, and the encoded attachment—into a single string that sendmail can process.

Here is how you integrate this into your existing script:

import smtplib
import base64
import os

# --- Configuration ---
TO = 'xxxx@gmail.com'
SUBJECT = 'Email with Excel Attachment'
TEXT_BODY = 'Please find the attached monthly report.'
FILE_PATH = 'report.xlsx' # Make sure this file exists!

# --- 1. Prepare the Attachment ---
try:
    with open(FILE_PATH, 'rb') as file:
        file_content = file.read()
        encoded_data = base64.b64encode(file_content).decode('utf-8')
except FileNotFoundError:
    print(f"Error: Attachment file '{FILE_PATH}' not found.")
    exit()

# --- 2. Construct the MIME Message ---
# Note: The format below is a simplified representation for demonstration.
# In production, you might use dedicated email libraries for complex MIME handling.
body = f"Here is the message:\n{TEXT_BODY}\n\n--- Attachment Details ---\nFile Name: {os.path.basename(FILE_PATH)}\nContent (Base64 Encoded): {encoded_data}"

message = f"""From: {gmail_sender}
To: {TO}
Subject: {SUBJECT}
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="----boundary"

----boundary
Content-Type: text/plain; charset="UTF-8"

{TEXT_BODY}

----boundary
Content-Type: application/octet-stream; name="{os.path.basename(FILE_PATH)}"
Content-Transfer-Encoding: base64

{encoded_data}

----boundary--"""


# --- 3. Send the Email ---
try:
    server = smtplib.SMTP('smtp.gmail.com',587)
    server.starttls()
    server.login(gmail_sender, gmail_passwd)
    
    # Use sendmail with the fully constructed MIME message
    server.sendmail(gmail_sender, [TO], message)
    print('Email sent successfully with attachment.')

except Exception as e:
    print(f'Error sending mail: {e}')
finally:
    server.quit()

Best Practices and Advanced Considerations

While the method above works by manually constructing a multipart message, for complex applications, relying on established libraries is always safer and more robust. If you are building large-scale communication systems, look into frameworks that handle these complexities gracefully. For instance, when designing data pipelines or application structures, understanding how modern frameworks organize data, much like how a system like Laravel organizes routes and controllers, helps in managing complex payloads efficiently.

Security Note: Never hardcode sensitive credentials (like gmail_passwd) directly into your script. Use environment variables to manage secrets securely. Furthermore, for production systems, consider using established email APIs (like SendGrid or Mailgun) instead of direct SMTP connections, as they handle deliverability, security, and attachment complexities far better than raw smtplib.

Conclusion

Attaching files to emails in Python requires understanding the underlying principles of MIME formatting. By reading your file in binary mode, using Base64 encoding to safely transport the bytes, and meticulously structuring the message with appropriate multipart boundaries, you can successfully send rich, attached emails. While manual construction is educational, always prioritize using robust libraries when building production systems.

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.