gmailR - send multiple emails through R with attachment

纵然是瞬间 提交于 2019-12-11 19:04:28

问题


I have figured out how to sent a single email through R with an attachment and have the body of the email show up (seems to be a common problem). However, I'd like to follow Jenny Bryan's method of sending multiple emails while also attaching a file.

Sending a single email with attachment and a message.

msg <- "this is the message of the email"
test_email <- mime() %>%
  to("to@gmail.com") %>%
  from("from@gmail") %>%
  subject("subject goes here") %>%
  body(msg) %>%
  attach_file("29697.html", type = "html")
test_email <- attach_part(test_email, msg)
send_message(test_email)

To mimic the above code, but with Jenny's example, I have the following:

addresses <- read_csv("addresses.csv") #contains a column for 'name' and 'email'
email_sender <- 'First Last <from@gmail.com>' # your Gmail address
msg <- "this is the message of the email"

edat <- addresses %>%
  mutate(
    To = sprintf('%s <%s>', name, email),
    From = email_sender,
    Subject = sprintf('Mark for %s', name),
    body = msg,
    attach_file = sprintf('%s.html, type = html', name))

edat <- edat %>%
  select(To, From, Subject, body, attach_file)

emails <- edat %>%
  pmap(mime)

safe_send_message <- safely(send_message)

sent_mail <- emails %>%
  map(safe_send_message)

The above example creates a list to form the components of the mime file structure that gmailR uses, however, it does not attach the file like the single example above does. I've attempted to structure the attach_file function similarly, however, it does not place it in the list item for the mime in a similar way as calling it alone like the single example above where it puts it in the parts section of the list item. Thanks in advance if anyone has run into this.


回答1:


Sometimes it is easier, though perhaps not quite as elegant, to write a function that performs the action of interest for one row of the tibble. And then use map/map2/pmap or walk/walk2/pwalk to apply that function repeatedly.

library("tidyverse")
library("gmailr")

# Create two empty attachment files needed for example
file.create("A.html")
#> [1] TRUE
file.create("B.html")
#> [1] TRUE

test_send_message <- function(msg) {
  # Doesn't actually send any emails
  print(strwrap(as.character(msg)))
}

prepare_and_send <- function(sender, recepient,
                             title, text,
                             attachment) {
  email <- mime() %>%
    to(sender) %>%
    from(recepient) %>%
    subject(title) %>%
    text_body(text) %>%
    attach_file(attachment, type = "html") %>%
    test_send_message()
}

# Test that function works to send one email
prepare_and_send("to@gmail.com", "from@gmail", "some subject",
                 "some text", "A.html")
#>  [1] "MIME-Version: 1.0\r Date: Mon, 18 Mar 2019 21:32:20 GMT\r To:"        
#>  [2] "to@gmail.com\r From: from@gmail\r Subject: some subject\r"            
#>  [3] "Content-Type: multipart/mixed;"                                       
#>  [4] "boundary=2c47d060a267bfdca54a1fdfe0c4ecaf\r Content-Disposition:"     
#>  [5] "inline\r \r MIME-Version: 1.0\r Date: Mon, 18 Mar 2019 21:32:20 GMT\r"
#>  [6] "Content-Type: text/plain; charset=utf-8; format=flowed\r"             
#>  [7] "Content-Transfer-Encoding: quoted-printable\r Content-Disposition:"   
#>  [8] "inline\r \r some text\r --2c47d060a267bfdca54a1fdfe0c4ecaf\r"         
#>  [9] "MIME-Version: 1.0\r Date: Mon, 18 Mar 2019 21:32:20 GMT\r"            
#> [10] "Content-Type: html; name=A.html\r Content-Transfer-Encoding:"         
#> [11] "base64\r Content-Disposition: inline; filename=A.html;"               
#> [12] "modification-date=Mon, 18 Mar 2019 21:32:20 GMT\r \r \r"              
#> [13] "--2c47d060a267bfdca54a1fdfe0c4ecaf--\r"

# Then try to send multiple emails
addresses <- tribble(
  ~name, ~email,
  "A", "a@gmail.com",
  "B", "b@gmail.com"
)

email_sender <- 'First Last <from@gmail.com>'
msg <- "this is the message of the email"

addresses %>%
  mutate(
    To = sprintf('%s <%s>', name, email),
    From = email_sender,
    Subject = sprintf('Mark for %s', name),
    body = msg,
    attachment = sprintf('%s.html', name)) %>%
  mutate(x = pmap(list(To, From, Subject, body, attachment),
                   safely(prepare_and_send)))
