Sending email with onBookmarked() creates several (server) bookmarks

I'm creating a shiny application where the user can save a bookmark and have the (server) bookmark url sent to their email. The problem is that once the bookmark is opened, another 1-3(!) emails (sometimes with a few minute delay) with new bookmark urls are sent even though I'm trying to isolate the necessary inputs from the bookmark call. There's no manual binding to session$doBookmark() so there shouldn't be anything else than the bookmark button triggering bookmarking unless there's something in onBookmarked(). I've tried to isolate() input calls in onBookmarked() just to be safe, but it doesn't seem to matter.

If the bookmark url is not opened, there will only be one email.

I can't reproduce this on my local windows machine. The problem only occurs when I deploy the app to a fresh Ubuntu EC2 virtual machine with the latest R and R packages.

The email includes two inputs, the email address and the projects name.

I'm using Sendgrid to send email and can't produce a general example with similar functions, but I hope someone might have an idea what I'm doing wrong.

It looks like extra bookmarks are not being made if the email part is commented out, but I'm not entirely sure.

I'm using a general bookmarkButton() with no id.

In the server part I have this (slightly generalized):

  onBookmarked({
    function(url) {
      email <- isolate(input$email)
      proj <- isolate(input$proj_name)
      send_email(email, proj, url) # a custom function that passes values to `sendgridr` package
      showModal(urlModal(url))
    }
  })
> sessionInfo()
R version 4.1.2 (2021-11-01)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 20.04.3 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0

locale:
 [1] LC_CTYPE=C.UTF-8       LC_NUMERIC=C           LC_TIME=C.UTF-8
 [4] LC_COLLATE=C.UTF-8     LC_MONETARY=C.UTF-8    LC_MESSAGES=C.UTF-8
 [7] LC_PAPER=C.UTF-8       LC_NAME=C              LC_ADDRESS=C
[10] LC_TELEPHONE=C         LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base

other attached packages:
[1] shiny_1.7.1

loaded via a namespace (and not attached):
 [1] compiler_4.1.2   ellipsis_0.3.2   magrittr_2.0.1   fastmap_1.1.0
 [5] R6_2.5.1         promises_1.2.0.1 later_1.3.0      htmltools_0.5.2
 [9] Rcpp_1.0.8       digest_0.6.29    xtable_1.8-4     httpuv_1.6.5
[13] lifecycle_1.0.1  mime_0.12        rlang_0.4.12

While writing this, I created another bookmark and after a while, clicked the link in my email. Another two bookmarks were created on the spot.

I ran some tests and I can't seem to get extra bookmarks made when I have no email sending in the code (send is commented out) but everything is otherwise the same. It really looks like there's something in the email sending, where basically a POST call is made to an API, and somehow that causes reverse triggering of session$doBookmark(). It's notable that the modal is never shown when extra emails are sent, it's only shown on the first time (when the button is actually pressed).

Moving the email send outside of onBookmarked() does not help either, spam is still sent (with unique server bookmark ids). In the code below the email send should only be triggered when the reactiveVal() URL has changed.

  URL <- reactiveVal()

  onBookmarked({
    function(url) {
      URL(url)
      showModal(urlModal(url))
    }
  })

  observe({
    email <- isolate(input$email)
    proj <- isolate(input$proj_name)
    url <- URL() # dependency only on the url

    send_email(email, proj, url)
  }) %>% bindEvent(URL())

Well this remain a mystery. The only workaround I've found is to exclude the email address from the bookmark. Even then I can see that the application is trying to send an email, but I can stop that by adding a step to check if there are more than zero characters in the address to an observe which should not even evaluate without a button press.

This observe will evaluate on bookmark restore without the nchar() check. It will also evaluate if I restore the email address via onRestored() with a few second delay. Bookmark button id is excluded from the bookmark.

I would think that I shouldn't even need to use isolate() in an observe that is bound with bindEvent() and also that there shouldn't be a need for ignoreInit = TRUE. A series of emails are send on restore in spite of them.

  observe({
    email <- isolate(input$email)
    req(nchar(email) > 0)

    proj <- isolate(input$proj_name)
    url <- isolate(URL())

    send_email(email, proj, url)
  }) %>% bindEvent(input$bookmark, ignoreInit = TRUE)
1 Like

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.