Get Google Drive file owner email address using Google Drive API V3 via python - google-drive-api

I'm having trouble getting the owner of a file on Google Drive via the Google Drive API v3.
I could do this under v2, but things have changed.
According to the documentation I need to:
List the permissions on a file (no problem)
Find Id of the permission with the 'owner' role from that list of permissions (no problem)
Get that permission ... which should return a permissions resource which should include the email address (problem!)
Unfortunately, what I'm getting back includes some of the information, but not the email address.
I suspect that I need to change my "get" call to tell the API which fields I'm after, but I can't see how to do this.
This is what I've got (v3):
from oauth2client.service_account import ServiceAccountCredentials
from httplib2 import Http
from apiclient.discovery import build
def build_service(user):
keyfile = 'C:\Python27\Scripts\Certificates for Transfer owner script\Transfer Ownership on Drive-f240cff252af.json'
SCOPE = 'https://www.googleapis.com/auth/drive'
credentials = ServiceAccountCredentials.from_json_keyfile_name(keyfile, scopes=SCOPE).create_delegated(user)
http_auth = credentials.authorize(Http())
return build('drive', 'v2', http=http_auth)
service = build_service('lpglobaldrive#lonelyplanet.com.au')
f = service.files().get(fileId='1lASRBuAHRxEC-T0X5SdlF3w7X_168Q2QV9L0V6QaXUk').execute()
p = service.permissions().get(fileId='1lASRBuAHRxEC-T0X5SdlF3w7X_168Q2QV9L0V6QaXUk',permissionId='18137907375963748644').execute()
currentOwner = p['emailAddress']
Unfortunately I get a "KeyError: 'emailAddress'" (and if I look at the contents of "p", there's role, kind, type and id, but no email Address).
This works for me (using v2):
from oauth2client.service_account import ServiceAccountCredentials
from httplib2 import Http
from apiclient.discovery import build
def build_service(user):
keyfile = 'C:\Python27\Scripts\Certificates for Transfer owner script\Transfer Ownership on Drive-f240cff252af.json'
SCOPE = 'https://www.googleapis.com/auth/drive'
credentials = ServiceAccountCredentials.from_json_keyfile_name(keyfile, scopes=SCOPE).create_delegated(user)
http_auth = credentials.authorize(Http())
return build('drive', 'v2', http=http_auth)
service = build_service('lpglobaldrive#lonelyplanet.com.au')
f = service.files().get(fileId='1lASRBuAHRxEC-T0X5SdlF3w7X_168Q2QV9L0V6QaXUk').execute()
currentOwner = f['owners'][0]['emailAddress']

Too simple ... just needed to add the following to the get call:
,fields='emailAddress'
i.e.
currentOwner = service.permissions().get(fileId='1lASRBuAHRxEC-T0X5SdlF3w7X_168Q2QV9L0V6QaXUk',permissionId='18137907375963748644',fields='emailAddress').execute()['emailAddress']

Related

How to get file information in google drive using google drive url in google drive api

Does anyone know if this is possible?
i think i can do it by extracting id from url.
then execute code like below.
service = build('drive', 'v3', credentials=creds)
# Call the Drive v3 API
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name,parents,owners)",q="'drive id' in parents"
).execute()
https://developers.google.com/drive/api/guides/search-files
however parsing url might fail sometime.
so i would like to know how to get file information in drive by specify url.
To ensure the parsing URL will not fail, you can use the findall function in regex in extracting the folder ID from the folder URL. Since the structure of the folder URL is static except for the id part, this pattern will guarantee the extraction of folder Id
Regex Pattern
"/folders\/(.*)\?resourcekey"
Please see sample code below for getting the files in a specific folder in my google drive
Code:
from googleapiclient.discovery import build
from google.colab import auth
from google.auth import default
import re
auth.authenticate_user()
creds, _ = default()
# Build the service
service = build('drive', 'v3', credentials=creds)
# Google drive folder's URL
folder_url = 'https://drive.google.com/corp/drive/folders/1bBWIXbinmb-DQ1z_fspsvxlw3vt8v6Wa?resourcekey=0-3Q_nXWmlLp_eG79NzcRe5w'
# Get the folder's ID from the URL using regex
folder_id = re.findall("/folders\/(.*)\?resourcekey", folder_url)
#query
query = f"'{folder_id[0]}' in parents"
# List the files in the folder
results = service.files().list(pageSize=10, fields="nextPageToken, files(id, name,parents,owners)",q=query).execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
print(u'{0} ({1})'.format(item['name'], item['id']))
Output:
Resources:
Search for files and folders
Regular Expression
https://regex101.com/