#>  [1] "MIME-Version: 1.0\r Date: Mon, 18 Mar 2019 21:32:20 GMT\r To: A"      
#>  [2] "<a@gmail.com>\r From: First Last <from@gmail.com>\r Subject: Mark"    
#>  [3] "for A\r Content-Type: multipart/mixed;"                               
#>  [4] "boundary=bd435d3f3bb00aee58b776142a512702\r Content-Disposition:"     
#>  [5] "inline\r \r MIME-Version: 1.0\r Date: Mon, 18 Mar 2019 21:32:20 GMT\r"
#>  [6] "Content-Type: text/plain; charset=utf-8; format=flowed\r"             
#>  [7] "Content-Transfer-Encoding: quoted-printable\r Content-Disposition:"   
#>  [8] "inline\r \r this is the message of the email\r"                       
#>  [9] "--bd435d3f3bb00aee58b776142a512702\r MIME-Version: 1.0\r Date: Mon,"  
#> [10] "18 Mar 2019 21:32:20 GMT\r Content-Type: html; name=A.html\r"         
#> [11] "Content-Transfer-Encoding: base64\r Content-Disposition: inline;"     
#> [12] "filename=A.html; modification-date=Mon, 18 Mar 2019 21:32:20 GMT\r"   
#> [13] "\r \r --bd435d3f3bb00aee58b776142a512702--\r"                         
#>  [1] "MIME-Version: 1.0\r Date: Mon, 18 Mar 2019 21:32:20 GMT\r To: B"      
#>  [2] "<b@gmail.com>\r From: First Last <from@gmail.com>\r Subject: Mark"    
#>  [3] "for B\r Content-Type: multipart/mixed;"                               
#>  [4] "boundary=aa10620651c2281647a4fba0dc392694\r Content-Disposition:"     
#>  [5] "inline\r \r MIME-Version: 1.0\r Date: Mon, 18 Mar 2019 21:32:20 GMT\r"
#>  [6] "Content-Type: text/plain; charset=utf-8; format=flowed\r"             
#>  [7] "Content-Transfer-Encoding: quoted-printable\r Content-Disposition:"   
#>  [8] "inline\r \r this is the message of the email\r"                       
#>  [9] "--aa10620651c2281647a4fba0dc392694\r MIME-Version: 1.0\r Date: Mon,"  
#> [10] "18 Mar 2019 21:32:20 GMT\r Content-Type: html; name=B.html\r"         
#> [11] "Content-Transfer-Encoding: base64\r Content-Disposition: inline;"     
#> [12] "filename=B.html; modification-date=Mon, 18 Mar 2019 21:32:20 GMT\r"   
#> [13] "\r \r --aa10620651c2281647a4fba0dc392694--\r"
#> # A tibble: 2 x 8
#>   name  email   To       From        Subject body         attachment x     
#>   <chr> <chr>   <chr>    <chr>       <chr>   <chr>        <chr>      <list>
#> 1 A     a@gmai~ A <a@gm~ First Last~ Mark f~ this is the~ A.html     <list~
#> 2 B     b@gmai~ B <b@gm~ First Last~ Mark f~ this is the~ B.html     <list~

Created on 2019-03-18 by the reprex package (v0.2.1)




回答2:


Using code from dipetkov's suggestion, I modified it to include both an attachment and the message to send a single email.

library("tidyverse")
library("gmailr")

msg <- "this is the message of the email"

prepare_and_send <- function(sender, recipient,
                             title, text,
                             attachment) {
  email <- mime() %>%
    to(recipient) %>%
    from(sender) %>%
    subject(title) %>%
    html_body(text) %>%
    attach_file(attachment, type = "html")
  email <- attach_part(email, msg) %>%
    send_message() 
}

# Test that function works to send one email
prepare_and_send("sender@gmail", "to@gmail", "some subject",
                 "some text", "20558.html")

Taking this a step further, I modified it a bit more to iterate through a series of emails held in the 'addresses' dataframe.

#Iterate it ----
addresses %>%
  mutate(
    to = sprintf('%s <%s>', name, email),
    from = email_sender,
    subject = sprintf('Mark for %s', name),
    html_body = msg,
    attachment = sprintf('%s.html', name)) %>%
  mutate(x = pmap(list(from, to, subject, html_body, attachment),
                  safely(prepare_and_send)))


来源:https://stackoverflow.com/questions/55226676/gmailr-send-multiple-emails-through-r-with-attachment

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!