1

newbie to python. what I want is to go into a folder, grab the images and embed them in my email. But when I run the program wouldnt complete after 5 minutes even though i had limited to only 1 image to test. so I kept having to cancel. Any idea? Thanks.

Update: I fixed it by adding .as_string() to msg at the line smtp.sendmail(email_sender, email_receiver, msg)

Complete code:

from email.message import EmailMessage
from email.utils import make_msgid
import smtplib
import os
import ssl
import requests
import io
import time

start_time = time.time()

# Define these once; use them twice!
email_sender = '[email protected]'
email_receiver = '[email protected]'
email_password = 'aaaa aaaa aaaa aaaa'
subject = 'Test run HTML multiple images using URLs'

# use os to create list of image names and then join with raw folder path to get image location
folder_path = r'C:\Users\chris\OneDrive\My Computer\Reddit API\cats\images'
# create a dict called plots containing image name and file path
plots = {}
for file_name in os.listdir(folder_path)[:3]:
    file_path = os.path.join(folder_path, file_name)
    plots[file_name] = file_path
    print(f'{file_name}. {file_path}')

# empty list to host dict of each image info - name, content, type, content id
imgs = []
# generate name, the content and the id
for image_name, image_location in plots.items():
    with open(image_location, 'rb') as img:
        image_data = img.read()
        if image_name.endswith('png'):
            image_type = 'png'
        elif image_name.endswith('jpeg') or image_name.endswith('jpg'):
            image_type = 'jpg'
    imgs.append({
        "name": image_name,
        "data": image_data,
        "type": image_type,
        "cid": make_msgid().strip("<>")
    })

# create html content template for the subsequent msg base
# set up image placeholder using content id
# similar to how at reserved seats you have the person's name
# so later said person can just get directed there
html = """\
<html><head><title>Plots</title></head>
 <body>
  <h1>Your Plots</h1>
  <p>Dear Victim,</p>
  <p>Here are today's plots.
   <ul>
"""
for img in imgs:
    html += f'    <li><img src="cid:{img["cid"]}" style="max-width: 500px; height: auto;" alt="{img["name"]}" /></li>\n\n'
html += """\
   </ul>
  </p>
  <p>Plot to take over the world!</p>
 </body>
</html>
"""

print('\n\nhtml template:\n\n')
print(html)

# create an EmailMessage object to host necessary information
msg = EmailMessage()
msg['Subject'] = subject
msg['From'] = email_sender
msg['To'] = email_receiver

msg.set_content(html, subtype="html")

# add image content to the msg base at the image id placeholder
for img in imgs:
    msg.add_related(
        img["data"], "image", img['type'],
        cid=f'<{img["cid"]}>')

# send the email
# with smtplib.SMTP(host) as s:
#     s.send_message(msg)
context = ssl.create_default_context()
try:
    with smtplib.SMTP_SSL('smtp.gmail.com', 465, context = context) as smtp:
        smtp.login(email_sender, email_password)
        smtp.sendmail(email_sender, email_receiver, msg.as_string())
        print('Email sent successfully')
except Exception as e:
    print(f'Failed to send due to {e}')

end_time = time.time()

print(f'The script runs for {(end_time - start_time)/60} minutes.')
1
  • Lmao turns out that it was because I forgot to add .as_string() at the end of msg to smtp.sendmail(email_sender, email_receiver, msg) Commented Jul 6 at 2:01

0

Browse other questions tagged or ask your own question.