What is the recommended way to access shared *personal* calendars in EWS? - exchangewebservices

I am using Exchangelib with service account credentials to impersonate individual EWS users. I am able to retrieve a list of calendars the user has access to, but this list does not include personal calendars shared with the user.
Example: Jane has a default calendar named "Calendar", and they share this calendar with Bill. Jane also has a second calendar they created and shared with Bill named "Interviews".
When I list Bill's calendars, I can only see the "Interviews" calendar - Jane's default calendar is not listed.
I am iterating over the Account() object's calendar.children:
>>> ews_account = Account(
primary_smtp_address=XXXXX,
config=XXXXX,
autodiscover=False,
access_type=IMPERSONATION,
)
>>> for calendar in ews_account.calendar.children:
>>> print(calendar.name)
"Interviews"
Is there a different way to find out that Jane has shared her personal calendar with Bill?
It looks like there's a method to send the calendar ID along with Jane's email address to see if it's shared with Bill, but I'm hoping for a way to list all of these without knowing the calendar ID and email address in advance.
These personal calendars were shared with "delegate" level access, but I also tried sharing with "Can Edit" access.

I was able to solve the problem in a slightly different way with this code based on the Stackoverflow answer.
First I instantiate the base account using IMPERSONATION, and then I use GetFolder using the account context of the original account, and setting mailbox to the other user's email address.
For this to work, you have to know the email address of the owner of the shared calendar, which is not ideal. In the comments, Glen Scales indicates you can look up these shared calendars directly on the original account using NavLinks but I wasn't able to figure that out: EWS - Access All Shared Calendars
from exchangelib import (
IMPERSONATION,
Account,
Configuration,
Mailbox,
folders
)
from exchangelib.fields import FieldPath
from exchangelib.items import ID_ONLY
from exchangelib.services import GetFolder
account = Account(
primary_smtp_address="test#example.com",
config=Configuration(
server=...,
credentials=...,
),
autodiscover=True,
access_type=IMPERSONATION,
)
shared_calendar = next(
GetFolder(account=account).call(
folders=[
folders.DistinguishedFolderId(
id=folders.Calendar.DISTINGUISHED_FOLDER_ID,
mailbox=Mailbox(
email_address="other_user#example.com"
),
)
],
additional_fields={
FieldPath(field=field)
for field in account.calendar.supported_fields(
version=account.version
)
},
shape=ID_ONLY,
)
)

Related

How to store organization specific configuration values in properties?

I'm developing a Gmail Add On with Google Apps Script, which is intended to be used only by enterprise accounts (Google Workspace Accounts).
One of the requirements of the app is that when the Admin installs the app for all its users, they have to configure some organization wide configuration values (a license key for example).
I tried with the following code:
const userProperties = PropertiesService.getUserProperties();
userProperties.setProperty('licenseKey', '[TOKEN]');
But when I do this, the data is only accessible for the current user (and therefore I would need every user to know this key in order to save it on the configuration variables). I'm looking for an option in that a user saves this setting variable and then everyone on the domain can read the saved value.

Classroom.profiles.get returns 'User does not have permission'

I am trying to write a simple function to get all the students names and email addresses for a given class. The students have a mixture of mydomain.ac.uk and gmail.com. The students that have a mydomain.ac.uk address all return without problem, but if the student has a gmail account, I get the error 'The caller does not have permission'.
If I view the People tab of the course using the same superAdmin account that runs the code, I can see all of the students names and can email them. How do I get my code to return the userProfile of these gmail account users?
var sEmail = Classroom.UserProfiles.get({'userId' : '111294713083730379429'}).emailAddress
If I can see this information in the Classroom, why can't I access the same information in my code?
From the question
If I can see this information in the Classroom, why can't I access the same information in my code?
Only Google can answer why. Please bear in mind that the user profile data for #gmail.com is stored on an external domain, gmail.com.
I suggest you to checkout the Google Classroom Issue Tracker if there is already an issue about this "feature".

