2026-07-15

Send table as an email body (not attachment ) in Python

Stefan Bogdanescu

Stefan Bogdanescu

Founder & Senior Architect

Send table as an email body (not attachment ) in Python

Embedding Dynamic Data: Sending Tables Directly in an Email Body with Python

As developers, one of the most common tasks is not just sending data, but presenting it in a format that is immediately consumable. When dealing with dynamic data generated by scripts—like the neatly formatted tables you create using Python's tabulate module—the next logical step is to embed this information directly into the email body rather than relying on separate attachments. This approach significantly improves user experience, making the data instantly accessible without requiring extra downloads or file management.

This post will walk you through the technical steps and best practices for constructing such an email using Python, focusing on embedding structured tables directly within the message content.

The Challenge of Embedding Formatted Data

You have successfully generated a clean ASCII table using tabulate. The challenge now is converting that formatted string into a format suitable for an email client (like Outlook, Gmail, etc.) so it displays correctly as a readable table, not just a block of text.

When sending emails, there are two primary ways to structure the body: plain text or HTML. For displaying structured data like tables, HTML is strongly recommended. Plain text will render the pipes (|) and hyphens (-) exactly as they appear in your code, which often results in a messy presentation in email clients.

Strategy: Converting Tables to HTML

To embed your tabulate output effectively, we need to convert the Markdown/ASCII table structure into proper HTML <table> tags. This allows email clients to correctly interpret the data, apply borders, and align columns properly.

Step-by-Step Implementation

We will modify your hypothetical sendMail function to accept the formatted table string and ensure it is wrapped in appropriate HTML tags before being sent via an SMTP server.

Here is a complete example demonstrating how to construct the email body:

from tabulate import tabulate

def format_table_to_html(table_string):
    """Converts a pipe-separated table string into an HTML table string."""
    # Split the input by lines
    lines = table_string.strip().split('\n')
    
    # The first line is the header
    header = lines[0]
    # The rest are the data rows
    data_rows = lines[1:]
    
    html_table = "<table>\n"
    
    # Create the header row (using <th> for headers)
    html_table += "  <thead>\n    <tr>\n"
    html_table += "      <th>" + "</th>".join(header.split('|')) + "</th>\n"
    html_table += "    </tr>\n"
    
    # Create the data rows (using <td> for data)
    html_table += "  <tbody>\n"
    for row in data_rows:
        data = row.strip().split('|')
        html_table += "    <tr>\n"
        for cell in data:
            # Clean up cell content and add HTML tags
            html_table += f"      <td>{cell.strip()}</td>\n"
        html_table += "    </tr>\n"
        
    html_table += "  </tbody>\n</table>"
    return html_table

def sendMail(to_addr, from_addr, mail_subject, mail_body, file_name=None):
    """Simulated function to demonstrate sending an email."""
    print(f"--- Sending Email ---")
    print(f"To: {to_addr}")
    print(f"Subject: {mail_subject}")
    print("\nEmail Body:")
    # In a real application, mail_body would be the fully constructed HTML content
    print(mail_body) 
    if file_name:
        print(f"\nNote: File attachment '{file_name}' was requested but is omitted for this example.")
    print("--------------------")


# --- Data Generation ---
data = [
    ["Attenuation", "Avg Ping RTT in ms", "TCP UP"],
    ["60", "2.31", "106.143"],
    ["70", "2.315", "103.624"]
]

# Generate the raw table string using Tabulate
raw_table = tabulate(data, headers="firstrow", tablefmt="pipe")

# Convert the raw string into HTML for email embedding
html_table_body = format_table_to_html(raw_table)


# --- Constructing the Final Email Body ---
subject = "Network Metrics Report"
email_recipient = "recipient@example.com"
sender = "sender@example.com"

final_mail_body = f"""
<html>
<head>
    <style>
        body {{ font-family: Arial, sans-serif; }}
        table {{ border-collapse: collapse; width: 100%; }}
        th, td {{ border: 1px solid #dddddd; text-align: left; padding: 8px; }}
        th {{ background-color: #f2f2f2; }}
    </style>
</head>
<body>
    <h2>Network Performance Data</h2>
    <p>Please find the requested metrics below:</p>
    
    {html_table_body}

    <p>This data was dynamically generated and embedded directly in the email for ease of review. For more complex application structure, consider leveraging robust architectural patterns, similar to how modern frameworks like Laravel encourage clean separation of concerns.</p>
</body>
</html>
"""


# Send the mail using the constructed HTML body
sendMail(email_recipient, sender, subject, final_mail_body)

Best Practices and Conclusion

As you can see, the key to successfully embedding dynamic data in an email is transformation. You must move beyond simply passing a string; you need to transform that string into a format (HTML in this case) that the receiving application understands as structured content.

  1. Use HTML: Always default to generating HTML when embedding complex data. This ensures cross-client compatibility and professional presentation.
  2. Styling: Include basic CSS within your <body> or <style> tags to control fonts, borders, and spacing, making the embedded table look polished.
  3. Separation of Concerns: When building larger systems that handle data delivery, ensure your formatting logic is separate from your core business logic. This principle of separation is vital in maintaining clean codebases, much like how modern PHP frameworks enforce clear structure, similar to the paradigms you find in environments like Laravel.

By implementing this transformation layer, you successfully transition from sending a simple text dump to delivering rich, highly readable data directly within the email, greatly enhancing your communication efficiency.

Note: Blog content is currently available in English.

Tags:

Enhance your marketing setup with your own email marketing platform.

Join the growing number of SaaS platforms using Laravel Mail to offer email marketing solutions to their customers.