r-lib / gmailr

Access the Gmail RESTful API from R.
https://gmailr.r-lib.org
Other
229 stars 56 forks source link

Issue sending emails with gmailr via cron script #124

Closed sdisav closed 4 years ago

sdisav commented 4 years ago

I have an R server setup that I use to create and automatically send reports using cron and gmailR package (i.e. non-interactive session). Prior to the most recent version release if I ran:

options(httr_oob_default=TRUE) 
gmail_auth(path = "gmailr.json")

It would return the following prompt:

If you hit yes, it went through the authentication dance and then created the .httr-oauth token that was cached. Once the token was cached, I had several cron scripts that were scheduled to run that would automatically generate and email reports.

With the newest version of gmailR, if I run

gm_auth_configure(key = key, secret = secret, path = path, app = oauth_app(appname, key, secret), cache = TRUE)
gm_auth()

It returns the following prompt:

I can authenticate by selecting my account or I can go through the authentication dance but it does not cache a .httr-oauth token. If I run a script manually, it auto-refreshes the stale OAuth token and sends. However, anytime I try to send an email through an automated cron script, it returns the following error:

Any insight into what I am doing wrong or how I can fix this would be greatly appreciated!

danielmartincruz commented 4 years ago

Hello sdisav, did you manage to solve this problem?

sdisav commented 4 years ago

I did end up solving this problem. This is the script I used to initially setup the authentication and restart it if needed:

# Download .json authentication file from gmail API 
# Create gargle token:
path <- "<insert path to secret .json>"
gm_auth_configure(path = path)

gm_auth(path = path,
        cache = gargle::gargle_oauth_cache(),
        use_oob = TRUE, token = NULL)

# Send token script:
appname <- "gmailr"
email   <- "<insert email>"
scopes  <- "full"
path    <- "<insert path to secret .json>"
key     <- "<insert your key>"
secret  <- "<insert your secret>"
app     <- httr::oauth_app(appname, key, secret)

gm_auth_configure(key = key, 
                  secret = secret, 
                  path = path, 
                  app = app, 
                  cache = TRUE)
gm_auth(email = email, 
        token = httr::config("<insert path to gargle token>"))

# Replace the path to the garge-oauth token if it changes

Then, when I am sending an email through a cron, I have it run just the send token script part before the email script, i.e.:

# Send token script:
appname <- "gmailr"
email   <- "<insert email>"
scopes  <- "full"
path    <- "<insert path to secret .json>"
key     <- "<insert your key>"
secret  <- "<insert your secret>"
app     <- httr::oauth_app(appname, key, secret)

gm_auth_configure(key = key, 
                  secret = secret, 
                  path = path, 
                  app = app, 
                  cache = TRUE)
gm_auth(email = email, 
        token = httr::config("<insert path to gargle token>"))

Not sure if everything I do is necessary but honestly I was just happy that it worked so I didn't bother messing with it.

danielmartincruz commented 4 years ago

It worked for me as well! Thank you very much. I have found this interesting post with all the options for sending emails thorough R :

From all the options I found mailR with similar capabilities than gmailr but using smtp identification. I add my working code just in case it can be useful for someone.

library(mailR)
library(shiny)

send_achievements <- function(Name, Email){
  send.mail(from = "myemail@gmail.com",
            to = "otheremail@gmail.com",
            subject = "Subject of the email",
            html = TRUE, 
            body = HTML("Hello <b>",Name, "</b><br/>Updated <b>"), #Body accepts html, I use HTML #function from shiny package because I'm a noob yet but it is not necessary
            smtp = list(host.name = "smtp.gmail.com", port = 465, user.name = "myemail@gmail.com", passwd = "Mypasswd", ssl = TRUE),
            authenticate = TRUE,
            send = TRUE,
            attach.files = c(file.path(path_to_file,"name_of_the_file")) #Attach one or more files.
  )
}

Thank you again I will explore both options now.

sdisav commented 4 years ago

I ran into issues with mailR that prevented me from using it due to it's use of Apache Commons but it's not a bad option if it works for you.

jreid88 commented 4 years ago

Hi, I know this question has been answered but I am having a similar problem. I tried sdisav's suggestion above and I am still prompted to authenticate in the browser. Is there another step or change anyone else has made to resolve this?

r0bis commented 4 years ago

gmailr is all that is necessary. As it states in gmailr/readme - you download json credentials, authenticate once interactively and copy creds to wherever you like. Credentials you can get via python quickstart, or even better - by simply creating a project on https://console.developers.google.com, adding gmail API to it, then creating OAuth credentials for a desktop app. The benefit of the latter approach is you will know where all components are. You will download OAuth "client-secret" .json file into your project directory and call it credentials.json (or any other json name you like). Then you will once authenticate interactively running below commands from Rstudio where you are in your project directory:

gm_auth_configure(path  = "credentials.json")
gm_auth(email = TRUE, cache = ".secret")

A webpage will pop up with scary messages, but you will agree to all and from then on you will be using cache. Cache .secret that you just created (you can give whatever name you wish to that cache directory) is portable - you can copy that alongside your credentials.json over to your shiny-server. It is convenient that all is contained in your project directory. You will need two lines in your code after that - they should precede the command gm_send_message(yourpreparedemailwith_gm_mime) and no more interactive authentication is needed no matter which computer you have copied your project to as long as it has gmailr and gargle installed in R on your server:

gm_auth_configure(path  = "credentials.json")
options(
  gargle_oauth_cache = ".secret",
  gargle_oauth_email = "email_address_used_for_creds@gmail.com"
)
gm_auth(email = "email_address_used_for_creds@gmail.com")

# then compose your e-mail and send it

the last command allows to avoid dialogue for which account to use. This sometimes pops up on first use. Readme explains it well, this is rather an encouragement to read it.

Schumzy commented 3 years ago

cache = ".secret"

If anyone has similar issue, especially with running code via cron. This works.

So what I had to do was de-auth using gm_deauth(), then added this to my gm_auth() command, re-ran it and it allowed me to do the initial first authorization and got a new key and sent.

I kept it in, hopefully it will not revoke access again.

Mr-Hadoop-Hotshot commented 3 years ago

@sdisav Hey I tried your code it works well with the task scheduleR.

But it sends email every 3 minutes when scheduler is scheduled to run every "MINUTE".

For example my script log messages:

LOG REPORT MESSAGE AS FOLLOWS: 11:14 - Script scheduled successfully -Email ID generated in R - Email Received.

11:15 - Script scheduled successfully -Email ID generated in R - Email NOT Received.

11:16 - Script scheduled successfully -Email ID generated in R - Email NOT Received.

11:17 - Script scheduled successfully -Email ID generated in R - Email Received

Any idea guys?!?