Is there a way to get Group Guests using the calendar service in Google Apps Script?

I am writing a tool in Google Sheets to analyze my work calendar and I just noticed that if I invite a "Group" (of 23 people) it only shows up as a single guest in the calendar data. Is there a way to get access to the e-mails of the people in the group?
From my research I know there is a Groups service but I'm not sure how to even recognize that it's a group. It looks like a normal e-mail address in the calendar: "management_team#gmail.com". (I could search for that specific group name, but I'm looking for a universal solution, so I can share this tool with others.)
Any suggestions will be appreciated. Thank you.
To verify either an email is a group and to retrieve its members you need to use the Admin SDK method Groups:get
But in order to use the Admin SDK you need to be a domain admin.
Each person who uses my tool will need their own copy and they will have to enter their calendar e-mail address. (The first time they run the tool there's a rather scary permissions message, but I will only be sharing this with some office mates so that should be okay.)
When my program runs I'll use this command:
var groups = GroupsApp.getGroups();
... to get a list of all the groups to which that person belongs. (I'll also have arrays for the members of each group.) Then I'll just compare the group names against the meeting guest names. If there's a match I can pretty easily retrieve the whole list.

Retrieve the list of users in a Google Apps Domain with a non-admin account

Is it possible to retrieve the list of users in a Google Apps Domain with a non-admin account?
Non-admin users can call users.list(viewType=domain_public) which offers the same amount of details that the users see in the domain contacts directory.
Depends on what you think an admin account is.
Long ago the user roles were just "regular" and "admin". Now you can choose from a fine-grained set of permissions and define a role name for them. "Superadmin" is now a built-in role that has every permission possible.
So, if you define a role which can retrieve the user list and assign it to a user I wouldn't call it an admin account.
You need to be a true admin to do that, though :)
As a complement to the other (excellent) answer, what I do in our domain is to create a full list of domain users in a spreadsheet with all necessary informations and run a script every night that updates the spreadsheet automatically. When I make a change (add or remove user) I can run the script manually to avoid temporary differences.
This script runs as "me" but any domain user has access to the list (I invite them to this shared doc when I create their account so it shows up in their drive/shared with me folder). With this solution I don't need to give special rights to any users.

Google Contacts API's and scope?

Currently i'm trying to retrieve all of a users contact information as well as retrieve their unique User ID.
Our app needs to utilise a users google contacts and the user will sign in using google. Thus we require some way of identifying each unique user (most likely a unique user id provided by google)
Is this possible only using the google contacts API.
The initial call I make to retrieve an access token is:
"https://accounts.google.com/o/oauth2/auth?client_id=51672309258-94cnvnrkrverd72neakom9d3siscda5o.apps.googleusercontent.com&redirect_uri=http://localhost/lunch/oauth.php&scope=https://www.google.com/m8/feeds/&response_type=code"
However I do not believe the access token returned from this call has any information for user ID and, also, does not provide the permissions to retrieve User ID from the Google+ Api.
Is there anyway that one can obtain a unique user ID from the google contacts API? There are examples of obtaining a user id of the users contacts but I need to obtain the actual users ID (i.e. the user whose contacts I am obtaining)?
Does this require another scope or can this also be accomplished by using the contacts API?
You can identify a user by his/her email address, which is unique AFAIK. When you issue requests to google contacts api you get a field in the xml which is called Id, that is the user's email address.
For example you could ask for all contacts and you would get an xml like this .The Id field is what you want, and depending on the programming language, lib , etc you are using you can get it with your existing permissions. For example in C# and gdata you would do something like this(googleCredentials is supposed to be your object):
var cr = new ContactsRequest(settings);
var feed = cr.GetGroups();
googleCredentials.Email = feed.AtomFeed.Id.Uri.Content;
Note: The special userEmail value default can be used to refer to the
authenticated user.
from the documentation documentation. You may try the keyword default as userEmail.