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:

  1. Create a plot in R
  2. Save it as a .jpg or .png file
  3. Attach it to an html format email
  4. Reference the image in the body of the message with the img tag 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"]] = "recipient1@test.com; recipient2@test.com"
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:

  1. Create a report using R and Markdown
  2. Export the report to an HTML file
  3. Create a new email message in R
  4. Use the HTML file as the body of the email
  5. 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"]] = "recipient1@test.com; recipient2@test.com"
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

  1. Hi Sean,
    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?
    Thank you

    1. Hi Luca,

      It’s been a while since I’ve revisited this, but try using Email[["htmlbody"]] instead of Email[["body"]].

      I think it’s the use of the htmlbody attribute that triggers the HTML formatting in your message.

  2. 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

    1. 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")

  3. 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:

    80020009
    No support for InterfaceSupportsErrorInfo
    checkErrorInfo -2147352567
    Error: Exception occurred.

    Any thoughts?
    Thank you for the great tutorial!
    Ricky

  4. I think it needs to be the absolute path i.e. “C:/Users/path/to/my/file.html”

Leave a Reply to Luca Cancel reply

Your email address will not be published. Required fields are marked *