placing a list of variables in one line of html - newbie!


7 posts
by depauw » Mon Jun 19, 2017 3:08 pm
Hello,
I'm struggling with this:
I'm writing a script that looks at the image (jpg) files in a directory.
Then it should add those images to an email....

so far, I have some code (see below) for 2 images, or 3 or 5 or 10 if you want, but it's manually done and I don't always know how many files there will be in the directory

Code: Select all
path = "I:/raspberry/scripts python/email templates/images/"
image1 = 'foto_1.jpg'
image2 = 'foto_2.jpg'
image_name1 = path + image1
image_name2 = path + image2

# This example assumes the image1 is in the directory 'path'
fp = open(image_name1, 'rb')
msgImage = MIMEImage(fp.read(), _subtype='jpg')

# Define the image1's ID as referenced below
msgImage.add_header('Content-ID', '<' + image1 + '>')
msgRoot.attach(msgImage)

# This example assumes the image2 is in the directory 'path'
fp = open(image_name2, 'rb')
msgImage = MIMEImage(fp.read(), _subtype='jpg')
fp.close()

# Define the image2's ID as referenced below
msgImage.add_header('Content-ID', '<' + image2 + '>')
msgRoot.attach(msgImage)

# We reference the image in the IMG SRC attribute by the ID we gave it above
msgText = MIMEText('<b>Some <i>HTML</i> text</b> and an image.<br><img src="cid:' + image1 + '"><br><img src="cid:' + image2 + '"><br>Nifty!', 'html')
msgAlternative.attach(msgText)


My challenge is: let's say there are 5 files: how do I get the 5 variables (image1 to image5) into the line [codemsgText = MIMEText('<b>Some <i>HTML</i> text</b> and an image.<br><img src="cid:' + image1 + '"><br><img src="cid:' + image2 + '"><br>Nifty!', 'html')][/code]

I thnk I have to somehow go over names of the files in the directory and assign those to image_name1, image_name2 ,.....
I also think it has something to do with lists, but I'm not sure how to handle this to place the image_name variables in the one line of code.
I'm learning by try and error, assisted by Google and.... you guys from the forum!!

kind regards,
Christophe
Posts: 42
Joined: Mon Nov 09, 2015 2:12 pm
by davef21370 » Mon Jun 19, 2017 4:24 pm
Have a look at lists.
Code: Select all
imageList = ["image_1.jpg", "image_2.jpg", etc...]
then access each image(or path to the file or whatever)
Code: Select all
print imageList[0]
print imageList[1]

or

for img in imageList:
    print img
That's the general idea. Also a list object has functions like append, pop, shuffle which may come in useful. Do a little googling.

Dave.
I'll only give pointers... not full code.
User avatar
Posts: 850
Joined: Fri Sep 21, 2012 4:13 pm
Location: Earth But Not Grounded
by scotty101 » Mon Jun 19, 2017 4:28 pm
Some more code that might help. Untested as I haven't got anything to send the messages to. (I've never dealt with MIME before)
This should find all .jpg images in a folder and attach them to a MIME email. Also creates some body text that contains the HTML for each image.

Code: Select all
from email.mime.image import MIMEImage
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

import os

path = "I:/raspberry/scripts python/email templates/images/"
#Grab all the images (files that have .jpg as file extension)
images = [f for f in os.listdir(path) if f.endswith('.jpg')]
print(images)

#Create container email with a dummy subject
msg = MIMEMultipart()
msg['Subject'] = 'Test'

#Create a blank string to contain the text of our email
email_body = ""

#Step through each of the images
for img in images:
    image_path = os.path.join(path,img)
    #Open the image, read it and add a header
    with open(image_path,'rb') as fp:
        imgObj = MIMEImage(fp.read())
        imgObj.add_header('Content-ID', '<{}>'.format(img))
    #attach the email to the message
    msg.attach(imgObj)
    #Add the html for the current image to the text
    email_body += '<img src="cid:{}"><br>'.format(img)
   
#Create the email text and add it to the message
msgText = MIMEText(email_body)
msg.attach(msgText)




The official python examples are similar to what you are looking for
https://docs.python.org/3/library/email-examples.html
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter
Posts: 2138
Joined: Fri Jun 08, 2012 6:03 pm
by depauw » Wed Jun 21, 2017 10:08 pm
I've been working with the suggestions given by scotty101 and incorporated it in my code.
Code: Select all
# Send an HTML email with an embedded image and a plain text message for
# email clients that don't want to display the HTML.
import os
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage

path = "I:/raspberry/scripts python/email templates/images/"
#Grab all the images (files that have .jpg as file extension)
images = [f for f in os.listdir(path) if f.endswith('.JPG')]
print(images)

# Define these once; use them twice!
strFrom = 'from@apotheekdepauw.be'
strTo = 'to@apotheekdepauw.be'

# Create the root message and fill in the from, to, and subject headers
msgRoot = MIMEMultipart('related')
msgRoot['Subject'] = 'test message imageembedmailalt2.py'
msgRoot['From'] = strFrom
msgRoot['To'] = strTo
msgRoot.preamble = 'This is a multi-part message in MIME format.'

