Previously we looked at how you can combine R and Markdown to create reports directly from your R scripts, and also how to send email from R using Microsoft Outlook. In this post, we’ll take these concepts a step further and look at how we can use R to embed images in email messages or even use Markdown to create entire messages.
Before getting started with this, we recommend you review the following posts (if you haven’t already) since this post expands on concepts introduced previously:
Embedding images in messages
First, let’s look at how we can embed images in messages. Imagine we have a quarterly report that we’d like to send out by email, and we want to include a graph of the previous quarter’s results in the body of the message. To do this, all you need to do is:
- Create a plot in R
- Save it as a .jpg or .png file
- Attach it to an html format email
- Reference the image in the body of the message with the
imgtag and by using
cid:followed by the file name of the attachment
Here’s a full example of this in action:
# Set up some data for the chart chartValues = c(8,13,4,9,7) # Set the filename for the chart png(file = "chart.jpg") # Create the chart plot(chartValues, type = "o", main = "Quarterly Sales") # Save the file dev.off() # Load the DCOM library require (RDCOMClient) # Open Outlook Outlook <- COMCreate("Outlook.Application") # Create a new message Email = Outlook$CreateItem(0) # Set the recipient, subject, and body Email[["to"]] = "email@example.com; firstname.lastname@example.org" Email[["subject"]] = "Quarterly Sales Report" # Attach the image to the message # You need to specify the full path for Outlook to find the file Email[["attachments"]]$Add("D:\\Reports\\chart.jpg") # To add the image: create a HTML message, use the image tag, # and prefix the name of the file with "cid:" Email[["htmlbody"]] = "<h1>Quarterly Sales Report</h1> <p>The quarterly sales report has been updated</p> <img src='cid:chart.jpg'>" # Send the message Email$Send() # Close Outlook, clear the message rm(Outlook, Email)
Using Markdown to generate entire messages
Since Markdown is an easy way to create beautiful reports directly from R, it can also be leveraged to create email messages. One of the default output formats in Markdown is an HTML document, which makes this an easy process: we can use the HTML output as the body of our message. The overall process is simple:
- Create a report using R and Markdown
- Export the report to an HTML file
- Create a new email message in R
- Use the HTML file as the body of the email
- Send the message
We’ll start by creating a .Rmd document which creates the body of your email. Next we’ll create a second script that serves two purposes: it will build a HTML document from the .Rmd file and then use the HTML document as the body of your email.
Create a report using R and Markdown
Following the instructions provided previously in Quickly create polished, professional reports with Markdown and R, create a R Markdown script that produces the exact output you want to see in the body your email.
You can take full advantage of the formatting options in Markdown such as headings, embedded code and / or graphs, but the crucial settings you need to include in your Markdown file are to create HTML output and that the file should be self-contained (all the images should be embedded directly within the HTML). You can set these options in the header of your .Rmd file:
--- # Change the title to match your message title: "Quarterly Sales Report" output: html_document: self_contained: true ---
Save your Markdown file and we are ready to start the next step.
Creating the email using our Markdown file
In a new script, we’ll start by knitting the .Rmd into a self contained HTML document. Once the HTML file has been saved, we’ll using the
readtext function from the readtext library to read it into an object. Next, we’ll start a new message in Outlook and, instead of providing body of the message ourselves, we’ll just pass it the object with the contents of our HTML file.
Here’s what the entire script looks like:
# Knit the 'analysis' Markdown file into an HTML document, # you'll need to change this to the name of your Markdown report. rmarkdown::render("analysis.Rmd", "html_document") # Load the readtext library require (readtext) # Read the HTML document into an object, the file name # should match your .Rmd document above body <- readtext("analysis.htm") # Load the DCOM library require (RDCOMClient) # Open Outlook Outlook <- COMCreate("Outlook.Application") # Create a new message Email = Outlook$CreateItem(0) # Set the recipient, subject, and body Email[["to"]] = "email@example.com; firstname.lastname@example.org" Email[["subject"]] = "Quarterly Sales Report" Email[["body"]] = body$text # Send the message Email$Send() # Close Outlook, clear the message rm(Outlook, Email)
That’s all there is to it. If you run this script, it will knit a fresh copy of your analysis and send it out in a email message. It’s amazing how easy it is to use R to create and distribute reports.
Want to learn more about how you can automate your daily work with R? Reach out to me by leaving a comment or using the contact form and I would be happy to hear from you!
6 Replies to “Advanced email in R: embedding images and markdown”
thank you for the very useful guide. The command:
Email[[“body”]] = body$text
sends a flat email and not an HTML one (with images and formatting). It seems that readtext put as “text” a flat text and not a HTML code ( as I expect).
What do you think I’m doing wrong?
It’s been a while since I’ve revisited this, but try using
I think it’s the use of the
htmlbodyattribute that triggers the HTML formatting in your message.
I got a workaround:
# in RStudio Files tab
# click on the .html file, Open in Editor
# File -> Save as -> [file_name].txt
body <- readtext(here::here("self.txt"))
Email[["htmlbody"]] = body$text
You don’t need to use the readtext package nor the workaround that Luca outlined. Instead, you can use the readLines() function from base R as follows:
body <- paste(readLines("analysis.html"), collapse="\n")
This is a great guide, but how does one attach a .html file as the result? I can get this to work without the .html attachment and also works fine with a .csv file, but the only purpose of my script is to send a .html file, and I’m getting the following error:
No support for InterfaceSupportsErrorInfo
Error: Exception occurred.
Thank you for the great tutorial!
I think it needs to be the absolute path i.e. “C:/Users/path/to/my/file.html”