How to send email with BytesIO attachment via SMTP in Python
This example details how to send an email in Python, with an attachment from a io.BytesIO
instance instead of reading the attachment from a file on the filesystem:
#!/usr/bin/env python3
__author__ = "Uli Köhler"
__license__ = "CC0 1.0 Universal (public domain)"
__version__ = "1.0"
import smtplib
import mimetypes
from io import BytesIO
from email.message import EmailMessage
# Create message and set text content
msg = EmailMessage()
msg['Subject'] = 'This email contains an attachment'
msg['From'] = '[email protected]'
msg['To'] = '[email protected]'
# Set text content
msg.set_content('Please see attached file')
def attach_bytesio_to_email(email, buf, filename):
"""Attach a file identified by filename, to an email message"""
# Reset read position & extract data
buf.seek(0)
binary_data = buf.read()
# Guess MIME type or use 'application/octet-stream'
maintype, _, subtype = (mimetypes.guess_type(filename)[0] or 'application/octet-stream').partition("/")
# Add as attachment
email.add_attachment(binary_data, maintype=maintype, subtype=subtype, filename=filename)
# Attach files
buf = BytesIO()
buf.write(b"This is a test text")
attach_bytesio_to_email(msg, buf, "test.txt")
def send_mail_smtp(mail, host, username, password):
s = smtplib.SMTP(host)
s.starttls()
s.login(username, password)
s.send_message(msg)
s.quit()
send_mail_smtp(msg, 'smtp.my-domain.com', '[email protected]', 'sae7ooka0S')
The script from above is using the following utility functions:
def attach_bytesio_to_email(email, buf, filename):
"""Attach a file identified by filename, to an email message"""
# Reset read position & extract data
buf.seek(0)
binary_data = buf.read()
# Guess MIME type or use 'application/octet-stream'
maintype, _, subtype = (mimetypes.guess_type(filename)[0] or 'application/octet-stream').partition("/")
# Add as attachment
email.add_attachment(binary_data, maintype=maintype, subtype=subtype, filename=filename
def send_mail_smtp(mail, host, username, password):
s = smtplib.SMTP(host)
s.starttls()
s.login(username, password)
s.send_message(msg)
s.quit()
which you can use in your code directly. The easiest way to initialize the email message is using
# Create message and set text content
msg = EmailMessage()
msg['Subject'] = 'This email contains an attachment'
msg['From'] = '[email protected]'
msg['To'] = '[email protected]'
# Set text content
msg.set_content('Please see attached file')
and then attaching your BytesIO
instance (named buf
) using
attach_bytesio_to_email(msg, buf, "test.txt")
and once you’re finished with adding attachments, sending the message using
send_mail_smtp(msg, 'smtp.my-domain.com', '[email protected]', 'sae7ooka0S')