Converting PIL image to MIMEImage

Question:

I’d like to create an image using PIL and be able to email it without having to save it to disk.

This is what works, but involves saving to disk:

from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart

msg = MIMEMultipart()

im = Image.new("RGB", (200, 200))

with open("tempimg.jpg", "w") as f:
    im.save(f, "JPEG")

with open("tempimg.jpg", 'rb') as f:
    img = MIMEImage(f.read())

msg.attach(img)

Now I’d like to be able to do something like:

import StringIO

tempimg = StringIO.StringIO()
tempimg.write(im.tostring())
img = MIMEImage(tempimage.getvalue(), "JPG")
msg.attach(img)

, which doesn’t work. I’ve found some discussion in Spanish that looks like it addresses the same question, with no solution except a pointer at StringIO.

Asked By: user1103852

||

Answers:

im.tostring returns raw image data but you need to pass whole image file data to MIMEImage, so use StringIO module to save the image to memory and use that data:

from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from PIL import Image
import cStringIO

msg = MIMEMultipart()

im = Image.new("RGB", (200, 200))
memf = cStringIO.StringIO()
im.save(memf, "JPEG")
img = MIMEImage(memf.getvalue())

msg.attach(img)
Answered By: Anurag Uniyal

Since the cStringIO module used in the Anurag Uniyal’s answer has been removed in Python 3.0, here is a solution for Python 3.x:

To convert a given PIL image (here pil_image) to a MIMEImage, use the BytesIO module to save the PIL image to a byte buffer and use that to get a MIMEImage.

from email.mime.image import MIMEImage
from io import BytesIO
from PIL import Image

byte_buffer = BytesIO()
pil_image.save(byte_buffer, "PNG")
mime_image = MIMEImage(byte_buffer.getvalue())
Answered By: Korne127