Sending R Markdown Report in Body of Email


#1

I'm attempting to generate an HTML document using R Markdown that includes charts and email it to a defined distribution group. I've had success doing this with just a knitr::kable, but as soon as I attempt to include an embedded plot, the email process fails.

I'm open to any suggestions on alternative ways to embed images in emails and have found a few threads on how to approach this issue here, but thus far I haven't been able to run a successful end to end test. For this use case, I'm using rmarkdown::render and the mailR package (I have to send to and from an Office 365 Outlook host).

here is my example.Rmd script

---
title: "Unemployment Report"
output:
    html_document:
        self_contained: no
        theme: null
        highlight: null
        mathjax: null
        css: ink.css
---

Annual Unemployment Summary
```{r, echo=FALSE}
library(tidyverse)
library(plotly)
library(lubridate)
library(knitr)

economics %>%
    mutate(year = year(date)) %>%
    group_by(year) %>%
    summarise_if(is.numeric, funs(mean(.))) %>%
    kable()

Unemployment Charts

charts <- c("pce", "pop", "psavert", "uempmed", "unemploy") %>%
    map( ~{
        economics %>%
            plot_ly(type = "scatter", mode = "lines") %>%
            add_trace(x = ~date, y = ~get(.x)) %>%
            layout(
                annotations = list(text = .x, xref = "paper", yref = "paper", yanchor = "bottom", xanchor = "center", align = "center", x = 0.5, y = 1, showarrow = FALSE),
                showlegend = FALSE)
})

subplot(charts, nrows = length(charts), shareX = TRUE)

And here's a sample email script:

# compile using rmarkdown
library(rmarkdown)

rmarkdown::render("example.Rmd")

library(mailR)

send.mail(from = "me@company.com",
          to = "me@company.com",
          subject = "R Markdown Report - rmarkdown",
          html = T,
          inline = T,
          body = "example.html",
          smtp = list(host.name = "outlook.office365.com", port = 587, user.name = "me@company.com", passwd = "password", tls = T),
          authenticate = T,
          send = T)

Here's the error I'm getting:

org.apache.commons.mail.EmailException: Building the MimeMessage failed
at org.apache.commons.mail.ImageHtmlEmail.buildMimeMessage(ImageHtmlEmail.java:112)
at org.apache.commons.mail.Email.send(Email.java:1436)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at RJavaTools.invokeMethod(RJavaTools.java:386)
Caused by: java.io.IOException: Cant resolve the following file resource :example_files\htmlwidgets-1.0\htmlwidgets.js
at org.apache.commons.mail.resolver.DataSourceFileResolver.resolve(DataSourceFileResolver.java:105)
at org.apache.commons.mail.resolver.DataSourceFileResolver.resolve(DataSourceFileResolver.java:79)
at org.apache.commons.mail.ImageHtmlEmail.replacePattern(ImageHtmlEmail.java:151)
at org.apache.commons.mail.ImageHtmlEmail.buildMimeMessage(ImageHtmlEmail.java:106)


#2

Hi Garrick,

The error message says that the external resource path example_files\htmlwidgets-1.0\htmlwidgets.js can't be resolved.

Have you tried with the option self_contained: yes on the report's YAML header? That way, the report will be rendered as a single HTML file, including the scripts, images, CSS, etc. For more details, check out the RMarkdown documentation, section Document dependencies.


#3

Hi Fernando,

Thanks very much for the response. Initially I did use the self_contained: yes flag but the mailR::send.mail call generates a generic error. Here is the what that rmarkdown YAML looks like:

---
title: "Unemployment Report"
output:
    html_document:
        self_contained: yes
---

And this is the error that I get:

NULL
Error: EmailException (Java): Building the MimeMessage failed

Interestingly, this method generates this error regardless of whether I include the plots or not. The methodology I included in the original post DOES work so long as I comment out the chart generation and inclusion, like so:

example.Rmd

---
title: "Unemployment Report"
output:
    html_document:
        self_contained: no
        theme: null
        highlight: null
        mathjax: null
        css: ink.css
---

Annual Unemployment Summary
```{r, echo=FALSE}
library(tidyverse)
library(plotly)
library(lubridate)
library(knitr)

economics %>%
    mutate(year = year(date)) %>%
    group_by(year) %>%
    summarise_if(is.numeric, funs(mean(.))) %>%
    kable()

example.R

# compile using rmarkdown
library(rmarkdown)

rmarkdown::render("example.Rmd")

library(mailR)

send.mail(from = "me@gmail.com",
          to = "me@gmail.com",
          subject = "R Markdown Report - rmarkdown",
          html = T,
          inline = T,
          body = "example.html",
          smtp = list(host.name = "smtp.gmail.com", port = 465, user.name = "me", passwd = "password", ssl = T),
          authenticate = T,
          send = T)

#4

Oh, ok, so it seems that mailR can't handle self-contained resources encoded in base64, neither RMarkdown v2 documents. A couple of workarounds are reported in the following GitHub issues:


#5

Thanks Fernando. The second post looks promising and I'll be sure to include a working example if I'm successful. I'm not married to any of these libraries by the way. If you know of any email packages that support smtp authentication but might also play a little nicer with R Markdown, I'm all ears.


#6

Well I wasn't able to successfully embed these charts inline in an email. Thanks for your input though!


#7

Hi again @gmccomas. Sad to hear that!

I see that you need to send emails from an Outlook host. Just so you know, if you use gmail, the gmailr package apparently can handle this case. I've found this repo from Jenny Bryan with a mini-tutorial about that: How to send a bunch of emails from R


#8

Not a problem Fernando. I ultimately opted to host the charts on a plotly account and have just embedded a link. I'm certainly no expert in generating MIME friendly content, and this simplified the process considerably.

Let me know if RStudio ever decides to create a generic email library :wink: you guys always create the best maintained and documented libraries and I find that I avail myself of RStudio's code base with increasing frequency.


#9

I'm not an RStudio employee, but I think your kind words will be appreciated by them :slight_smile: I do agree about what you said, and also that the power of the community is one of the best things in the R ecosystem.


#10

Ah! My apologies...had I simply taken the step of reading your profile I would have known that. You've just been so helpful and responsive, I assumed you were in their employ! Though to your point, the strength and enthusiasm of this community is what really drives this ecosystem. Thanks again for all your input.