问题
I am desiring to send an email in R with an attachment using gmail. I have found that sendmailR does not work with gmail because it requires authentication (I couldn't get it to work with gmail so I assume this to be true unless someone tells me I'm wrong , in which case I'll post the R output and error message for that). I found a code snippet found here (LINK). As the site suggests the code is not formatted to send attachments but I have got it to send an email. I'd like to extend this code to send attachments (in an email correspondence the author of this code was unable to extend the code to send attachments).
I want to send emails with R using gmail. I am a windows 7 user with the 2.14 beta version of R.
The code that sends emails but not attachments:
require(rJython)
rJython <- rJython()
rJython$exec( "import smtplib" )
rJython$exec("from email.MIMEText import MIMEText")
rJython$exec("import email.utils")
mail<-c(
#Email settings
"fromaddr = 'bigbird@gmail.com'",
"toaddrs = 'oscarthegrouch@gmail.com'",
"msg = MIMEText('This is the body of the message.')",
"msg['From'] = email.utils.formataddr(('sender name', fromaddr))",
"msg['To'] = email.utils.formataddr(('recipient name', toaddrs))",
"msg['Subject'] = 'Simple test message'",
#SMTP server credentials
"username = 'bigbird@gmail.com'",
"password = 'pw'",
#Set SMTP server and send email, e.g., google mail SMTP server
"server = smtplib.SMTP('smtp.gmail.com:587')",
"server.ehlo()",
"server.starttls()",
"server.ehlo()",
"server.login(username,password)",
"server.sendmail(fromaddr, toaddrs, msg.as_string())",
"server.quit()")
jython.exec(rJython,mail)
Note this message is cross posted at talkstats.com. I did not receive a reply there (just members telling me they wish they could help). If I receive a workable solution i will also post it there as well.
回答1:
You are running Jython code inside of your R environment, so you're looking for a way to send an attachment using the Jython language, not R.
Since Jython is basically Python, here is a way to send an email with an attachment with Python: How to send email attachments with Python.
You will just have to hack together that code into yours.
回答2:
A response that works and works well is found here:
http://r.789695.n4.nabble.com/Email-out-of-R-code-td3530671.html
Thank you to nutterb for an answer from the rhelp list. Thank you to all that tried to assist me and were patient with my ignorance of python.
回答3:
Option 1: For sendmailR
, it seems that you're having issues with the appending of port 25. You should be able to specify the destination port via sendmail_options(smtpPort = 587)
, prior to using the sendmail()
command.
I am not sure that this will resolve your other issues, but it should get you the right port.
Option 2: If you'd like to invoke a Python script, this one looks most relevant. You may find it easiest to do token substitution, i.e. take a base script, put in strings that you'll simply find (i.e. the tokens) & replace (i.e. substitution with your desired strings), and then execute the revised script.
For instance, using the script at the link above (saved in a local directory as "sendmail_base.py"):
BasePy = scan("sendmail_base.py", what = "character", sep = "\n")
OutPy = gsub("your_email@gmail.com", "yourRealEmailAddress", InFile)
OutPy = gsub("your_password", "yourRealPassword", OutFile)
and so on, replacing the header, recipient, etc., with the text strings you'd like to use, and the same for specification of the attachment file name. Finally, you can save the output to a new Python file and execute it:
cat(OutPy, file = "sendmail_new.py", sep = "\n")
system("chmod u+x sendmail_new.py; ./sendmail_new.py")
Although this is a very naive approach, it is simple and debugging of the script involves only examination of whether your output Python program is working and whether or not R is generating the right output Python program. This is in contrast to debugging what's going on with R passing objects to and from various packages and languages.
回答4:
I came across this code today from the rhelp listserve. Maybe it'll help things along:
send.email <- function(to, from, subject, message, attachment=NULL, username, password,
server="smtp.gmail.com:587", confirmBeforeSend=TRUE){
# to: a list object of length 1. Using list("Recipient" ="recip@somewhere.net") will send the message to the address but
# the name will appear instead of the address.
# from: a list object of length 1. Same behavior as 'to'
# subject: Character(1) giving the subject line.
# message: Character(1) giving the body of the message
# attachment: Character(1) giving the location of the attachment
# username: character(1) giving the username. If missing and you are using Windows, R will prompt you for the username.
# password: character(1) giving the password. If missing and you are using Windows, R will prompt you for the password.
# server: character(1) giving the smtp server.
# confirmBeforeSend: Logical. If True, a dialog box appears seeking confirmation before sending the e-mail. This is to
# prevent me to send multiple updates to a collaborator while I am working interactively.
if (!is.list(to) | !is.list(from)) stop("'to' and 'from' must be lists")
if (length(from) > 1) stop("'from' must have length 1")
if (length(to) > 1) stop("'send.email' currently only supports one recipient e-mail address")
if (length(attachment) > 1) stop("'send.email' can currently send only one attachment")
if (length(message) > 1){
stop("'message' must be of length 1")
message <- paste(message, collapse="\\n\\n")
}
if (is.null(names(to))) names(to) <- to
if (is.null(names(from))) names(from) <- from
if (!is.null(attachment)) if (!file.exists(attachment)) stop(paste("'",
attachment, "' does not exist!", sep=""))
if (missing(username)) username <- winDialogString("Please enter your
e-mail username", "")
if (missing(password)) password <- winDialogString("Please enter your
e-mail password", "")
require(rJython)
rJython <- rJython()
rJython$exec("import smtplib")
rJython$exec("import os")
rJython$exec("from email.MIMEMultipart import MIMEMultipart")
rJython$exec("from email.MIMEBase import MIMEBase")
rJython$exec("from email.MIMEText import MIMEText")
rJython$exec("from email.Utils import COMMASPACE, formatdate")
rJython$exec("from email import Encoders")
rJython$exec("import email.utils")
mail<-c(
#Email settings
paste("fromaddr = '", from, "'", sep=""),
paste("toaddrs = '", to, "'", sep=""),
"msg = MIMEMultipart()",
paste("msg.attach(MIMEText('", message, "'))", sep=""),
paste("msg['From'] = email.utils.formataddr(('", names(from), "',
fromaddr))", sep=""),
paste("msg['To'] = email.utils.formataddr(('", names(to), "',
toaddrs))",
sep=""),
paste("msg['Subject'] = '", subject, "'", sep=""))
if (!is.null(attachment)){
mail <- c(mail,
paste("f = '", attachment, "'", sep=""),
"part=MIMEBase('application', 'octet-stream')",
"part.set_payload(open(f, 'rb').read())",
"Encoders.encode_base64(part)",
"part.add_header('Content-Disposition', 'attachment;
filename=\"%s\"' %
os.path.basename(f))",
"msg.attach(part)")
}
#SMTP server credentials
mail <- c(mail,
paste("username = '", username, "'", sep=""),
paste("password = '", password, "'", sep=""),
#Set SMTP server and send email, e.g., google mail SMTP server
paste("server = smtplib.SMTP('", server, "')", sep=""),
"server.ehlo()",
"server.starttls()",
"server.ehlo()",
"server.login(username,password)",
"server.sendmail(fromaddr, toaddrs, msg.as_string())",
"server.quit()")
message.details <-
paste("To: ", names(to), " (", unlist(to), ")", "\n",
"From: ", names(from), " (", unlist(from), ")",
"\n",
"Using server: ", server, "\n",
"Subject: ", subject, "\n",
"With Attachments: ", attachment, "\n",
"And the message:\n", message, "\n", sep="")
if (confirmBeforeSend)
SEND <- winDialog("yesnocancel", paste("Are you sure you want to send
this e-mail to ", unlist(to), "?", sep=""))
else SEND <- "YES"
if (SEND %in% "YES"){
jython.exec(rJython,mail)
cat(message.details)
}
else cat("E-mail Delivery was Canceled by the User")
Now I try it:
x<-paste(getwd(),"/Eercise 6.doc",sep="")
send.email(list("bigbird@gmail.com"), list("bigbird@gmail.com"), 'dogs',
'I sent it!', attachment=x, 'bigbird@gmail.com', 'mypassword',
server="smtp.gmail.com:587", confirmBeforeSend=FALSE)
AND THE ERROR:
> x<-paste(getwd(),"/Eercise 6.doc",sep="")
>send.email(list("bigbird@gmail.com"), list("bigbird@gmail.com"), 'dogs',
+ 'I sent it!', attachment=x, 'bigbird@gmail.com', 'mypassword',
+ server="smtp.gmail.com:587", confirmBeforeSend=FALSE)
Error in .jcall("RJavaTools", "Ljava/lang/Object;", "invokeMethod", cl, :
SyntaxError: ("mismatched character '\\n' expecting '''", ('<string>', 15,
52, "\tpart.add_header('Content-Disposition', 'attachment;\n"))
回答5:
Take a look at the package sendmailR
which can send attachments. To make sendmail
work with gmail on a Mac would require some additional fiddling around, but you can find the instructions to do it using a google search.
回答6:
You could give the new mailR package a shot that allows SMTP authorization: http://rpremraj.github.io/mailR/
The following call should then work:
27/05/14: Editing example below to demonstrate how attachments can be sent via R:
send.mail(from = "sender@gmail.com",
to = c("recipient1@gmail.com", "recipient2@gmail.com"),
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"),
file.names = c("Download log", "Upload log"), # optional parameter
file.descriptions = c("Description for download log", "Description for upload log"))
回答7:
For working with Gmail using R best working example is available here. It's basic is as below:
A project in Google Developers Console to manage your use of the Gmail API
the gmailr R package by Jim Hester, which wraps the Gmail API (development on GitHub)
the plyr and dplyr packages for data wrangling (do this with base R if you prefer)
addresses.csv a file containing email addresses, identified by a key. In our case, student names.
marks.csv a file containing the variable bits of the email you plan to send, including the same identifying key as above. In our case, the homework marks.
the script send-email-with-r.r
回答8:
Pasting here for convenience the code from one link above
send.email <- function(to, from, subject,
message, attachment=NULL,
username, password,
server="smtp.gmail.com:587",
confirmBeforeSend=TRUE){
# to: a list object of length 1. Using list("Recipient" = "recip@somewhere.net") will send the message to the address but
# the name will appear instead of the address.
# from: a list object of length 1. Same behavior as 'to'
# subject: Character(1) giving the subject line.
# message: Character(1) giving the body of the message
# attachment: Character(1) giving the location of the attachment
# username: character(1) giving the username. If missing and you are using Windows, R will prompt you for the username.
# password: character(1) giving the password. If missing and you are using Windows, R will prompt you for the password.
# server: character(1) giving the smtp server.
# confirmBeforeSend: Logical. If True, a dialog box appears seeking confirmation before sending the e-mail. This is to
# prevent me to send multiple updates to a collaborator while I am working interactively.
if (!is.list(to) | !is.list(from)) stop("'to' and 'from' must be lists")
if (length(from) > 1) stop("'from' must have length 1")
if (length(to) > 1) stop("'send.email' currently only supports one recipient e-mail address")
if (length(attachment) > 1) stop("'send.email' can currently send only one attachment")
if (length(message) > 1){
stop("'message' must be of length 1")
message <- paste(message, collapse="\\n\\n")
}
if (is.null(names(to))) names(to) <- to
if (is.null(names(from))) names(from) <- from
if (!is.null(attachment)) if (!file.exists(attachment)) stop(paste("'", attachment, "' does not exist!", sep=""))
if (missing(username)) username <- winDialogString("Please enter your e-mail username", "")
if (missing(password)) password <- winDialogString("Please enter your e-mail password", "")
require(rJython)
rJython <- rJython()
rJython$exec("import smtplib")
rJython$exec("import os")
rJython$exec("from email.MIMEMultipart import MIMEMultipart")
rJython$exec("from email.MIMEBase import MIMEBase")
rJython$exec("from email.MIMEText import MIMEText")
rJython$exec("from email.Utils import COMMASPACE, formatdate")
rJython$exec("from email import Encoders")
rJython$exec("import email.utils")
mail<-c(
#Email settings
paste("fromaddr = '", from, "'", sep=""),
paste("toaddrs = '", to, "'", sep=""),
"msg = MIMEMultipart()",
paste("msg.attach(MIMEText('", message, "'))", sep=""),
paste("msg['From'] = email.utils.formataddr(('", names(from), "', fromaddr))", sep=""),
paste("msg['To'] = email.utils.formataddr(('", names(to), "', toaddrs))", sep=""),
paste("msg['Subject'] = '", subject, "'", sep=""))
if (!is.null(attachment)){
mail <- c(mail,
paste("f = '", attachment, "'", sep=""),
"part=MIMEBase('application', 'octet-stream')",
"part.set_payload(open(f, 'rb').read())",
"Encoders.encode_base64(part)",
"part.add_header('Content-Disposition', 'attachment; filename=\"%s\"' % os.path.basename(f))",
"msg.attach(part)")
}
#SMTP server credentials
mail <- c(mail,
paste("username = '", username, "'", sep=""),
paste("password = '", password, "'", sep=""),
#Set SMTP server and send email, e.g., google mail SMTP server
paste("server = smtplib.SMTP('", server, "')", sep=""),
"server.ehlo()",
"server.starttls()",
"server.ehlo()",
"server.login(username,password)",
"server.sendmail(fromaddr, toaddrs, msg.as_string())",
"server.quit()")
message.details <-
paste("To: ", names(to), " (", unlist(to), ")", "\n",
"From: ", names(from), " (", unlist(from), ")", "\n",
"Using server: ", server, "\n",
"Subject: ", subject, "\n",
"With Attachments: ", attachment, "\n",
"And the message:\n", message, "\n", sep="")
if (confirmBeforeSend)
SEND <- winDialog("yesnocancel", paste("Are you sure you want to send this e-mail to ", unlist(to), "?", sep=""))
else SEND <- "YES"
if (SEND %in% "YES"){
jython.exec(rJython,mail)
cat(message.details)
}
else cat("E-mail Delivery was Canceled by the User")
}
来源:https://stackoverflow.com/questions/7802360/email-an-attachment-in-r-with-gmail