great-tables
great-tables copied to clipboard
Nanoplots compatible in an email using as_raw_html()
Question
Is a nanoplot capable of appearing in an email? Before I open a bug I want to confirm whether or not when using as_raw_html() and sending via email the nanoplot should be displaying correctly?
Currently no interactive plot appears and instead the individual values are what's left when viewing in an email:
Product | Trend Plot
Shoes 0.9900.710.980.270.440.99
@rich-iannone, I recall seeing a video where you shared your experience implementing a table that could be beautifully sent via email. Could you provide some insights on that? What else would be needed to send Great Tables via email without much hassle?
Yes! That was with the R version of Great Tables ('gt'). I also develop an R package called blastula that makes it fairly easy to send an HTML email through SMTP (and Posit Connect). It does work well and is well tested across email providers/clients/OSes. What's uncertain is whether nanoplots in tables in HTML emails work as well as they do in a browser.
I tried testing this out yesterday (w/ gt + blastula, since it also has nanoplots) but came up against issues sending a message through SMTP. Using the SMTP2GO service (which used to be pretty painless) now has some hoops to jump through. What I'll try soon is sending an email (w/ nanoplots-containing table) through the combination of Posit Connect, Quarto (which has built-in emailing functionality), and Great Tables.
I looked around for a similar package to blastula in the Python ecosystem. Couldn't find anything, but maybe I'm missing something obvious. I've had Python users ask me to port over blastula to Python so maybe this is missing functionality in the Python space.
@andre-sun I forgot to ask the more obvious thing: what are you using to send an email with a GT table? Could you share the code?
@rich-iannone Thanks for the replies. I am using the smtplib library for the sending of the message and the email library for the message formatting. Here's concise version of my code which currently is using GT.save() to create a .png of the image as an alternative to as_raw_html():
table = (
GT(merged_df)
.tab_header(title="Predictions")
.fmt_percent("Probability", decimals=0)
.fmt_nanoplot(
columns="5-Day Trend",
plot_type='bar',
plot_height="4em",
expand_y=[0, 1.2],
options=nanoplot_options(
interactive_data_values=False,
y_val_fmt_fn=lambda y: f"{y:.2f}"
)
)
)
# Save the table as an image
image_path = "table_image.png"
table.save(image_path, selector='table', scale=1.0)
# Create HTML body with embedded image
html_body = """
<html>
<body>
<p>Competitor Restore Predictions:</p>
<img src="cid:table_image" alt="Predictions Table" style="max-width:100%; height:100%;"/>
</body>
</html>
"""
# Send email using SMTP
try:
logging.info("Setting up email parameters")
# Setup email parameters
sender_email = email_config['sender']
receiver_emails = email_config['recipient']
email_subject = email_config['subject']
if isinstance(receiver_emails, str):
receiver_emails = [receiver_emails]
logging.debug(f"Converted receiver_emails to list: {receiver_emails}")
msg = MIMEMultipart('related')
alt = MIMEMultipart('alternative')
msg.attach(alt)
msg["From"] = sender_email
msg["To"] = ", ".join(receiver_emails)
msg["Subject"] = email_subject
# Attach HTML body to alt part
alt.attach(MIMEText(html_body, "html"))
# Attach image to related part
with open(image_path, 'rb') as f:
img = MIMEImage(f.read())
img.add_header('Content-ID', '<table_image>')
img.add_header('Content-Disposition', 'inline', filename='table_image.png')
msg.attach(img)
# Connect to SMTP server and send email
logging.info("Connecting to SMTP server")
with smtplib.SMTP(email_config['smtp_server'], email_config['smtp_port']) as server:
server.sendmail(sender_email, receiver_emails, msg.as_string())
logging.info(f"Email successfully sent!")
except Exception as e:
logging.error(f"Error sending email: {e}")
GT table in Python does not display properly.