如何使用R发送/接收(SMTP / POP3)电子邮件?

时间:2022-10-25 18:14:26

I strongly suspect the most upvoted answer will be "that is the wrong tool for the job". I acknowledge that R may not be particularly well suited for sending and receiving email but it is the scripting language I know best. I am hoping to find a way to send and receive short emails in R. Does anybody know an established way to do this on a Windows platform? I might be able to use a combination of BLAT and GetMail but a native R solution would be preferred.

我强烈怀疑最受欢迎的答案是“这是工作的错误工具”。我承认R可能不太适合发送和接收电子邮件,但它是我最熟悉的脚本语言。我希望能找到一种在R中发送和接收短电子邮件的方法。有人知道在Windows平台上执行此操作的既定方法吗?我或许可以使用BLAT和GetMail的组合,但首选原生R解决方案。

Edit: An acceptable solution should be able to interface with servers that require SSL.

编辑:可接受的解决方案应该能够与需要SSL的服务器连接。

Edit 2: I provide my stab at a 80% answer. Sadly an R native way is not demonstrated. Instead I use an unholy combination of system calls and command line programs that is likely to not be compatible across platforms. R native calls will require digging into the way POP3 servers like to talk to connected clients and an understanding of SSL that I don't currently have. Other answers are still encouraged.

编辑2:我提供了80%的答案。可悲的是,没有证明R本地方式。相反,我使用系统调用和命令行程序的邪恶组合,这些程序很可能不会跨平台兼容。 R本地调用将需要深入了解POP3服务器与连接客户端交互的方式以及对当前不具备的SSL的理解。其他答案仍然鼓励。

##Note: Other programs are wrapped in R functions and system calls.
#They each have their own licenses which may or may not allow the use suggested here
#Programs used here:
#STunnel: http://www.stunnel.org/; Provides an SSL tunnel but requires OpenSSL 
#OpenSSL: http://www.openssl.org/; OpenSSL to actually provide SSL
#   Note that these .dlls should be placed with the stunnel exe.
#   Also note that libssl32.dll may need to be renamed from ssleay32.dll
#Microsoft Visual C++ 2008 Redistributable (may be required for the SSL .dlls to work correctly)
#Blat: http://www.blat.net; a public domain SMTP sending program
#Getmail is free for non-commercial use. If you use it in a business environment, then a fee of $50 USD is payable to Tim Charron. 

#Stunnel is a TSR, so it will need to be killed from the task manager if there is an issue.  If you are willing to install it as a service you may be able to tweak my code to start and stop the service.  
#My current code does not create .conf file for stunnel the way a full version ought.  Check http://spampal.sanesecurity.com/manual_eng/servers/stunnel/stunnel.htm#sconfig21 to create the appropriate configuration file.

#Set the config values as appropriate
##Config##
BLAT.loc <- "c:/Programming/R/Rmail/blat262/full/blat.exe"
GetMail.loc <- "C:/Programming/R/RMail/getmail133/getmail.exe"
stunnel.loc <- "C:/Programming/R/RMail/stunnel/stunnel-4.11.exe"

#The set mail function assigns the username and password to be used as well as the smtp and pop3 servers it starts stunnel (and assumes that the stunnel.conf file is present and set correctly).
setMail <- function(user,pw,SSL=FALSE,smtp="127.0.0.1:259",pop3="127.0.0.1:1109")
{
    if (SSL==TRUE)
    {
        print("Starting stunnel; you will need to kill this from the task-manager")
        system(stunnel.loc,wait=FALSE)
        Sys.sleep(2) #Give it time to start 
    }
    return(list(user=user,pw=pw,smtp=smtp,pop3=pop3,SSL=SSL))
}

#function to send mail, myMail is the resulting list from setMail
sendmail <- function(myMail, to, subject, msg,VERBOSE=FALSE)
{
    writeLines(msg, "out.txt", sep = "\n", useBytes = FALSE)
      targ <- paste(getwd(),"/out.txt",sep="")
    call <- paste(BLAT.loc, ' "',targ,'" -subject "',subject,'" -to ',to," -u ",myMail$user," -pw ",myMail$pw, " -f ",myMail$user, " -debug -server ",myMail$smtp,sep="")
    res <- system(call,intern=TRUE)
    if (VERBOSE) {return(res)}
}

