How to send an email with attachment from R in windows
Asked Answered
T

9

57

I have a scheduled an R script running from a windows machine.

After it finishes, I wish this script to automatically send an email with some log file attached.

Using shell() with some other scripts may be possible, but I was wondering if there is a better solution within R. Thanks.

Throughcomposed answered 21/5, 2010 at 21:22 Comment(3)
I presume you meant system() when you wrote shell().Weapon
Hi Ahala, I hope Stedy solution will help. Might I ask, what do you use to have a scheduled R script? Thanks.Parnassus
Tal, use Scheduled tasks in Windows (I reckon that entry goes something like R CMD BATCH script.R), cron on *NIX sistems.Immortelle
W
51

sendmailR works for me on Windows 7. I referenced http://cran.es.r-project.org/web/packages/sendmailR/sendmailR.pdf

smtpServer= info for Outlook 2010 is in File -> Account Settings -> Account Settings -> double click your account -> text in "Server" box

library(sendmailR)

#set working directory
setwd("C:/workingdirectorypath")

#####send plain email

from <- "[email protected]"
to <- "[email protected]"
subject <- "Email Subject"
body <- "Email body."                     
mailControl=list(smtpServer="serverinfo")

sendmail(from=from,to=to,subject=subject,msg=body,control=mailControl)

#####send same email with attachment

#needs full path if not in working directory
attachmentPath <- "subfolder/log.txt"

#same as attachmentPath if using working directory
attachmentName <- "log.txt"

#key part for attachments, put the body and the mime_part in a list for msg
attachmentObject <- mime_part(x=attachmentPath,name=attachmentName)
bodyWithAttachment <- list(body,attachmentObject)

sendmail(from=from,to=to,subject=subject,msg=bodyWithAttachment,control=mailControl)

In addition, multiple files can be sent by adding another mime_part to the msg list as follows (I also condensed it):

attachmentObject <- mime_part(x="subfolder/log.txt",name="log.txt")
attachmentObject2 <- mime_part(x="subfolder/log2.txt",name="log2.txt")
bodyWithAttachment <- list(body,attachmentObject,attachmentObject2)
Wotan answered 3/2, 2012 at 16:24 Comment(5)
Can you use html in "Email body."? Can you use utf-8 encoding (for multilingual text)?Gleason
I don't know. Try it and see.Wotan
How do you configure the serverinfo part for gmail?Salpingectomy
I don't think sendmailR accepts authentication (user/password) - I use mailR for this reason.Rysler
@Rysler Your statement appears true statistik.tu-dortmund.de/~olafm/software/sendmailRWotan
R
21

Use mailR - it works with authentication, attachments, it automatically send txt message along with html and more.

mailR requires rJava which can be a bit of a pain sometimes. On windows I haven't had any problems. On ubuntu this solved the one issue I've had:

sudo apt-get install openjdk-jdk 

in R

install.packages("devtools", dep = T)
library(devtools)
install_github("rpremraj/mailR")

(if you have trouble with rJava - try sudo R CMD javareconf in terminal)

mailR is easy to work with and well documented on the github page.

Example from the documentaion

library(mailR)
send.mail(from = "[email protected]",
          to = c("[email protected]", "[email protected]"),
          subject = "Subject of the email",
          body = "Body of the email",
          smtp = list(host.name = "smtp.gmail.com", port = 465, user.name = "gmail_username", passwd = "password", ssl = TRUE),
          authenticate = TRUE,
          send = TRUE,
          attach.files = c("./download.log", "upload.log", "https://dl.dropboxusercontent.com/u/5031586/How%20to%20use%20the%20Public%20folder.rtf"),
          file.names = c("Download log.log", "Upload log.log", "DropBox File.rtf"), # optional parameter
          file.descriptions = c("Description for download log", "Description for upload log", "DropBox File"), # optional parameter
          debug = TRUE)

Note: your smtp server might find excessive use suspicious. This is the case with e.g. gmail. So after sending a few mails you probably have to log in to the gmail account and see if the account has been temporarily disabled. Also note that if you use a gmail account with two-factor authentication you need to use an application specific password.