# Encapsulate the plain and HTML versions of the message body in an
# 'alternative' part, so message agents can decide which they want to display.
msgAlternative = MIMEMultipart('alternative')
msgRoot.attach(msgAlternative)

msgText = MIMEText('This is the alternative plain text message.')
msgAlternative.attach(msgText)


for img in images:
   image_path = os.path.join(path,img)
   # Open the image, read it and add a header
   with open(image_path, 'rb') as fp:
      msgImage = MIMEImage(fp.read(), _subtype='jpg')
      msgImage.add_header('Content-ID', '<{}>').format(img)
   msgRoot.attach(msgImage)
   email_body += '<img src="cid:{}"><br>'.format(img)

msgText = MIMEText(email_body)
msgAlternative.attach(msgText)

# Send the email (this example assumes SMTP authentication is required)
import smtplib

# Enter your smtp Server-Connection
server = smtplib.SMTP('server', port)
#if your using gmail: smtp.gmail.com
server.ehlo()
server.starttls()
server.ehlo
# Login
server.login("login", "password")

try:
   server.sendmail(strFrom, strTo, msgRoot.as_string())
   server.quit()
   print ("success")
except Exception:
   print ("failed")


Running it gives this error:
Traceback (most recent call last):
File "I:/raspberry/scripts python/email templates/imageembedmailalt2.py", line 56, in <module>
msgImage.add_header('Content-ID', '<{}>').format(img)
AttributeError: 'NoneType' object has no attribute 'format'


Any suggestions on this?

much appreciated!
Christophe
Posts: 42
Joined: Mon Nov 09, 2015 2:12 pm
by DirkS » Wed Jun 21, 2017 10:18 pm
Compare location of parentheses in
Code: Select all
msgImage.add_header('Content-ID', '<{}>').format(img)
with the code scotty101 posted:
Code: Select all
imgObj.add_header('Content-ID', '<{}>'.format(img))
Posts: 6924
Joined: Tue Jun 19, 2012 9:46 pm
Location: Essex, UK
by scotty101 » Thu Jun 22, 2017 8:53 am
^ What he said!
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter
Posts: 2138
Joined: Fri Jun 08, 2012 6:03 pm
by depauw » Thu Jun 22, 2017 2:49 pm
Yes, coding at night in this warm weather makes curly brackets, indentations, etc dance before my eyes :)
Made the change and I also forgot the lin to declare the variable email_body. So fixed that to!
Made a last adjustment to the line
Code: Select all
msgText = MIMEText(email_body)

I changed it to this: [codemsgText = MIMEText('<b>Some <i>HTML</i> text</b> and an image.<br>'+ email_body + '<br>Cool!', 'html')][/code]

And now the images come ferdectly inline in the email body text.

This is the finished code. Feel free to use it!
Code: Select all
# Send an HTML email with an embedded image and a plain text message for
# email clients that don't want to display the HTML.
import os
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage

path = "I:/raspberry/scripts python/email templates/images/"
#Grab all the images (files that have .jpg as file extension)
images = [f for f in os.listdir(path) if f.endswith('.JPG')]
print(images)

# Define these once; use them twice!
strFrom = 'from@apotheekdepauw.be'
strTo = 'to@apotheekdepauw.be'

# Create the root message and fill in the from, to, and subject headers
msgRoot = MIMEMultipart('related')
msgRoot['Subject'] = 'test message imageembedmailalt2.py'
msgRoot['From'] = strFrom
msgRoot['To'] = strTo
msgRoot.preamble = 'This is a multi-part message in MIME format.'

# Encapsulate the plain and HTML versions of the message body in an
# 'alternative' part, so message agents can decide which they want to display.
msgAlternative = MIMEMultipart('alternative')
msgRoot.attach(msgAlternative)

msgText = MIMEText('This is the alternative plain text message.')
msgAlternative.attach(msgText)

#Create a blank string to contain the text of our email
email_body = ""

for img in images:
   image_path = os.path.join(path,img)
   # Open the image, read it and add a header
   with open(image_path, 'rb') as fp:
      msgImage = MIMEImage(fp.read(), _subtype='jpg')
      msgImage.add_header('Content-ID', '<{}>'.format(img))
   msgRoot.attach(msgImage)
   email_body += '<img src="cid:{}"><br>'.format(img)

msgText = MIMEText(email_body)
msgAlternative.attach(msgText)

# Send the email (this example assumes SMTP authentication is required)
import smtplib

# Enter your smtp Server-Connection
server = smtplib.SMTP('server', port)
#if your using gmail: smtp.gmail.com
server.ehlo()
server.starttls()
server.ehlo
# Login
server.login("login", "password")

try:
   server.sendmail(strFrom, strTo, msgRoot.as_string())
   server.quit()
   print ("success")
except Exception:
   print ("failed")


a big shoutout to davef21370, scotty101 and DirkS for helping me out and a nice learning experience!!!
Posts: 42
Joined: Mon Nov 09, 2015 2:12 pm