Google apps script for Gmail - broken email from inbox [duplicate]

This question already has an answer here:
Gmail AppScript mailMessage.getFrom() to return email not name
(1 answer)
Closed 2 years ago.
I have developed a Gmail add-on.
In that I will get the list of emails in from, to, cc and bcc with the help of GmailMessage class.
like for from email , GmailMessage.getFrom()
for to email, GmailMessage.getTo()
In the documentation it is stated that it will return an email as string but it is not clearly mentioned anywhere about the format of that string.
Sometimes I'm getting in the format of Name of the account<accountEmail#gmail.com>
and sometimes in the format of <accountEmail#gmail.com> and sometimes only name will be available without the email ID of the recepient.
Sometimes it also includes double quotes on the email like Name of the account<"accountEmail#gmail.com">
Can someone tell is there a way to get the exact email address and name separately from Gmail using Google apps script?
Or suggest some ways to parse the email from GmailMessage class and get email address and name separately
I found the the gmail api site (here) which might come in use if you end up using the code. Although the code is in python so it might not work on google app script, but the only reason to use google apps script is to achieve these results. You also are going to have to know what you are doing when using this(if you want to use google app script, try making a gmail app template then go here to learn the basics (here) and here for further documentation (here))
Replace CLIENTSECRETS_LOCATION value with the location of your client_secrets.json file.
import logging
from oauth2client.client import flow_from_clientsecrets
from oauth2client.client import FlowExchangeError
from apiclient.discovery import build
# ...
# Path to client_secrets.json which should contain a JSON document such as:
# {
# "web": {
# "client_id": "[[YOUR_CLIENT_ID]]",
# "client_secret": "[[YOUR_CLIENT_SECRET]]",
# "redirect_uris": [],
# "auth_uri": "https://accounts.google.com/o/oauth2/auth",
# "token_uri": "https://accounts.google.com/o/oauth2/token"
# }
# }
CLIENTSECRETS_LOCATION = '<PATH/TO/CLIENT_SECRETS.JSON>'
REDIRECT_URI = '<YOUR_REGISTERED_REDIRECT_URI>'
SCOPES = [
'https://www.googleapis.com/auth/gmail.readonly',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
# Add other requested scopes.
]
class GetCredentialsException(Exception):
"""Error raised when an error occurred while retrieving credentials.
Attributes:
authorization_url: Authorization URL to redirect the user to in order to
request offline access.
"""
def __init__(self, authorization_url):
"""Construct a GetCredentialsException."""
self.authorization_url = authorization_url
class CodeExchangeException(GetCredentialsException):
"""Error raised when a code exchange has failed."""
class NoRefreshTokenException(GetCredentialsException):
"""Error raised when no refresh token has been found."""
class NoUserIdException(Exception):
"""Error raised when no user ID could be retrieved."""
def get_stored_credentials(user_id):
"""Retrieved stored credentials for the provided user ID.
Args:
user_id: User's ID.
Returns:
Stored oauth2client.client.OAuth2Credentials if found, None otherwise.
Raises:
NotImplemented: This function has not been implemented.
"""
# TODO: Implement this function to work with your database.
# To instantiate an OAuth2Credentials instance from a Json
# representation, use the oauth2client.client.Credentials.new_from_json
# class method.
raise NotImplementedError()
def store_credentials(user_id, credentials):
"""Store OAuth 2.0 credentials in the application's database.
This function stores the provided OAuth 2.0 credentials using the user ID as
key.
Args:
user_id: User's ID.
credentials: OAuth 2.0 credentials to store.
Raises:
NotImplemented: This function has not been implemented.
"""
# TODO: Implement this function to work with your database.
# To retrieve a Json representation of the credentials instance, call the
# credentials.to_json() method.
raise NotImplementedError()
def exchange_code(authorization_code):
"""Exchange an authorization code for OAuth 2.0 credentials.
Args:
authorization_code: Authorization code to exchange for OAuth 2.0
credentials.
Returns:
oauth2client.client.OAuth2Credentials instance.
Raises:
CodeExchangeException: an error occurred.
"""
flow = flow_from_clientsecrets(CLIENTSECRETS_LOCATION, ' '.join(SCOPES))
flow.redirect_uri = REDIRECT_URI
try:
credentials = flow.step2_exchange(authorization_code)
return credentials
except FlowExchangeError, error:
logging.error('An error occurred: %s', error)
raise CodeExchangeException(None)
def get_user_info(credentials):
"""Send a request to the UserInfo API to retrieve the user's information.
Args:
credentials: oauth2client.client.OAuth2Credentials instance to authorize the
request.
Returns:
User information as a dict.
"""
user_info_service = build(
serviceName='oauth2', version='v2',
http=credentials.authorize(httplib2.Http()))
user_info = None
try:
user_info = user_info_service.userinfo().get().execute()
except errors.HttpError, e:
logging.error('An error occurred: %s', e)
if user_info and user_info.get('id'):
return user_info
else:
raise NoUserIdException()
def get_authorization_url(email_address, state):
"""Retrieve the authorization URL.
Args:
email_address: User's e-mail address.
state: State for the authorization URL.
Returns:
Authorization URL to redirect the user to.
"""
flow = flow_from_clientsecrets(CLIENTSECRETS_LOCATION, ' '.join(SCOPES))
flow.params['access_type'] = 'offline'
flow.params['approval_prompt'] = 'force'
flow.params['user_id'] = email_address
flow.params['state'] = state
return flow.step1_get_authorize_url(REDIRECT_URI)
def get_credentials(authorization_code, state):
"""Retrieve credentials using the provided authorization code.
This function exchanges the authorization code for an access token and queries
the UserInfo API to retrieve the user's e-mail address.
If a refresh token has been retrieved along with an access token, it is stored
in the application database using the user's e-mail address as key.
If no refresh token has been retrieved, the function checks in the application
database for one and returns it if found or raises a NoRefreshTokenException
with the authorization URL to redirect the user to.
Args:
authorization_code: Authorization code to use to retrieve an access token.
state: State to set to the authorization URL in case of error.
Returns:
oauth2client.client.OAuth2Credentials instance containing an access and
refresh token.
Raises:
CodeExchangeError: Could not exchange the authorization code.
NoRefreshTokenException: No refresh token could be retrieved from the
available sources.
"""
email_address = ''
try:
credentials = exchange_code(authorization_code)
user_info = get_user_info(credentials)
email_address = user_info.get('email')
user_id = user_info.get('id')
if credentials.refresh_token is not None:
store_credentials(user_id, credentials)
return credentials
else:
credentials = get_stored_credentials(user_id)
if credentials and credentials.refresh_token is not None:
return credentials
except CodeExchangeException, error:
logging.error('An error occurred during code exchange.')
# Drive apps should try to retrieve the user and credentials for the current
# session.
# If none is available, redirect the user to the authorization URL.
error.authorization_url = get_authorization_url(email_address, state)
raise error
except NoUserIdException:
logging.error('No user ID could be retrieved.')
# No refresh token has been retrieved.
authorization_url = get_authorization_url(email_address, state)
raise NoRefreshTokenException(authorization_url)

