Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 3 EmailMessage html message with Image

I am trying to get images shown as part of the mail sent with Python. There is a example on Python docs which is not working.

from datetime import datetime
import sys

import smtplib

from email.message import EmailMessage
from email.headerregistry import Address
from email.utils import make_msgid



from email.mime.image import MIMEImage

attachment = '/user/file/test.png'


import email.policy
msg = EmailMessage()
msg['To'] = Address("Srujan", '[email protected]')
msg['From'] = Address("Srujan", '[email protected]')
msg['Subject'] = "Nice message goes with it "+str(datetime.now())
id = make_msgid()
msg.set_type('text/html')
msg.set_content(" This is the Data Message that we want to send")
html_msg = "<br> <b><u> This is the Text .... </u></b><br> <img src='cid:{image_id}' />".format(image_id=id[1:-1])
msg.add_alternative(html_msg, subtype="html")
image_data = open(attachment, "rb")
image_mime = MIMEImage(image_data.read())
image_data.close()
msg.add_attachment(image_mime,   cid=id, filename = "myown.png" ,)


try:
    with smtplib.SMTP('example.com') as s:
        s.ehlo()
        s.starttls()
        s.ehlo()
        
        s.send_message(msg)
        s.close()
    print("Email sent!")
except:
    print("Unable to send the email. Error: ", sys.exc_info()[0])
    raise

I noticed that the last part is a message/rfc822, which then contains the image/png.

To: Srujan <"[email protected]"> From: Srujan
<"[email protected]"> Subject: Nice message goes with it 2016-01-21
17:39:23.642762 MIME-Version: 1.0 Content-Type: multipart/mixed;
boundary="===============3463325241650937591=="

--===============3463325241650937591==
Content-Type: multipart/alternative; boundary="===============0739224896516732414=="

--===============0739224896516732414==
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit

 This is the Data Message that we want to send

--===============0739224896516732414==
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: 7bit MIME-Version: 1.0

<br> <b><u> This is the Text .... </u></b><br> <img
src='cid:20160122013923.64205.76661' />

--===============0739224896516732414==--

--===============3463325241650937591==
Content-Type: message/rfc822
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="myown.png"
Content-ID: <20160122013923.64205.76661>
MIME-Version: 1.0

Content-Type: image/png
MIME-Version: 1.0
Content-Transfer-Encoding: base64

iVBORw0KGgoAAAANSUhEUgAAAyAAAAJYCAIAAAAVFBUnAAAABmJLR0QA/wD/AP+gvaeTAAAgAElE
QVR4nOzdd2BUVfYH8HNfmZJAChAEQ1FAqoKgCAsWLEgTG4gKP11FQNG1AauIgGBXVhRUsCK4i6gI

Now the attached message has two content-type values. Email comes with just text and with no image.

I have done it successfully with MultiPart class, but looking to achieve that with EmailMessage.

like image 970
SrujanSreepathi Avatar asked Jan 22 '16 01:01

SrujanSreepathi


People also ask

How do you insert an image in HTML using Python?

HTML Images SyntaxThe <img> tag creates a holding space for the referenced image. The <img> tag is empty, it contains attributes only, and does not have a closing tag. The <img> tag has two required attributes: src - Specifies the path to the image.

What is EmailMessage() in Python?

It is the base class for the email object model. EmailMessage provides the core functionality for setting and querying header fields, for accessing message bodies, and for creating or modifying structured messages. An email message consists of headers and a payload (which is also referred to as the content).

How do you put an image in the body of an email in Python?

will produce an email with empty body and the image as an attachment. The trick is to define an image with a specific Content-ID and make that the only item in an HTML body: now you have an email with contains that specific image as the only content of the body, embedded in it.

How do I use Smtplib in Python 3?

Python provides smtplib module, which defines an SMTP client session object that can be used to send mails to any Internet machine with an SMTP or ESMTP listener daemon. host − This is the host running your SMTP server. You can specifiy IP address of the host or a domain name like tutorialspoint.com.


1 Answers

It is really a pity that Python docs on this subject are incomplete/wrong. I wanted to do the same thing and got the same problem (attachments got two content-types)

Solved the problem by using the attach() method instead of add_attachment() on EmailMessage objects. The only caveat is that you have to transform the EmailMessage to multipart/mixed type before doing this. An example:

from smtplib import SMTP
from email.message import EmailMessage
from email.mime.text import MIMEText
from email.headerregistry import Address
from ssl import SSLContext, PROTOCOL_TLSv1_2

# Creating and populating email data:
msg = EmailMessage()
msg['From'] = Address(display_name='Recipient', addr_spec='[email protected]')
msg['To'] = Address(display_name='Sender', addr_spec='[email protected]')
msg['Subject'] = 'An email for you'    
msg.set_content('This should be in the email body')  
# It is possible to use msg.add_alternative() to add HTML content too  

# Attaching content:
att = MIMEText('This should be in an attached file') # Or use MIMEImage, etc
# The following line is to control the filename of the attached file
att.add_header('Content-Disposition', 'attachment', filename='attachment.txt')
msg.make_mixed() # This converts the message to multipart/mixed
msg.attach(att) # Don't forget to convert the message to multipart first!

# Sending the email:
with SMTP(host='smtp.example.org', port=587) as smtp_server:
    try:
        # You can choose SSL/TLS encryption protocol to use as shown
        # or just call starttls() without parameters
        smtp_server.starttls(context=SSLContext(PROTOCOL_TLSv1_2))
        smtp_server.login(user='[email protected]', password='password')
        smtp_server.send_message(msg)

    except Exception as e:                
        print('Error sending email. Details: {} - {}'.format(e.__class__, e))
like image 77
llekn Avatar answered Oct 05 '22 21:10

llekn