onEdit event object active user is returning my email address instead of the user doing the edit - google-apps-script

I have a Google sheet with an installed trigger / app script. The script uses the event object (I call it e) to do various things. One thing I am trying is to get the email address of the user who is doing the editing of the Google sheets. So, if the event object is e, the e.user should return the user id / email address of the person logged into the Google sheet and performing the action. But, what it does instead do is return MY email address. I'm guessing the e.user id is the id of the user the app script is running under. Can any Google engineers chime in? How can I get the user id of the person doing the editing?

Ok, wow, I finally got this working, and that was a weird one. So, if the trigger is installable as opposed to simple, and the users doing the editing belong to my same domain, then the e.user should work. It wasn't. What I eventually figured out is when one of the shared collaborators opens up the apps script editor from the container, for some reason, everything started working. So, I'm now able to get the user id's and emails from all the users in my domain when they perform an action. It seems like this is a bug. I dunno. But it works now.

You can obtain the User's Email with e.user.getEmail();
Here's the documentation comment:
getEmail()
Gets the user's email address, if available. If security policies do not allow access to the user's email address, this method returns a blank string. The circumstances in which the email address is available vary: for example, the user's email address is not available in any context that allows a script to run without that user's authorization, like a simple onOpen(e) or onEdit(e) trigger, a custom function in Google Sheets, or a web app deployed to "execute as me" (that is, authorized by the developer instead of the user). However, these restrictions generally do not apply if the developer runs the script themselves or belongs to the same G Suite domain as the user.

Related

Differentiate User and Owner Info in Apps Script Installable Trigger

When I call Session.getActiveUser() from a function called by an installable trigger (e.g. an OnOpen Event trigger in Google Sheets - but not the Simple Trigger) in Apps Script, what user information am I getting?
I understand that installable triggers run under the owner/creator of the trigger regardless of who has opened the sheet. So would this always return that person's info?
Either way, how do I get the information of the other person? (e.g. if it gives owner info, how do I get the info of the user actually opening it - and vice-versa)
Update:
I got another user to test my script. I watched the logs while they were in the file, and it definitely reported THEM as the user, even when the installable OnOpen trigger was triggered.
This is good from the perspective that it showed them the correct menu options - he and I saw different menus per my OnOpen script, which is what I want.
However, this raises two issues for me:
This seems to go against the Google Documentation, which states: "Installable triggers always run under the account of the person who created them. For example, if you create an installable open trigger, it runs when your colleague opens the document (if your colleague has edit access), but it runs as your account. This means that if you create a trigger to send an email when a document is opened, the email is always sent from your account, not necessarily the account that opened the document."
In a future function, I will be calling an API from another App. This API will need my credentials (API ID and Secret). I was hoping / expecting that I could "sandbox" my credentials in an installable trigger - invisible to other users - that will allow them to use my credentials just for the specific functions which I would script into the API. If the installable trigger is in fact, NOT using my credentials, then how can I do this? I don't want to have to make every user go to the other App and generate their own set of API credentials, that will be unsustainable in this organization, and not everyone should need to do that.
It should return whomever triggered the script. But it depends if the security policy does allow you to access the user's identity. Seeing the documentation:
Gets information about the current user. If security policies do not allow access to the user's identity, User.getEmail() returns a blank string. The circumstances in which the email address is available vary: for example, the user's email address is not available in any context that allows a script to run without that user's authorization, like a simple onOpen(e) or onEdit(e) trigger, a custom function in Google Sheets, or a web app deployed to "execute as me" (that is, authorized by the developer instead of the user).
I have tested it and even an installable trigger won't return anything if it belongs to a different organization.
But you might be able to if other users belong to the same organization.
However, these restrictions generally do not apply if the developer runs the script themselves or belongs to the same Google Workspace domain as the user.
Workaround:
One thing I guess would be to assign the triggered function into a button and have the users click that upon opening the sheet. Via clicking the button, I have been able to show the User object using that method.
Or a webapp that will serve as a relay and will get the User details.

MailApp.sendEmail() not sending from current user

I have an onEdit triggered appscript that grabs data from a spreadsheet, formats it and then sends it to an email address. Typically these messages would be sent 'from' the user that is triggering the script to run. However, I am experiencing strange behavior where the current user is not used to send the message - or used inconsistently.
A couple of notes:
Occasionally the message is sent by the current user, other times it is not (in those cases it comes from my account, which created the script)
Script trigger is an 'onEdit' script which monitors the sheet for a checkbox status change
Spreadsheet is in a Shared Drive
We are using Google apps for education
The recipient address is a mailing list tool. When I list a different email address as the recipient (internal, external, other) the message consistently comes from the current user as expected. I've no idea why the recipient would affect how Google sends the message.
I realize i could use the GmailApp library to send instead, but want to avoid the re-authorizations that are mentioned.

Getting all viewers of spreadsheet using App Script

