Sending data-driven reports via email is a common task for developers and data analysts. However, if you try to send an interactive Plotly graph inside a Python HTML email, you often end up with a blank email, broken layouts, or raw code appearing as plain text.
In this guide, you will learn why Plotly graphs fail to render in email clients and how to fix this issue using Python.
Why Plotly Graphs Don’t Render in HTML Emails
If you convert a Plotly chart to HTML using fig.to_html() and paste it into an email body, most email clients (like Gmail, Outlook, or Yahoo) will strip it out.
Here is why:
- No JavaScript Support: Plotly relies on plotly.js to provide interactive features (hover effects, zooming, panning). Email clients block external JavaScript execution for security reasons.
- Inline Script Stripping: Email engines automatically remove <script> tags, causing the graph container to render completely blank.
Solutions: How to Send Plotly Graphs via Email
To handle this, you can use two approaches depending on your requirements:
Method 1 (Recommended): Embed Plotly Graph Inline as Static Image
Convert the Plotly figure to a high-resolution static image (PNG/JPEG) and embed it directly inside the email body using CID (Content-ID).
Method 2: Attach Interactive HTML File + Display Summary Image
Attach the full interactive .html file as a downloadable attachment while embedding a preview PNG image in the email body.
Method 1: Embed Inline Image (Complete Code)
First, install the required image processing library:
bash
pip install plotly kaleido
Python Script for Inline Image:
python
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
import plotly.express as px
# 1. Create Sample Plotly Chart
df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species", title="Iris Dataset Analysis")
# 2. Export Plotly Chart as Bytes (PNG)
img_bytes = fig.to_image(format="png", width=800, height=450, scale=2)
# 3. Setup Email Headers
sender_email = "your_email@gmail.com"
receiver_email = "client_email@gmail.com"
password = "your_app_password" # Use Google App Password
msg = MIMEMultipart("related")
msg["Subject"] = "Automated Report: Plotly Data Analysis"
msg["From"] = sender_email
msg["To"] = receiver_email
# 4. Create HTML Body referencing Image via CID
html_content = """
<html>
<body>
<h2>Weekly Data Summary</h2>
<p>Below is the latest automated data visualization report generated via Python:</p>
<br>
<img src="cid:plotly_graph" alt="Plotly Graph" style="max-width:100%; height:auto;">
<br>
<p>Regards,<br>Data Team</p>
</body>
</html>
"""
msg_alternative = MIMEMultipart("alternative")
msg.attach(msg_alternative)
msg_alternative.attach(MIMEText(html_content, "html"))
# 5. Attach Image with Content-ID
img_attachment = MIMEImage(img_bytes)
img_attachment.add_header("Content-ID", "<plotly_graph>")
img_attachment.add_header("Content-Disposition", "inline", filename="plotly_graph.png")
msg.attach(img_attachment)
# 6. Send Email using SMTP
try:
with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server:
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, msg.as_string())
print("Email sent successfully with embedded Plotly graph!")
except Exception as e:
print(f"Error sending email: {e}")
Method 2: Attach Interactive HTML File (Alternative Approach)
If your recipient must interact with the graph (zoom, hover, filter), save the chart as an HTML file and attach it to the email:
python
from email.mime.application import MIMEApplication
# Create a standalone interactive HTML file (Works offline)
html_graph_str = fig.to_html(
include_plotlyjs=True,
full_html=True
)
# Attach HTML file to the email
html_attachment = MIMEApplication(
html_graph_str.encode("utf-8"),
_subtype="html"
)
html_attachment.add_header(
"Content-Disposition",
"attachment",
filename="interactive_graph.html"
)
msg.attach(html_attachment)
Note: The recipient can download interactive_graph.html and open it in any browser to interact with the live chart.
Common Errors & Troubleshooting
Kaleido Not Installed or Image Export Fails:
If fig.to_image() throws an error or fails to render, ensure you have updated kaleido by running:
bash
pip install -U kaleido
Gmail SMTP Authentication Error:
If your Google account supports App Passwords and the required security settings (like 2-Step Verification) are enabled, use a generated 16-character App Password instead of your normal Gmail password.
Image Not Displaying in Outlook:
Ensure your HTML uses <img src=”cid:plotly_graph”> and the Content-ID header matches exactly including the angle brackets <>.
Conclusion
While email clients prevent full JavaScript interactivity inside the inbox, embedding high-resolution rendered images via MIMEImage and CID is the most reliable way to display Plotly charts in Python HTML emails. For full interactivity, attach the standalone HTML file separately using Method 2.
1 thought on “How to Embed Interactive Plotly Graphs in Python HTML Emails (Fixed)”