[英]Attach a knitted tempfile to email in R shiny
I have a working shiny app that uses Mailgun
to send an email when a button is clicked and also produces a rmarkdown report when another button is clicked. 我有一个工作闪亮的应用程序,使用Mailgun
在单击按钮时发送电子邮件,并在单击另一个按钮时生成rmarkdown报告。
Here is working code, obviously without the working email authentication: 这是工作代码,显然没有工作电子邮件身份验证:
ui.R ui.R
library(shiny)
# Define UI for application that draws a histogram
shinyUI(fluidPage(
sliderInput("slider", "Slider", 1, 100, 50),
downloadButton("report", "Generate report"),
actionButton("mail", "send email"),
textOutput('mailo')
)
)
server.R server.R
library(shiny)
sendEmail <- function(email = "xxx@you.org",
mail_message = "Hello"){
url <- "https://api.mailgun.net/v3/sandboxxxxxxxxx.mailgun.org/messages"
## username:password so api_key is all after the api:
api_key <- "key-0xxxxxxxxxxxx"
the_body <-
list(
from="Mailgun Sandbox <postmaster@sandboxxxxxxxxxxxxxxxx.mailgun.org>",
to=email,
subject="Mailgun from R test",
text=mail_message
)
req <- httr::POST(url,
httr::authenticate("api", api_key),
encode = "form",
body = the_body)
httr::stop_for_status(req)
TRUE
}
# Define server logic required to draw a histogram
shinyServer(function(input, output) {
event <- observeEvent(input$mail,{
sendEmail()
}, ignoreInit = TRUE)
output$mailo <- renderText({print("EMAIL SENT!")})
output$report <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "report.html",
content = function(file) {
# Copy the report file to a temporary directory before processing it, in
# case we don't have write permissions to the current working dir (which
# can happen when deployed).
tempReport <- file.path(tempdir(), "report.Rmd")
file.copy("report.Rmd", tempReport, overwrite = TRUE)
# Set up parameters to pass to Rmd document
params <- list(n = input$slider)
# Knit the document, passing in the `params` list, and eval it in a
# child of the global environment (this isolates the code in the document
# from the code in this app).
rmarkdown::render(tempReport,
output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
})
I want to do both things in one step. 我想一步到位做两件事。 That is, generate the report, attach it to the email and send it to the given address. 也就是说,生成报告,将其附加到电子邮件并将其发送到给定地址。 I am just not sure how to treat a tempfile()
when referencing the file. 我只是不确定在引用文件时如何处理tempfile()
。
I also currently have the app deployed on Shinyapps.io, so saving to file and then retrieving won't work. 我目前也在Shinyapps.io上部署了应用程序,因此保存到文件然后检索将无法正常工作。
Any ideas? 有任何想法吗?
This is the code you need. 这是您需要的代码。 I tested this and it worked, although my gmail did give me huge bright yellow warnings that the email contains an unverified file that may be dangerous. 我测试了它并且它工作了,虽然我的gmail确实给了我巨大的黄色警告,电子邮件包含一个可能是危险的未经验证的文件。 I also simplified the app a bit and removed some unnecessary code. 我还简化了应用程序并删除了一些不必要的代码。
library(shiny)
ui <- fluidPage(
sliderInput("slider", "Slider", 1, 100, 50),
actionButton("mail", "send email")
)
sendEmail <- function(email = "RECIPIENT@gmail.com",
mail_message = "Hello",
file = NULL) {
url <- "https://api.mailgun.net/v3/sandboxxxxxxxxxxxxxxxxxxxxxxxx.mailgun.org/messages"
## username:password so api_key is all after the api:
api_key <- "XXXXXXXXXXXXXXXXXX-XXXXXXXXX-XXXXX"
the_body <-
list(
from = "Mailgun Sandbox <postmaster@sandboxXXXXXXXXXXXXXXXXXXX.mailgun.org>",
to = email,
subject = "Mailgun from R test",
text = mail_message
)
if (!is.null(file)) {
the_body$attachment = httr::upload_file(file)
}
req <- httr::POST(url,
httr::authenticate("api", api_key),
encode = "multipart",
body = the_body)
httr::stop_for_status(req)
TRUE
}
server <- function(input, output, session) {
observeEvent(input$mail, {
# Copy the report file to a temporary directory before processing it, in
# case we don't have write permissions to the current working dir (which
# can happen when deployed).
tempReport <- file.path(tempdir(), "report.Rmd")
file.copy("report.Rmd", tempReport, overwrite = TRUE)
# Set up parameters to pass to Rmd document
params <- list(n = input$slider)
# Knit the document, passing in the `params` list, and eval it in a
# child of the global environment (this isolates the code in the document
# from the code in this app).
file <- rmarkdown::render(tempReport,
output_file = file.path(tempdir(), "report.html"),
params = params,
envir = new.env(parent = globalenv())
)
sendEmail(file = file)
})
}
shinyApp(ui, server)
By the way, there's also an IMmailgun
package in case you're interested, but it achieves essentially what you do with this code. 顺便说一下,如果你感兴趣的话,还有一个IMmailgun
软件包,但它实际上完成了你对这段代码的处理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.