i wrote code for getting all viewers of spreadsheet in app script .
i have used getViewers() method to get viewers names who actually viewed it. but that method is returning me the names of people to whom i actually shared the spreadsheet....
is there any other way that i can get all viewers of spreadsheet.?
is there any web automation tools that can solve my problem?
Answer:
It is not possible to get a list of people that have opened your a Google Drive file using Google Apps Script - a method that returns this list does not exist. The getViewers() method returns the list of people with view and comment permissions for a file, while getEditors() retrieves the list of people that have edit permissions.
The Issue:
is there any other way that i can get all viewers of spreadsheet.? is there any web automation tools that can solve my problem?
There is no way of getting viewers of a Google Sheet as this is a huge security issue. This information is not stored and is therefore not retrievable.
Workaround:
You can make a custom function which stores the username of a person when they open the file - though be aware that triggers have restrictions and will only run if the person opening the file has edit access. I have included a list of Apps Script Trigger Restrictions below for you to look through and decide what is the best approach for you.
Code:
function onOpen(e) {
var user = e.user.getEmail();
// do some code to store or save this parameter
// for example save it to a hidden sheet or email it to yourself
// though an email would require an installable trigger to be made
}
Simple Trigger Restrictions:
These are not all of the restrictions (full restrictions are available here), but these are the ones that I believe to be most relevant for you.
As per the Google Apps Script Simple Triggers documentation:
They do not run if a file is opened in read-only (view or comment) mode.
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.
They can modify the file they are bound to, but cannot access other files because that would require authorization.
They may or may not be able to determine the identity of the current user, depending on a complex set of security restrictions.
This last point is important - getting information about the current user is possible depending on the security policies of the the G Suite domain. A detailed explanation of this can be found in the getActiveUser() method documentation:
If security policies do not allow access to the user's identity, User.getEmail() returns a blank string. The circumstances in which the email address is available vary: for example, the user's email address is not available in any context that allows a script to run without that user's authorization, like a simple onOpen(e) or onEdit(e) trigger, a custom function in Google Sheets, or a web app deployed to "execute as me" (that is, authorized by the developer instead of the user). However, these restrictions generally do not apply if the developer runs the script themselves or belongs to the same G Suite domain as the user.
There are big security issues with getting a list of people that have viewed a file, for good reason, and so what you are looking to do it highly restricted by Google.
References:
Class File of Google Apps Script
getViewers() method of Class File
getEditors() method of Class File
Simple Triggers
onOpen(e) Trigger
Simple Trigger Restrictions
Installable Triggers
Event objects
Class User of Apps Script
User.getEmail() method
Class Session
getActiveUser() method of Session Class

(How) can I publish a Google Sheet and associated Google Apps Script organization-wide and avoid or suppress authorization prompts?

Our organization uses Google Apps for Work. We have a Google Sheet "form" for employees/users to complete. After entering information, users are expected to use email as attachment/PDF. Finally, users click a "button" near the bottom of the sheet that triggers a script to clear user data. The first time a user clicks the button, an "Authorization Required" prompt appears, informing the user "the application" (script) "needs authorization to run." If approved, the prompt goes on to request View and manage your spreadsheets in Google Drive permissions for the script.
Is it possible to digitally sign or otherwise pre-approve a Google Apps Script for all users in a Google Apps organization so this prompt doesn't appear? We can/will include instructions for users, to head off questions / allay fear, but many of our users will either ignore or not understand the instructions and be perplexed.
I'm open to (and exploring) other options for tackling this (Google Forms/Sheets?), but prefer to stay in the (native) Google Apps environment as much as possible.
I couldn't find this question elsewhere and as best as I can tell, it isn't answered in Google Apps Script documentation.
I have found no way to pre-approve an organization/group/individual without manually doing it for each account.
You CAN deploy the script using a service account and have it run as that account. Then you are authorizing that account and the end user's accounts do not come into play. The drawback is that if you want the emails to go out using the end user's email, it won't happen. Plus the sending of the email would have to be from code in the app. That means all emails would go out using the service account's email address. (Although I am now wondering if it is possible to initiate the email without sending it. Basically pop it up as if a mailto link was clicked.)
You also will not be able to get the end user's name, etc. If these items are not important, or you can trust them to fill out their name where it may be needed (you could change the From name to what they key in) then running as the service account may work for you.
Karl

Google Apps Script - I am unable to retrieve user's email address when add-on is published

The following code works before I publish the G docs add-on. However the released version obtained via Google Docs Add-on/my_add-on doesn't work.
What concepts am I missing here?
onOpen(){
var email = Session.getActiveUser().getEmail();
}
The documentation explicitly states that:
If security policies do not allow access to the user's identity,
User.getEmail() returns a blank string. The circumstances in which the
email address is available vary: for example, the user's email address
is not available in any context that allows a script to run without
that user's authorization, like a simple onOpen(e) or onEdit(e)
trigger, a custom function in Google Sheets, or a web app deployed to
"execute as me" (that is, authorized by the developer instead of the
user). However, these restrictions generally do not apply if the
developer and the user belong to the same Google Apps for Business
domain.
So presumably your script fails to meet those conditions.
You need to run a function that the user has to authorize first in order to get their email.