0

I am writing code in python to send email. I use smtplib and mime for sending email and formatting the content. I convert the word document to HTML to use as content. The following mail was send with the text, but the image wasn't processed in mail. Do you have any recommendation. I have tried to embed the image into the html also but it does not work.

import os
from docx import Document
import re
import smtplib
from email.message import EmailMessage
from docxtpl import DocxTemplate
import pyperclip
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from bs4 import BeautifulSoup
from string import Template
from email.mime.application import MIMEApplication
import glob
from email.mime.image import MIMEImage
from jinja2 import Template


with open('welcome_message.htm') as f:
    a=f.read()
soup=BeautifulSoup(a, 'lxml')
for div in soup.find_all('p', {'class':'delete'}):
    div.decompose()
with open('Aloitusmateriaalit.zip', 'rb') as f:
    part=MIMEApplication(f.read())
part['subject']='attachement'
part.add_header('Content-Disposition', 'attachment', filename=os.path.basename('Aloitusmateriaalit.zip'))
msg.attach(part)

word=['$PERSON_NAME','$FIRST_DATE','$ADDRESS','$PEER_ADVISOR','$SUPERVISOR']
target=soup.find_all(text=re.compile('|'.join(map(re.escape,word))))
for v in target:
    v.replace_with(v.replace('$PERSON_NAME', 'Duyen').
                   replace('$FIRST_DATE', 'Duyen').replace('$ADDRESS', 'Duyen'))
 = main.render(pictures=list_of_images)
part1=MIMEText(soup, 'html')
msg.attach(part1)
msg.add_header('Content-Disposition', 'attachment', filename='data.XLSX')
msg['Subject'] ='test email'
smtpObj = smtplib.SMTP('')
smtpObj.ehlo()
smtpObj.starttls()
smtpObj.login('xxxxx', 'xxxxx')
smtpObj.sendmail('xxxxx', 'xxxx', msg.as_string())
smtpObj.quit()

and the word document look something like this https://1drv.ms/w/s!Anyt3NEJ2JjqgeJtFMRGug96QkYFqA (i have deleted the content but it is not important) because the important is that the image does not show up. I save the docx as htm (welcome_message.htm) and then run the code

2 Answers2

1

I have figured out how to deal with it. It turned out we need to attach the picture with the email and then change the scr in the html with the name of the picture.

import os
from docx import Document
import re
import smtplib
from email.message import EmailMessage
from docxtpl import DocxTemplate
import pyperclip
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from bs4 import BeautifulSoup
from string import Template
from email.mime.application import MIMEApplication
import glob
from email.mime.image import MIMEImage
from jinja2 import Template

list_of_images = glob('*.png')
msg = MIMEMultipart()
for filename in list_of_images:
    fp = open(filename, 'rb')
    msg_img = MIMEImage(fp.read())
    fp.close()
    msg_img.add_header('Content-ID', '<{}>'.format(filename))
    msg_img.add_header('Content-Disposition', 'inline', filename=filename)
    msg.attach(msg_img)

with open('welcome_message.htm') as f:
    a=f.read()
soup=BeautifulSoup(a, 'lxml')
count=-1
for img in soup.findAll('img'):
    count+=1
    img['src'] = 'cid:' + os.path.basename(list_of_images[count])

for div in soup.find_all('p', {'class':'delete'}):
    div.decompose()
with open('Aloitusmateriaalit.zip', 'rb') as f:
    part=MIMEApplication(f.read())
part['subject']='attachement'
part.add_header('Content-Disposition', 'attachment', filename=os.path.basename('Aloitusmateriaalit.zip'))
msg.attach(part)
-1

Posting your code will be very helpful to us.

HTML: is a standard commonly used to send emails that have rich text formatting, graphics, and more.

MIME: is an internet standard that extends the format of email messages to support things like non-ASCII character sets, multi-part messages, and attachments like audio, video, and images.

"Servers insert the MIME header at the beginning of any Web transmission. Clients use this content type or media type header to select an appropriate viewer application for the type of data the header indicates. Some of these viewers are built into the Web client or browser (for example, almost all browsers come with GIF and JPEG image viewers as well as the ability to handle HTML files)." - Wikipedia, 2018 (Accessed Feb, 2).

What if the web client/browser does not have the ability to handle e.g. an image file? The receiver probably only accepts plain text messages!

To solve this we use MIME multipart messages. So you need to understand how to use the MIME structure correctly. By constructing a root email message that has two parts (i.e its a multipart message) we can allow the web client or browser to choose which one of those parts it wants to display.

We will use the MIME standard to attach these parts to the root. And we will also attach message content to each of those two parts. Followed by dealing with loading/finding the referenced image by ID. Then we have to send the message.

Let us create to MIME parts. Let one of those two parts be the nicer HTML message containing the embedded image and other content, and let the other part be just a plain text message.

For the plain text component of our root email message we will have to attach:

myPlainVar = MIMEText('plain text here')

Then for fancier HTML component of our root email we will again attach

myHTMLVar = MIMEText('<b>My <i>HTML </i>stuff</b><br><img src="cid:embeddedImage">', 'html')

Note that this time it includes the HTML scripting tags and your image. You will need code to open the image file from your directory using pythons open() and MIME's MIMEImage().

You also need to define the embedded image according to the content ID you assigned to it, in your HTML tag using .add_header('Content-ID', '<embeddedImage>').

The last step is to send the email message.

See this recipe, and this question. Good luck.

student23
  • 40
  • 5