#function to get mail, myMail is the resulting list from setMail; it returns a list with one element that contains everything unparsed, another list provides the number of messages remaining on the server.
getmail <- function(myMail,VERBOSE=FALSE)
{      
    unlink("MSG1.txt") #drop previous get
    #download next message
    call <- paste(GetMail.loc," -u ",myMail$user," -pw ",myMail$pw," -s ",strsplit(myMail$pop3,":")[[1]][1],
        " -port ",strsplit(myMail$pop3,":")[[1]][2]," -n 1",sep="")
    res <- system(call,intern=TRUE)
    if (VERBOSE) {print(res)}
    nmsgtxt <- res[grep("messages on the server.",res)]
    nstart <- regexpr("There are",nmsgtxt)
    nend <- regexpr("messages on the server.",nmsgtxt)
    nmess <- as.numeric(substr(nmsgtxt,10,nend-1))-1
      x <- readLines("MSG1.txt",-1)
    return(list(message=x,remaining=nmess))
}

Usage case: Simply put, I need to have R be able to send a message whose content is determined elsewhere in the R script to an SMTP server. Participants will receive the email and respond to it. I need to retrieve their response from my POP3 server and store it in an R data structure so that I can perform post processing on it. In practice, I'm establishing a way to do experience sampling via R. That is, R can email a participant "How are you today (1 = Bad; 7 = Great)?" The participant can respond "4", and I can match the question asked, the response, and so on in a database for statistical analysis.

使用案例:简单地说,我需要让R能够将内容在R脚本中的其他位置确定的消息发送到SMTP服务器。参与者将收到电子邮件并回复。我需要从我的POP3服务器检索他们的响应并将其存储在R数据结构中,以便我可以对其执行后期处理。在实践中,我正在建立一种通过R进行经验抽样的方法。也就是说,R可以通过电子邮件向参与者发送电子邮件“你今天好吗(1 =坏; 7 =好)?”参与者可以回答“4”,我可以在数据库中匹配问题,响应等,以进行统计分析。

3 个解决方案

#1


12  

Pulling messages from a Pop server

从Pop服务器中提取消息

To take a stab at implementing @JorisMeys idea of taking advantage of other languages, I took a stab at pulling mail from Gmail (over ssl) using Python and the rJython package. Jython is Python implemented on the Java virtual machine, so using rJython feels to me a bit like using R to call Java that then pretends to be Python.

为了实现@JorisMeys利用其他语言的想法,我尝试使用Python和rJython包从Gmail(通过ssl)中提取邮件。 Jython是在Java虚拟机上实现的Python,所以使用rJython对我来说有点像使用R来调用Java然后假装是Python。

I find rJython pretty easy for simple things, but since I'm not well versed in S4 objects and (r)Java I sometimes struggle to properly manipulate the return objects from rJython. But, it works. Here's a basic construct that will pull a single message from a Gmail account:

我觉得rJython对于简单的事情很容易,但由于我不熟悉S4对象和(r)Java,我有时很难从rJython中正确地操作返回对象。但是,它的确有效。这是一个从Gmail帐户中提取单个邮件的基本结构:

library(rJython)

rJython <- rJython( modules = "poplib")

rJython$exec("import poplib")
rJython$exec("M = poplib.POP3_SSL('pop.gmail.com', 995)")
rJython$exec("M.user(\'yourGmailAddy@gmail.com\')")
rJython$exec("M.pass_(\'yourGmailPassword\')")
rJython$exec("numMessages = len(M.list()[1])")
numMessages <- rJython$get("numMessages")$getValue()

# grab message number one. Loop here if you
# want more messages
rJython$exec("msg = M.retr(1)[1]")
emailContent <- rJython$get("msg")

# turn the message into a list
contentList <- as.list(emailContent)
# so we have an R list... of Java objects
# To get a more native R list we have to
# yank the string from each Java item

