How to send email attachments?
Stefan Bogdanescu
Founder & Senior Architect
How to Send Email Attachments in Python: A Complete Guide
As a developer, sending simple text emails using smtplib is straightforward. However, adding file attachments introduces a layer of complexity because emails are not just plain text; they follow strict standards defined by MIME (Multipurpose Internet Mail Extensions). This guide will walk you through the correct way to attach files to an email using Python, moving beyond basic message sending to handle binary data effectively.
If you are building robust applications—whether you are working with systems that interact with services similar to those found in frameworks like Laravel, where handling complex data payloads is critical—understanding these underlying protocols is essential for reliable communication.
The Challenge: Understanding the MIME Structure
When you send an email, it is fundamentally a structured message. To attach a file, you cannot simply append the file content to the message body. Instead, you must package the text and the file data together into a format that the recipient's mail client understands. This packaging is handled by MIME.
For attachments, we need to use Python’s built-in email package to construct a multipart message. A multipart message allows an email to contain different parts (like the main body text and one or more file attachments) separated by unique boundaries.
Step-by-Step Guide: Attaching Files with Python
To successfully send an attachment, you will utilize the MIMEMultipart class to create the container for your message and then use the MIMEApplication class to correctly encode the file data as an attachment part.
Here is a complete example demonstrating how to attach a local file to an email using Python:
import smtplib
from email importmime,mime.multipart
# --- Configuration ---
smtp_server = 'smtp.gmail.com' # Example: Use your actual SMTP server details
sender_email = 'your_email@example.com'
password = 'your_app_password' # Use environment variables for security!
receiver_email = 'recipient@example.com'
attachment_file = 'report.pdf' # The file you want to attach
# 1. Create the container for the email (MIMEMultipart)
msg = MIMEMultipart()
msg['From'] = sender_email
msg['To'] = receiver_email
msg['Subject'] = 'Email with PDF Attachment'
# 2. Separate the body and attach the file
body = "Please find the requested report attached below."
msg.attach(mime.MIMEText(body, 'plain'))
# 3. Attach the file
with open(attachment_file, "rb") as f:
# Use MIMEApplication to correctly set the content type and handle binary data
part = MIMEApplication(f.read(), 'application/pdf')
part.add_header('Content-Disposition', f'attachment; filename="{attachment_file}"')
msg.attach(part)
# 4. Send the email (using smtplib)
try:
server = smtplib.SMTP(smtp_server, 587)
server.starttls() # Secure the connection
server.login(sender_email, password)
text = msg.as_string()
server.sendmail(sender_email, receiver_email, text)
print("Successfully sent email with attachment!")
server.quit()
except Exception as e:
print(f"An error occurred: {e}")
Best Practices for Attachment Handling
When dealing with file attachments in production environments, keep these best practices in mind:
- Binary Mode (
'rb'): Always open the file in binary read mode ("rb") when reading files to ensure that the raw byte data is passed correctly to the email protocol. - Content-Disposition Header: The most crucial part for attachments is setting the
Content-Dispositionheader within your attachment part. Setting it toattachment; filename="..."tells the receiving mail client that this content should be downloaded as a file rather than displayed inline. - Security First: Never hardcode passwords directly into your script. Use environment variables or secure secret management systems to handle sensitive credentials, which is a fundamental principle in building secure backends, much like when designing complex data flows within a framework like Laravel.
Conclusion
Sending email attachments requires moving beyond simple string manipulation and embracing the structure of MIME. By correctly utilizing the MIMEMultipart and MIMEApplication classes in Python, you gain full control over how your files are packaged and delivered. Mastering this step is key to building reliable communication systems, whether you are automating tasks or developing complex backend services.