skip to Main Content

How can I horizontally align and display two images side-by-side using Python and HTML in an email? I’ve tried adding the images using HTML code, but they’re currently being displayed vertically instead of horizontally. I’m not sure what I’m doing wrong, and I’ve already tried a few different approaches, but none of them seem to be working. Can someone help me modify my code to display the images responsively, side by side? It seems that changes need to be made to the current below HTML code. Full code also below.

html_text = body + '<html><body><br>'
    for i, image in enumerate(images):
        html_text = body + '<html><body><br><table border="0" cellspacing="0" cellpadding="0">'
        number_of_columns = 2 # set the number of columns here
        number_of_rows = (len(images) + number_of_columns - 1) // number_of_columns
        for row in range(number_of_rows):
            html_text += "<tr>"
            for col in range(number_of_columns):
                i = row * number_of_columns + col
                if i >= len(images):
                    break
                base = os.path.basename(images[i])
                image_without_extension = os.path.splitext(base)[0]
                html_text += "<td style='vertical-align: top;'>" + image_without_extension + ":<br><img src='cid:image{}' width='100' height='100'></td>".format(i)
                html_text += "</tr>"
        html_text += """</table><br><br>
                    Best,
                    <br>
                    XYZ
                    <br>
                    Note: XYZ</body></html>"""
    text = MIMEText(html_text, 'html')
    msg.attach(text)
import os
import base64
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
import smtplib
from pretty_html_table import build_table
from mimetypes import guess_type
import os
from email.message import EmailMessage
from smtplib import SMTP_SSL
import json
import argparse
import time
import pyodbc
import pandas as pd
import warnings
warnings.filterwarnings("ignore")

def send_email_with_images(images):
    # Define the email details
    to = '[email protected]'
    sender = '[email protected]'
    subject = 'Example Email with Multiple Inline Images'

    # Create the multipart message
    msg = MIMEMultipart()
    msg['From'] = sender
    msg['To'] = to
    msg['Subject'] = subject
    
    df = pd.read_csv('path/to/csv/file1.csv')
    df2 = pd.read_csv('path/to/csv/file2.csv')
    df3 = pd.read_csv('path/to/csv/file3.csv')

    # Create the HTML text
    name = "All"
    body = """
            <html>
            <head>
            </head>

            <body>
            Hi {3},

            <br><br>

            Please find below the report

            <br><br>

                    File1:
                    {0}
                    <br>
                    File2:
                    {1}
                    <br>
                    File3:
                    {2} 
                    
            <br><br>
            """.format(build_table(df, "blue_light", width="auto", font_family="Open Sans", font_size="13px", text_align="justify",), build_table(df2, "blue_light", width="auto", font_family="Open Sans", font_size="13px", text_align="justify",), build_table(df3, "blue_light", width="auto", font_family="Open Sans", font_size="13px", text_align="justify",), name)
    html_text = body + '<html><body><br>'
    for i, image in enumerate(images):
        html_text = body + '<html><body><br><table border="0" cellspacing="0" cellpadding="0">'
        number_of_columns = 2 # set the number of columns here
        number_of_rows = (len(images) + number_of_columns - 1) // number_of_columns
        for row in range(number_of_rows):
            html_text += "<tr>"
            for col in range(number_of_columns):
                i = row * number_of_columns + col
                if i >= len(images):
                    break
                base = os.path.basename(images[i])
                image_without_extension = os.path.splitext(base)[0]
                html_text += "<td style='vertical-align: top;'>" + image_without_extension + ":<br><img src='cid:image{}' width='100' height='100'></td>".format(i)
                html_text += "</tr>"
        html_text += """</table><br><br>
                    Best,
                    <br>
                    XYZ
                    <br>
                    Note: XYZ</body></html>"""
    text = MIMEText(html_text, 'html')
    msg.attach(text)
    
     # Add each image to the message
    for i, image in enumerate(images):
        with open(image, 'rb') as f:
            img_data = f.read()
        encoded_data = base64.b64encode(img_data).decode()
        mime_image = MIMEImage(img_data)
        mime_image.add_header('Content-ID', '<image{}>'.format(i))
        msg.attach(mime_image)

    # Send the email
    smtp = smtplib.SMTP('smtp.gmail.com', 587)
    smtp.starttls()
    smtp.login(sender, 'XYZ')
    smtp.sendmail(sender, [to], msg.as_string())
    smtp.quit()

# Example usage
send_email_with_images([r'FILE1.jpg', r'FILE2.jpg'])

3

Answers


  1. You can put each image inside a div element, and both div elements inside a parent div:

    def send_email_with_images(paths_list):
        #do stuff
        html_text = '<div>' 
            f'<div style="width:50%; float:left;"><img style="width:100%;" src={paths_list[0]}></div>' 
            f'<div style="width:50%; float:left;;"><img style="width:100%;" src={paths_list[1]}></div>' 
            '</div>' 
    
        # do stuff
    
    Login or Signup to reply.
  2. The output of your loop appears to be

    <tr>
      <td> (image1) </td>
    </tr>
    <tr>
      <td> (image2) </td>
    </tr>
    

    Instead of placing the images in separate rows, you want them as adjacent cells in the same row:

    <tr>
      <td> (image1) </td><td> (image2) </td>
    </tr>
    

    You will still need to respect the width of the email (usually set by a parent table with fixed width, and there are still very many things which can mess up your layout (image dimensions, table/td element properties), but this will set you on the right track 🙂

    Login or Signup to reply.
  3. seems like you need a shift + tab @

    html_text += "</tr>"
    

    as this is breaking the line in your for loop

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search