I have created two tables that I would like to send in body email using R.
Currently I am using mailR package and have managed to send one of the tables, however I can't find a way to include both tables in the email. Please note that the two tables have different number of columns (and so I can't append them). Any suggestions? Thanks
send.mail (from = "email",
to = c("email"),
subject = "Something",
body = print(xtable(tablename), type = "html",
format.args = list(big.mark = ",", decimal.mark = "."),
size="\\fontsize{10pt}\\Arial",
booktabs = TRUE,
include.rownames = FALSE),
html = TRUE,
smtp = list(host.name = "hostname"),
attach.files = c(paste0("G:/",
format(Sys.time(), "%d-%b-%Y"), ".xlsx")),
send = TRUE)
Related
I have 3 dataframes say df1, df2, df3 and I want to send it in an email as 3 separate tables with some space between them.
I am able to currently send 1 dataframe as table with below code
library("mailR")
df1 <- read.csv('Adhoc/temp.csv')
final1 <- print(xtable(df1,caption = "Report"), type = "html", include.rownames = FALSE,
caption.placement = getOption("xtable.caption.placement", "top"),
html.table.attributes = getOption("xtable.html.table.attributes","border=1"))
date_of_report<- Sys.Date() - 1
send.mail(from = "no-reply#abc.com",
to = c('xyz.pqr#abc.com'
),
subject = paste('Report', date_of_report, sep=' '),
body = final1,
html = TRUE,
smtp = list(host.name = "aspmx.l.google.com", port = 25),
authenticate = FALSE,
send = TRUE,
debug=TRUE)
I wanted some help so that I can send all the dataframes in one email itself. Currently I send 3 such emails.
Suggested untested Solution: paste multiple pre-formatted tables:
final1 <- print(xtable(df1,caption = "Report"), type = "html", include.rownames = FALSE,
caption.placement = getOption("xtable.caption.placement", "top"),
html.table.attributes = getOption("xtable.html.table.attributes","border=1"))
final2 <- print(xtable(df2,caption = "Report2"), type = "html", include.rownames = FALSE,
caption.placement = getOption("xtable.caption.placement", "top"),
html.table.attributes = getOption("xtable.html.table.attributes","border=1"))
final3 <- print(xtable(df3,caption = "Report3"), type = "html", include.rownames = FALSE,
caption.placement = getOption("xtable.caption.placement", "top"),
html.table.attributes = getOption("xtable.html.table.attributes","border=1"))
final <- paste(final1, final2, final3, sep="\n")
date_of_report<- Sys.Date() - 1
send.mail(from = "no-reply#abc.com",
to = c('xyz.pqr#abc.com'
),
subject = paste('Report', date_of_report, sep=' '),
body = final,
html = TRUE,
smtp = list(host.name = "aspmx.l.google.com", port = 25),
authenticate = FALSE,
send = TRUE,
debug=TRUE)
I think it makes a lot of sense to define a function, here. And then there are a couple of things I would change up for future extensibility.
library(xtable) # This is required for the xtable function and print method
library(mailR)
# Read the data.frames into a list. This makes it easier to add/remove tables later
dfs <- list(
`Report 1` = data.frame(letter = LETTERS[seq_len(5L)],
number = seq_len(5L),
stringsAsFactors = FALSE
),
`Report 2` = data.frame(letter = letters[6L + seq_len(5L)],
number = 6L + seq_len(5L),
stringsAsFactors = FALSE
),
`Report 3` = data.frame(letter = LETTERS[20L:16L],
number = 20L:16L,
stringsAsFactors = FALSE)
)
Now we need to define the function that will format one of our tables. I'm just calling it make_xtable, and I'm giving it two arguments, the first is a data.frame, and the second is a string that will be used as the caption.
make_xtable <- function(df, caption) {
print(
xtable(df, caption = caption),
type = "html",
include.rownames = FALSE,
caption.placement = getOption("xtable.caption.placement", "top"),
html.table.attributes = getOption("xtable.html.table.attributes", "border=1"),
print.results = FALSE # This suppresses the results from printing to the console
)
}
So far we've loaded in our data, and we've defined a process for creating the tables from a given data.frame and caption string, but we still need to actually run each of our tables through the process. Here is where putting our data.frames into a list will come in handy. The family of apply functions will help us run the function on every element of our list, and then paste0 will let us combine the resulting character vector into a character object of length 1.
email_body <-
paste0(
mapply(
make_xtable,
dfs, # The list of data.frames containing our data
names(dfs) # Names attribute of the list of data.frames
),
collapse = "<br \>" # Concatenate using an HTML newline as a separator
)
Then use email_body as the argument body in the send.mail function.
I am trying to send a mail via mailR and it is working fine. I have a Data Frame and I wanted to colour code specific cells. I used Kable() to format and I got the desired output and it is showing the way it should in Rstudio viewer. But while sending that HTML in the mail, the gridlines are not visible.
I've tried adding 'bordered' in kable_styling()
#color coding for a data frame
library(knitr)
library(kableExtra)
library(dplyr)
a<-mtcars[1:10, 1:2] %>%
mutate(
car = row.names(.),
mpg = cell_spec(mpg, "html", color = ifelse(mpg > 20, "red", "blue")),
cyl = cell_spec(cyl, "html", color = "white", align = "c", angle = 45,
background = factor(cyl, c(4, 6, 8),
c("#666666", "#999999", "#BBBBBB")))
) %>%
select(car, mpg, cyl) %>%
kable(format = "html", escape = F) %>%
kable_styling(c("striped","bordered"), full_width = F)
#=================Send Email
library(mailR)
body_B <- paste("<p>
",a,"
<br> Note: report
<p>",sep="")
Subject <- paste(Sys.Date(), 'xyz',sep= ":")
send.mail(from = "asdf#gmail.com",
to = c("asdf#gmail.com"),
subject = Subject,
body = body_B,
html = TRUE,
smtp = list(host.name = "smtp.gmail.com", port = 587,
user.name = "#####",
passwd = "#####", ssl = T),
authenticate = T,
#attach.files = raw_data,
send = TRUE)
When you print a, you're using the print.kableExtra method, but body_B doesn't have the kableExtra class, so you'll just use the default methods producing the body for your message. If you read the source to kableExtra:::print.kableExtra, you'll see it really does quite a bit of manipulation before sending the object to the browser, so you'll need to duplicate that.
Here's an attempt at that. This might not be the simplest way to do it, but this produces a file that displays properly:
# Generate an HTML header
html_header <- htmltools::tags$head(rmarkdown::html_dependency_jquery(),
rmarkdown::html_dependency_bootstrap(theme = "simplex"),
html_dependency_kePrint())
# Declare body_B to be HTML
html_table <- htmltools::HTML(body_B)
# Glue the two parts together
html_result <- htmltools::tagList(html_header, html_table)
# Create a temp file and write the result there
html_file <- tempfile(fileext = ".html")
htmltools::save_html(html_result, file = html_file, background = "white")
# That will require several different files. You probably want to
# merge them all into one to display. Pandoc can do that...
system(paste(rmarkdown::pandoc_exec(), "--self-contained --template", html_file, "-o", html_file, "</dev/null"))
# The result is now in the file named in html_file. If you want it as
# a character variable, you can read it.
html_lines <- readLines(html_file)
I haven't tried putting this in an email, but I don't see why it wouldn't work.
send.mail(from = "abc#gmail.com",
to = c("abc#gmail.com"),
subject = mail_subject,
body = "High_loss_gain_Imprsn_accounts.html",
html=TRUE,
attach.files = "c:/users/rkathuria/Documents/ACCOUNT_BLOCK_NO_COST_MONITOR.xlsx",
smtp = list(host.name = "aspmx.l.google.com", port = 25),
authenticate = FALSE,
send = TRUE)
In the body part of send.mail; i want to send this html table and a "Hello" message. However, it is either taking my message or html table.
body = "High_loss_gain_Imprsn_accounts.html" ----> this line prints my table in mail message body.
body = "Hello" --> this lines prints Hello.
How can I put together in mail body?
<------------------------------------------------------------------------------->
If instead of xtable, i use tableHTML package and write my code, would it will solve my purpose of adding 2 tables on mail with subject.
mail_body1<-tableHTML(High_loss_gain_Imprsn_accounts, widths = rep(100, 11), caption="Hi, High gain loss account", collapse = 'separate')
mail_body<-paste0(mail_body1,mail_body1)
mail_subject<-paste("Account Block No Cost Monitor ", Sys.Date()-1)
send.mail(from = "abc#gmail.com",
to = c("abc#gmail.com"),
subject = mail_subject,
body = mail_body,
html=TRUE,
attach.files = "c:/users/rkathuria/Documents/ACCOUNT_BLOCK_NO_COST_MONITOR.xlsx",
smtp = list(host.name = "aspmx.l.google.com", port = 25, ssl = TRUE),
authenticate = FALSE,
send = TRUE)
And new problem am facing is through this smtp, mail is not going now.
I struggeled with this before and the best solution I could find was using xtable to produce a html table with caption:
table <- data.frame(a = LETTERS[1:6],
b = LETTERS[7:12])
mailR::send.mail(from = "XXXXXXXX",
to = "XXXXXXXX",
subject = "Hello World",
body = xtable::print.xtable(xtable::xtable(table,
caption = "Hello World"),
type = "html",
caption.placement = "top",
include.rownames = FALSE),
html = TRUE,
smtp = list(host.name = "smtp.gmail.com",
port = 465,
user.name = "XXXXXXXX",
passwd = "XXXXXXXX",
ssl = TRUE),
authenticate = TRUE,
send = TRUE)
The problem is that you can only pass one object or path to body. So if you want to have more than one caption line, you would need to change your html object, I think (I haven't tested what happens if you put more text into the caption, so this might work, too).
I want to write a file using write.table and use UTF-8 as encoding. This works as long as I don't append to this file. When I do, the encoding changes to ANSI. Why is that and how can I prevent this?
Here is a small example code:
options("encoding" = "UTF-8")
write.table("Hello World in UTF-8", file = "C:/TEMP/test.txt", col.names = FALSE, row.names = FALSE, sep = "", quote = FALSE)
write.table("Now it changes to ANSI", file = "C:/TEMP/test.txt", col.names = FALSE, row.names = FALSE, sep = "", quote = FALSE, append = TRUE)
I also tried to use fileEncoding = "UTF-8" directly in write.table, but the result is the same.
Personally, I prefer not to rely on global option. Using fileEncoding parameter to write.table safeguards your code from any changes in global option. Hence the line should be:
write.table("Now it changes to ANSI", file = "C:/TEMP/test.txt", col.names = FALSE, row.names = FALSE, sep = "", quote = FALSE, append = TRUE, fileEncoding = "UTF-8")
I am creating an html output of the dataframe so that the url in one of the column is hyperlinked. Want to embed this in email body instead of attachment, I am using RDCOMclient package.
Forget about RDCOMclient. Try this to e.g. send the data frame df to a gmail account:
library(mailR)
library(xtable)
df <- data.frame(links = sprintf('Go here', c("http://stackoverflow.com/questions/31290427/how-to-embed-a-html-file-in-email-body-using-rdcomclient", "http://stackoverflow.com/")), x = 1:2)
html <- print(xtable(df), type = "html", include.rownames = FALSE, sanitize.text.function = force)
send.mail(from = "...#gmail.com",
to = "...#gmail.com",
subject="subject",
body = html, html = TRUE,
smtp = list(host.name = "smtp.gmail.com", port = 465, user.name = "username", passwd = "password", ssl = TRUE),
authenticate = TRUE,
send = TRUE)
(You may need to allow access to less secure apps.)