Rysler answered 6/1, 2016 at 12:16 Comment(2)
Perhaps you could include an example from the documentation to demonstrate what the code would look like. The other answers successfully included examples.Ricci
@Rysler For attachments, I tried using fileInput function that allows the users to select the file instead of hardcoding the file name...but it returns an error Error in file.exists: invalid 'file' argument...any thoughts?Pulverable
B
10

Would you settle for a twitter message? You could use Rcurl to post an update to twitter, which can then be forwarded to your cell phone as a text, or to your email via the notification settings.

See here: http://www.sakana.fr/blog/2007/03/18/scripting-twitter-with-curl/

Birthstone answered 22/5, 2010 at 0:51 Comment(1)
There is a CRAN package called twitteR for interfacing twitter from R: cran.r-project.org/web/packages/twitteR/index.htmlWeapon
M
6

Have you looked into the sendmailR package yet? It allows SMTP to submit a message and you could probably edit the function to allow an attachment. Then again, if its only one log file it might just be worth it to use shell() as you mentioned.

Metallurgy answered 21/5, 2010 at 23:30 Comment(0)
S
4

For Windows one might parse together a VB-Script (see e.g. http://www.paulsadowski.com/wsh/cdo.htm ) and then call it via shell.

This might look like this:

SendMail <- function(from="[email protected]",to="[email protected]",text="Hallo",subject="Sag Hallo",smtp="smtp.my.server.de",user="me.myself.and.i",pw="123"){
require(stringr)
part1 <- "Const cdoSendUsingPickup = 1 'Send message using the local SMTP service pickup directory. 
Const cdoSendUsingPort = 2 'Send the message using the network (SMTP over the network). 
Const cdoAnonymous = 0 'Do not authenticate
Const cdoBasic = 1 'basic (clear-text) authentication 
Const cdoNTLM = 2 'NTLM "

part2 <- paste(paste("Set objMessage = CreateObject(",'"',"CDO.Message",'"',")" ,sep=""),
paste("objMessage.Subject = ",'"',subject,'"',sep=""),
paste("objMessage.From = ",'"',from,'"',sep=""),
paste("objMessage.To = ",'"',to,'"',sep=""),
paste("objMessage.TextBody = ",'"',text,'"',sep=""),
sep="\n")

part3 <- paste(
"'==This section provides the configuration information for the remote SMTP server. 

objMessage.Configuration.Fields.Item _ 
(\"http://schemas.microsoft.com/cdo/configuration/sendusing\") = 2

'Name or IP of Remote SMTP Server 
objMessage.Configuration.Fields.Item _ 
(\"http://schemas.microsoft.com/cdo/configuration/smtpserver\") = ",'"',smtp,'"'," 

'Type of authentication, NONE, Basic (Base64 encoded), NTLM 
objMessage.Configuration.Fields.Item _ 
(\"http://schemas.microsoft.com/cdo/configuration/smtpauthenticate\") = cdoBasic 

'Your UserID on the SMTP server 
objMessage.Configuration.Fields.Item _ 
(\"http://schemas.microsoft.com/cdo/configuration/sendusername\") = ",'"',user,'"'," 

'Your password on the SMTP server 
objMessage.Configuration.Fields.Item _ 
(\"http://schemas.microsoft.com/cdo/configuration/sendpassword\") = ",'"',pw,'"', "

'Server port (typically 25) 
objMessage.Configuration.Fields.Item _ 
(\"http://schemas.microsoft.com/cdo/configuration/smtpserverport\") = 25 

'Use SSL for the connection (False or True) 
objMessage.Configuration.Fields.Item _ 
(\"http://schemas.microsoft.com/cdo/configuration/smtpusessl\") = False 

'Connection Timeout in seconds (the maximum time CDO will try to establish a connection to the SMTP server) 
objMessage.Configuration.Fields.Item _ 
(\"http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout\") = 60 
objMessage.Configuration.Fields.Update

'==End remote SMTP server configuration section== 

objMessage.Send 
",sep="")

vbsscript <- paste(part1,part2,part3,sep="\n\n\n")
str_split(vbsscript,"\n")
writeLines(vbsscript, "sendmail.vbs")
shell("sendmail.vbs")
unlink("sendmail.vbs")
}
Surinam answered 25/7, 2012 at 14:33 Comment(3)
Thanks a lot, this works like a dream! This is the only approach I have found to work in R (on Windows). As explained in Paul's web page, if you use gmail you need to set the server port to 465 and to set the "Use SSL" option to True. I used the following code to call it: SendMail(from="[email protected]",to="[email protected]",text="Hallo", subject="Sag Hallo",smtp="smtp.gmail.com",user="[email protected]",pw="********") Insert your real password of course... Also, the work directory of R must be somewhere on the hard disk (C:).Alyshaalysia
This is awesome! Is it possible to add an attachment? I have very limited VB experience...so, that's why I'm asking.Roee
Love to help :-) ... jip, it seems possible although I never tried it myself, see here: paulsadowski.com/wsh/cdo.htm under headline "Sending a text email with an attached file" ... one could include the relevant lines in the function.Surinam
S
3

Just want to remind people who wants self-notifying feature of a service called twilio, they provide free service to send sms to your own cellphone. A walk-through using R is available here https://dreamtolearn.com/ryan/data_analytics_viz/78

An example code is attached, just replace the credentials with the ones of your own.

library(jsonlite)
library(XML)
library(httr)
library(rjson)
library(RCurl)
options(RCurlOptions = list(cainfo = system.file("CurlSSL", "cacert.pem", package = "RCurl")))

authenticate_twilio <- "https://[ACCOUNT SID]:[AUTH TOKEN]@api.twilio.com/2010-04-01/Accounts"
authenticate_response <- getURL(authenticate_twilio)
print(authenticate_response)

postForm("https://[ACCOUNT SID]:[AUTH TOKEN]@api.twilio.com/2010-04-01/Accounts/[ACCOUNT SID]/Messages.XML",.params = c(From = "+1[twilio phone#]", To = "+1[self phone#]",Body = "Hello from twilio"))
Stulin answered 30/9, 2015 at 2:2 Comment(0)
S
1

Here is a simple code snippet for sending an e-mail by using "mailR" package

library(mailR)

# 1. Sender
sender <- "[email protected]"

# 2. Recipients
recipients <- c("[email protected]", "[email protected]")

# 3. Attached files
list_files_attached_location <- c("mtcars.csv")
list_files_attached_names <- c("mtcars name")
list_files_attached_description <- c("mtcars desc")

# 4. Send email
tryCatch({
  send.mail(from = sender,
            to = recipients,
            subject = "Your subject",
            body = "Your mail body",
            smtp = list(
              host.name = "smtp.gmail.com", 
              port = 465,
              user.name = sender,
              passwd = "psw", 
              ssl = TRUE),
            authenticate = TRUE,
            send = TRUE,
            attach.files = list_files_attached_location,
            file.names = list_files_attached_names,
            file.descriptions = list_files_attached_description,
            debug = TRUE
  )
}, 
error = function(e) {
  print(e)
  stop()
})
Sardonyx answered 29/5, 2020 at 14:30 Comment(0)
M
1

For those who suggested using 'mailR' - this is the way to go, but it is difficult to install of ubuntu. Here is a resource to install 'javaR' on ubuntu which will allow you to install 'mailR'

https://www.r-bloggers.com/2018/02/installing-rjava-on-ubuntu/

Millesimal answered 1/4, 2022 at 20:57 Comment(0)
N
0

Late to this, but you can avoid shelling out to vbscript by using RDCOMClient correctly, as in this example from R-Help.

> sendEmail(ema = "r-help at r-project.org", 
        name = "R-help mailing list",
        subject = "How to send Email from R using the RDCOMClient"
        msgBody = "here is the body of the message")

The package RDCOMClient is available at http://www.omegahat.org/RDCOMClient.

"sendEmail" <-
function(ema, name, subject, msgBody, deliverNow = TRUE)
{
   require(RDCOMClient)

   ema <- paste("SMPT:", ema, sep="")   ## prepend protocol to address

   ## create an e-mail session 
   session <- COMCreate("Mapi.Session") 
   session$Logon()

   ## add a message to the outbox collection of messages
   outbox <- session[["Outbox"]]
   msg <- outbox[["Messages"]]$Add(subject, msgBody)

   ## add recipient's name  (TODO: addMultiple() or loop, if many recipients)
   msg[["Recipients"]]$Add(name, ema) 
   msg$Send()
   if(deliverNow)
      msg$DeliverNow()

   session$Logoff()   ## wrap up
}
Niphablepsia answered 10/12, 2019 at 9:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.