0

I would like to better clarify the question I have written. I am attempting to write an add-on that does the following:

When this add-on is installed in a document, I want it to send the user an email every time the document is opened, with the information of who opened the document. I have much more detail about my previous attempts below, but the big question is this: Is there a way for me to accomplish this?

Thanks to everyone who has helped.

I am working to write a Google Apps Script add-on that, once installed in a document, will execute a function to send an e-mail to the effective user every time the document is opened. What I am currently doing is the following:

function onInstall (e)
{
  onOpen (e)
}

function onOpen (e)
{
  if (/*Some Code*/)
  {
    DocumentApp.getUi().createAddonMenu()
      .addItem('Start Notification', 'myFunction')
      .addToUi();
  }

  else
  {
    myFunction ();
  }
}

In that if statement, I have tried a few different things:

e.authMode == ScriptApp.AuthMode.NONE

did not seem to work quite right- although I did get the menu the way it was intended, the function did not execute when someone else opened the document. I think this is because for them, the authorization mode is also NONE, so it would merely run the if, not the else. So I tried this instead:

e.authMode == ScriptApp.AuthMode.NONE && Session.getEffectiveUser().getEmail() == ""

But that didn't work either. Again, I was able to see the add-on menu, and when I clicked the button to activate the code I can verify that 'myFunction' did indeed run, but it didn't execute myFunction() when someone else opened the document. I'm open to ideas and suggestions!

Here is myFunction ()

function myFunction() {
  var doc = DocumentApp.getActiveDocument().getName();
  var userEmail = Session.getEffectiveUser().getEmail();
  var openerEmail = Session.getActiveUser().getEmail();
  if (openerEmail != userEmail) {
     GmailApp.sendEmail(userEmail, doc + ' opened', openerEmail + " opened the document.");
  }
}

And one more addition, per the second response given: I was originally using this code, and pasting it into all of my documents. Because this is only used for users within my domain, it worked perfectly fine. Is there any way around this?

function myFunction() {
  var email = Session.getActiveUser();
  if (email != 'myEmail@domain.org') {
    GmailApp.sendEmail('myEmail@domain.org', 'Document opened', email + " opened your document.");
  }
}

function triggerBuilder ()
{
  var doc = DocumentApp.getActiveDocument();
  ScriptApp.newTrigger (myFunction)
    .forDocument(doc)
    .onOpen()
    .create();
}

I would just run the trigger builder to make the installable trigger, or do it manually.

Some more info: I tested the following code, and found that when run, I was able to see the information when I myself opened the document, but not when someone else did. It seems that the onOpen(e) method may not have worked at all, as it did not appear in the Project Executions page either.

function onInstall (e)
{
  onOpen (e);
}

function onOpen (e)
{
  if (Session.getEffectiveUser().getEmail() == "")
  {
    DocumentApp.getUi().createMenu("Notification Test")
      .addItem("Run function", 'myFunction')
      .addToUi();
  }
  else
    myFunction ();
}

function myFunction ()
{
  Logger.log ("This is verification that the document was opened.");
  Logger.log("Current user: " + Session.getActiveUser().getEmail());
}
Lle.4
  • 516
  • 4
  • 17
  • It would help to check which Auth Mode it's running under. Try adding this at the top of your onOpen function before the `if` block: `Logger.log("Auth mode is: " + e.authMode)`. Then open the document yourself or have someone else do it and see what mode it's running in. There's more info here: https://developers.google.com/gsuite/add-ons/concepts/addon-authorization – e__n Jan 03 '19 at 23:14
  • That is a good suggestion, thank you. So from what I have gleaned: When the add-on gets installed, it runs under FULL (as shown in the documentation as well), but this actually means it runs the else statement when installed. When it has been installed but not enabled, it runs as NONE, and when it has been installed and enabled, it runs under LIMITED. Sadly, I don't think this will be too much help to me (except perhaps with the FULL authorization). Any other ideas? – Lle.4 Jan 04 '19 at 01:27
  • 2
    What are you trying to do in `myFunction`? And what isn't it allowing you to do currently that you're trying to do? Not exactly clear here. You can't access user data in NONE or LIMITED auth modes so it won't let you run a function that tries to access user data, e.g. spreadsheet cells. – e__n Jan 04 '19 at 01:40
  • myFunction is just sending an email out with some user data... but I had it accessing the ui interface, which may not have been allowed in the scope of the program. I will try changing it for that now. If it still doesn't work, I'll upload the actual code segment tomorrow. – Lle.4 Jan 04 '19 at 01:49
  • 1
    Possible duplicate of [Apps-Script email permissions approved in script editor, but not in sheet?](https://stackoverflow.com/questions/34645966/apps-script-email-permissions-approved-in-script-editor-but-not-in-sheet) – Rubén Jan 04 '19 at 05:24

2 Answers2

1

From Simple Triggers > Restrictions (emphasis mine)

They cannot access services that require authorization. For example, a simple trigger cannot send an email because the Gmail service requires authorization, but a simple trigger can translate a phrase with the Language service, which is anonymous.

The workaround is to use an installable on open trigger instead of a simple trigger.

Related

Rubén
  • 34,714
  • 9
  • 70
  • 166
  • Oh that makes sense... although it is rather unfortunate. Is there any way around this? I will post myFunction in an edited version of the original question. – Lle.4 Jan 04 '19 at 14:06
0

It is not just about authorization. You can only run certain functions from onOpen, i.e. functions that don't require user data. This is for security; otherwise you could share a link to your spreadsheet that when opened (and authorized) sends you the contents of the users Google drive.

Right now you are already trying to send an email documenting every person's opening of an email. The restrictions on onOpen are meant for this very situation. You shouldn't be able to access someone's email address simply because they opened your spreadsheet, even if they authorize it -- the user needs to interact with your spreadsheet more deliberately, such as opening a menu item, before you can access their info. Your intentions may be benign, but imagine this installed as an add-on. The best you can do is log a 'user key' to the console using Session.getTemporaryActiveUserKey(), which should be allowed in the restricted auth mode.

The somewhat vague documentation, with emphasis.

An editor add-on automatically runs its onOpen(e) function to add menu items when a document opens—but to protect users' data, Apps Script restricts what the onOpen(e) function can do. If the add-on hasn't been used in the current document, these restrictions become more severe.

e__n
  • 697
  • 7
  • 11
  • But then a question about this... I'm pretty sure that within a specific domain for an organization (which is what I am using this with) you have access to Session.getActiveUser().getEmail(), which I have actually used in the past- just not as an add-on. What I have done is actually written a few other lines of code (I will put them in my original question now) and used that with an installable trigger. I am merely trying to make this application more user-friendly so that one doesn't have to put the code in the Script Editor. Any suggestions for how to get around this? – Lle.4 Jan 04 '19 at 19:43
  • You might have access to `Session.getActiveUser().getEmail()` in other contexts but not inside an `onOpen` function (whether or not it's written as a function or an installed trigger). Why don't you test your onOpen functions as a simple Log output to see if it works and then using `Session.getActiveUser().getEmail()`, and see if it still works. – e__n Jan 04 '19 at 20:00
  • Ok, I will try a few things and then get back to you with what I find out. – Lle.4 Jan 04 '19 at 20:37