datawookie / emayili

An R package for sending email messages.
https://datawookie.github.io/emayili/
177 stars 27 forks source link

plumber using promises::future_promise #136

Closed riskcede closed 1 year ago

riskcede commented 2 years ago

Description of the bug

Hi Andrew

I've been using Emayili for a while and it works perfectly, thank you.

I've recently updated my plumber script that sends out an email at the end to use the new future_promise to run multiple requests in parallel. But this provides an error when I try to send out the email.

"Unhandled promise error: argument str should be a character vector (or an object coercible to) <simpleError in stri_detect_regex(string, pattern, negate = negate, opts_regex = opts(pattern)): argument str should be a character vector (or an object coercible to)>"

I'm not sure if this is an emayili of promise issue.

Can you please advise if I should be using the envelope function differently?

Thanks in advance

Regards Jan

Steps To Reproduce

Here is the script. It works perfect, but the moment i uncomment the future_promise code it stops working.

# TEST PLUMBER EMAYILI APIs ----
library(plumber)
library(future)
library(promises)
plan(multisession)

#* @get /email_out
function(){

  # promises::future_promise({

    library(tidyverse)       
    library(emayili)
    library(curl)

      smtp <- emayili::server(host = "smtp.gmail.com",
                              port = 465,
                              username = "xxxxxxxxx",
                              password = "xxxxxxxxx")

    envelope() %>%
        from("xxxxxxxxx") %>%
        to('xxxxxxxxx') %>%
        subject("test email from api") %>%
        smtp(verbose = FALSE)

  # })
}
datawookie commented 2 years ago

Hi @riskcede,

This is an interesting error.

Firstly I observed that the error only occurs with the multisession plan. With multicore your code works fine.

By trial and error I discovered that I needed to be explicit about the package for the envelope() and subject() calls. Here's the revised code, which works for me. Note that I have factored out the username and password into environment variables.

library(plumber)
library(future)
library(promises)
library(magrittr)
library(emayili)

plan(multisession)

USERNAME <- Sys.getenv("SMTP_USERNAME")
PASSWORD <- Sys.getenv("SMTP_PASSWORD")

#* @get /email_out
function(){
  promises::future_promise({
    smtp <- emayili::server(
      host = "smtp.gmail.com",
      port = 465,
      username = USERNAME,
      password = PASSWORD
    )

    emayili::envelope() %>%
      from(USERNAME) %>%
      to(USERNAME) %>%
      emayili::subject("test email from api") %>%
      smtp(verbose = FALSE)
  })
}

I am not sure why this is necessary. TBH I don't have much experience with {promises}.

However, a useful observation is that this does not seem to be a problem with {plumber} but rather with {promises}.

The following code also generates an error.

flibrary(future)
library(promises)
library(emayili)

plan(multisession)

future_promise({
  envelope
})

But this runs fine.

library(future)
library(promises)
library(emayili)

plan(multicore)

future_promise({
  envelope
})

So, on the one hand it seems to be something to do with the way that the promise is being handled (relating to multicore versus multisession plan) but it also seems to be specific to the envelope() function because other functions do now result in an error (for example, replace envelope with sqrt).

Thanks, Andrew.

riskcede commented 2 years ago

Hi Andrew

So was this just a namespace issue?

Ive changed to a multicore plan and it works perfect.

Thanks!!!!!

Regards Jan

On 2022 Jul 01, at 07:10, Andrew Collier @.***> wrote:

Hi @riskcede https://github.com/riskcede,

This is an interesting error.

Firstly I observed that the error only occurs with the multisession plan. With multicore your code works fine.

By trial and error I discovered that I needed to be explicit about the package for the envelope() and subject() calls. Here's the revised code, which works for me. Note that I have factored out the username and password into environment variables.

library(plumber) library(future) library(promises) library(magrittr) library(emayili)

plan(multisession)

USERNAME <- Sys.getenv("SMTP_USERNAME") PASSWORD <- Sys.getenv("SMTP_PASSWORD")

* @get /email_out

function(){ promises::future_promise({ smtp <- emayili::server( host = "smtp.gmail.com", port = 465, username = USERNAME, password = PASSWORD )

emayili::envelope() %>%
  from(USERNAME) %>%
  to(USERNAME) %>%
  emayili::subject("test email from api") %>%
  smtp(verbose = FALSE)

}) } Thanks, Andrew.

— Reply to this email directly, view it on GitHub https://github.com/datawookie/emayili/issues/136#issuecomment-1171942354, or unsubscribe https://github.com/notifications/unsubscribe-auth/AMU6SXGHRDK3JOH4MC3O6BDVRZ4T7ANCNFSM52LFMIBQ. You are receiving this because you were mentioned.