Günal
Günal

Reputation: 751

How to send emails from within R using a loop

The R code below sends email to the recipients whose email addresses are read from a text file named email. Since Gmail does not allow to send more than 100 in one go, I want to use a loop which will send email to the first 100 and then 101-200, and then 201-300 and so on. Can any please help me with that?

library(mailR)
sender <- "[email protected]"
recipients <- scan("email.txt", encoding="UTF-8",character(0))
send.mail(from = sender,
to = recipients,
subject="Subject of the Mail",
body = "Body of the Mail",
smtp = list(host.name = "smtp.gmail.com", port = 465, 
    user.name="[email protected]", passwd="Mypassword", ssl=TRUE),
    authenticate = TRUE, send = TRUE)

Upvotes: 0

Views: 1243

Answers (2)

lukeA
lukeA

Reputation: 54287

According to the Gmail Sending Limits, you can send to up to 99 addresses with one email. Maybe you want to put those into the BCC field? Here is a test example for Gmail (remember to allow unsecure apps first and to specify sender, user.name and passwd):

library(mailR)
sender <- "[email protected]" # gmail user
# create 5 test addresses from `sender`
testEmails <- paste(sapply(1:5, function(x) sub("(.*)(@.*)", paste0("\\1+test", x, "\\2"), sender)), collapse = "\n") 
cat(testEmails) # print the addresses 
recipients <- scan(file = textConnection(testEmails), encoding="UTF-8",character(0))

## Create a list of vectors of emails with the max size adrPerBatch each
getRecipientBatches <- function(emails, adrPerBatch = 98) {
  cuts <- seq(from = 1, to = length(emails), by = adrPerBatch)
  recipientBatches <- lapply(cuts, function(x) c(na.omit(emails[x:(x+adrPerBatch-1)])))
  return(recipientBatches)
}

## send the 3 test batches à 2/1 address(es)
res <- lapply(getRecipientBatches(recipients, adrPerBatch = 2), function(recipients) {
  send.mail(from =  sender,
            to = sender,
            bcc = recipients,
            subject="Subject of the Mail",
            body = "Body of the Mail",
            smtp = list(host.name = "smtp.gmail.com", 
                        port = 465, 
                        user.name = "...", 
                        passwd = "...", 
                        ssl = TRUE),
            authenticate = TRUE, 
            send = TRUE)
})

Upvotes: 4

Roman Luštrik
Roman Luštrik

Reputation: 70653

This is untested, but should give you a jump board for your own explorations. Conceptually this is like a for loop, but the FUN is applied to recipients for each factor in INDEX. I'm using tapply, which cuts recipients according to INDEX (feel free to calculate your own). You can insert Sys.sleep to prevent the "loop" to send too fast. If you insert browser() as the first line of the function (and run it), you'll be placed inside the function and you can further explore what it's doing.

tapply(X = recipients, INDEX = as.integer(cumsum(rep(1, 252))/100), FUN = function(x, recipients, sender) {
  send.mail(from = sender,
            to = recipients,
            subject="Subject of the Mail",
            body = "Body of the Mail",
            smtp = list(host.name = "smtp.gmail.com", port = 465, 
                        user.name="[email protected]", passwd="Mypassword", ssl=TRUE),
            authenticate = TRUE, send = TRUE)
}, recipients = recipients, sender = sender)

Upvotes: 1

Related Questions