Change Google Drive file from public to private

I created a public File on my Google Drive, I used the v3 API from Google Drive on Python to get a list of all my files.
Now I want to change a file permissions so it would be private and can only be seen by me (owner)
from __future__ import print_function
from apiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
# Setup the Drive v3 API
SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly'
store = file.Storage('credentials.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('client_id.json', SCOPES)
creds = tools.run_flow(flow, store)
service = build('drive', 'v3', http=creds.authorize(Http()))
# Call the Drive v3 API
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name, modifiedTime, owners, permissions)").execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
print('{0} ({1}) ({2})'.format(item['name'], item['id'], item["modifiedTime"])
Cosa = items[2]
print("--- Archivo Publico ---")
print(Cosa["permissions"])
print("---- Modifico los Permisos ----")
service.permissions().delete(fileId="ExampleID",permissionId="anyone").execute()
Now, when I execute the code I get:
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/drive/v3/files/1KHjbcJkN79cccgwywrwsBHlOuLUgtOqXZk4gvZKR1eE/permissions/anyone? returned "Insufficient Permission">
Why? I´m the owner of the File.
edit: The file has 2 permissions. The first is "anyone" which let´s everyone see and edit the file. The second is my permission which makes me the owner. I'm trying to delete the first to make the file private
I had to change de SCOPE from:
SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly'
to
SCOPES = 'https://www.googleapis.com/auth/drive'
I also deleted my credentials.json and made the web authentication. It works as spected now

Automatically verifying gdrive app login in python program

I want to automatically verify my credentials without going to the link and pasting the verification code every time I run this program.
might storing credentials will work but I don't know how to store it and reuse it..
my code is given below
#!/usr/bin/python
import httplib2
import pprint
from apiclient.discovery import build
from apiclient.http import MediaFileUpload
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.file import Storage
# Copy your credentials from the console
CLIENT_ID = 'my_id' #i have client id but dont wanna share
CLIENT_SECRET = 'my_secret' #i have client secret but dont wanna share
# Check https://developers.google.com/drive/scopes for all available scopes
OAUTH_SCOPE = 'https://www.googleapis.com/auth/drive'
# Redirect URI for installed apps
REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob'
# Path to the file to upload
FILENAME = 'hello.txt'
# Run through the OAuth flow and retrieve credentials
flow = OAuth2WebServerFlow(CLIENT_ID, CLIENT_SECRET, OAUTH_SCOPE,
redirect_uri=REDIRECT_URI)
authorize_url = flow.step1_get_authorize_url()
print 'Go to the following link in your browser: ' + authorize_url
code = raw_input('Enter verification code: ').strip()
credentials = flow.step2_exchange(code)
# Create an httplib2.Http object and authorize it with our credentials
http = httplib2.Http()
http = credentials.authorize(http)
drive_service = build('drive', 'v2', http=http)
# Insert a file
media_body = MediaFileUpload(FILENAME, mimetype='text/plain', resumable=True)
body = {
'title': 'My document',
'description': 'A test document',
'mimeType': 'text/plain'
}
file = drive_service.files().insert(body=body, media_body=media_body).execute()
pprint.pprint(file)
any help is appreciated !
Here you can find the documentation on OAuth with python: https://developers.google.com/api-client-library/python/guide/aaa_oauth (edited url)
basically you will have to use self.redirect(authorize_url) to make that step automatically and then in the second step you will use flow.step2_exchange(self.request.params)
In the documentation will find a better explanation of the process.

Store access token from Google OAuth 2.0 to access drive data from application account

I am able to execute quickstart.py for Google Drive using python. But how do we store the token and use it again - again for the same user without prompting user. Is their some way i can map user with access token when sending request for file on Google drive.
There are many different Storage types offered by google-api-python-client, some of which are well documented.
Some examples:
oauth2client.file.Storage:
from oauth2client.file import Storage
...
storage = Storage('a_credentials_file')
storage.put(credentials)
...
credentials = storage.get()
oauth2client.keyring_storage.Storage:
from oauth2client.keyring_storage import Storage
...
storage = Storage('application name', 'user name')
storage.put(credentials)
...
credentials = storage.get()
oauth2client.appengine.StorageByKeyName:
from oauth2client.keyring_storage import StorageByKeyName
from oauth2client.keyring_storage import CredentialsNDBModel
...
storage = StorageByKeyName(CredentialsNDBModel, some_user_id, 'credentials')
storage.put(credentials)
...
credentials = storage.get()
oauth2client.django_orm.Storage:
from django.contrib.auth.models import User
from oauth2client.django_orm import Storage
from your_project.your_app.models import CredentialsModel
...
user = # A User object usually obtained from request.
storage = Storage(CredentialsModel, 'id', user, 'credential')
credential = storage.get()
...
storage.put(credential)
I think you should give credit to bossylobster for a more complete answer, but based on your comment, which is precisely my setup, I've augmented the quickstart.py using the Storage class:
#!/usr/bin/python
import httplib2
import pprint
from apiclient.discovery import build
from apiclient.http import MediaFileUpload
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.file import Storage
# Copy your credentials from the console
CLIENT_ID = 'PASTE_YOUR_ID'
CLIENT_SECRET = 'PASTE_YOUR_SECRET'
# Check https://developers.google.com/drive/scopes for all available scopes
OAUTH_SCOPE = 'https://www.googleapis.com/auth/drive'
# Redirect URI for installed apps
REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob'
# Create a credential storage object. You pick the filename.
storage = Storage('a_credentials_file')
# Attempt to load existing credentials. Null is returned if it fails.
credentials = storage.get()
# Only attempt to get new credentials if the load failed.
if not credentials:
# Run through the OAuth flow and retrieve credentials
flow = OAuth2WebServerFlow(CLIENT_ID, CLIENT_SECRET, OAUTH_SCOPE, REDIRECT_URI)
authorize_url = flow.step1_get_authorize_url()
print 'Go to the following link in your browser: ' + authorize_url
code = raw_input('Enter verification code: ').strip()
credentials = flow.step2_exchange(code)
storage.put(credentials)
# Create an httplib2.Http object and authorize it with our credentials
http = httplib2.Http()
http = credentials.authorize(http)
drive_service = build('drive', 'v2', http=http)
# Use 'drive_service' for all of the API calls