messageToList <- function(contentList){
  outList <- list()
  for (i in 1:length(contentList)){
    outList[i] <- contentList[[i]]$toString()
  }
  outList
}

messageAsList <- messageToList(contentList)
messageAsList

#2


7  

Look at the sendmailR package on CRAN.

查看CRAN上的sendmailR包。

#3


1  

With the mailR package (http://rpremraj.github.io/mailR/), you could send emails with SSL:

使用mailR包(http://rpremraj.github.io/mailR/),您可以使用SSL发送电子邮件:

send.mail(from = "sender@gmail.com",
          to = c("recipient1@gmail.com", "recipient2@gmail.com"),
          subject = "Subject of the email",
          body = "<html>The apache logo - <img src=\"http://www.apache.org/images/asf_logo_wide.gif\"></html>",
          html = TRUE,
          smtp = list(host.name = "smtp.gmail.com", port = 465, user.name = "gmail_username", passwd = "password", ssl = TRUE),
          attach.files = c("./download.log", "upload.log"),
          authenticate = TRUE,
          send = TRUE)

#1


12  

Pulling messages from a Pop server

从Pop服务器中提取消息

To take a stab at implementing @JorisMeys idea of taking advantage of other languages, I took a stab at pulling mail from Gmail (over ssl) using Python and the rJython package. Jython is Python implemented on the Java virtual machine, so using rJython feels to me a bit like using R to call Java that then pretends to be Python.

为了实现@JorisMeys利用其他语言的想法,我尝试使用Python和rJython包从Gmail(通过ssl)中提取邮件。 Jython是在Java虚拟机上实现的Python,所以使用rJython对我来说有点像使用R来调用Java然后假装是Python。

I find rJython pretty easy for simple things, but since I'm not well versed in S4 objects and (r)Java I sometimes struggle to properly manipulate the return objects from rJython. But, it works. Here's a basic construct that will pull a single message from a Gmail account:

我觉得rJython对于简单的事情很容易,但由于我不熟悉S4对象和(r)Java,我有时很难从rJython中正确地操作返回对象。但是,它的确有效。这是一个从Gmail帐户中提取单个邮件的基本结构:

library(rJython)

rJython <- rJython( modules = "poplib")

rJython$exec("import poplib")
rJython$exec("M = poplib.POP3_SSL('pop.gmail.com', 995)")
rJython$exec("M.user(\'yourGmailAddy@gmail.com\')")
rJython$exec("M.pass_(\'yourGmailPassword\')")
rJython$exec("numMessages = len(M.list()[1])")
numMessages <- rJython$get("numMessages")$getValue()

# grab message number one. Loop here if you
# want more messages
rJython$exec("msg = M.retr(1)[1]")
emailContent <- rJython$get("msg")

# turn the message into a list
contentList <- as.list(emailContent)
# so we have an R list... of Java objects
# To get a more native R list we have to
# yank the string from each Java item

messageToList <- function(contentList){
  outList <- list()
  for (i in 1:length(contentList)){
    outList[i] <- contentList[[i]]$toString()
  }
  outList
}

messageAsList <- messageToList(contentList)
messageAsList

#2


7  

Look at the sendmailR package on CRAN.

查看CRAN上的sendmailR包。

#3


1  

With the mailR package (http://rpremraj.github.io/mailR/), you could send emails with SSL:

使用mailR包(http://rpremraj.github.io/mailR/),您可以使用SSL发送电子邮件:

send.mail(from = "sender@gmail.com",
          to = c("recipient1@gmail.com", "recipient2@gmail.com"),
          subject = "Subject of the email",
          body = "<html>The apache logo - <img src=\"http://www.apache.org/images/asf_logo_wide.gif\"></html>",
          html = TRUE,
          smtp = list(host.name = "smtp.gmail.com", port = 465, user.name = "gmail_username", passwd = "password", ssl = TRUE),
          attach.files = c("./download.log", "upload.log"),
          authenticate = TRUE,
          send = TRUE)