Search code examples
pythongoogle-sheetsgoogle-drive-apigoogle-sheets-apigspread

Transfer google sheets file ownership from service account to domain email address with gspread


In the example code below, I perform the following:

  1. connect to my google service account
  2. copy one of the google sheets files the service account has access to
  3. share that copy with a user specified by EMAIL
  4. transfer ownership of the copy to the user specified by EMAIL

This code works as expected when EMAIL is an @gmail.com address. When the email address is an @domain.com address (that is still using gmail, just not the @gmail address), the .transfer_ownership() line (step 4) fails.

Reproducible example:

# Step 1: Connect to your service account
gc = gspread.service_account("insert_path_to_credentials.json")

# Please replace this string with the spreadsheet id of any sheet the service account can access
KEY = "########"

# Step 2: Copy the spreadsheet
ss_copy = gc.copy(file_id=KEY)

# Please replace this string with the email address you wish to share with
EMAIL = "emailaddress@domain.com"

# Step 3: Share the copy with the user specified by EMAIL
response = ss_copy.share(email_address=EMAIL, 
                         perm_type="user", 
                         role="writer", 
                         notify=True)

# Step 4: Transfer ownership of the copy to the user specified by EMAIL
# This fails if EMAIL is an @domain.com address where domain may
# be the name of some business that uses gmail, but address is not @gmail 
permission_id = response.json()["id"]
transfer_response = ss_copy.transfer_ownership(permission_id)

Error during Step 4 when EMAIL is an @domain.com address:

APIError: {'code': 403, 'message': 'The target user cannot be a pending owner on this file.', 'errors': [{'message': 'The target user cannot be a pending owner on this file.', 'domain': 'global', 'reason': 'targetUserCannotBePendingOwnerOnFile'}]}

What is the correct method of using gspread to transfer ownership of a google sheet from a service account to a person using an @domain.com email address?

If this cannot be done using gspread, what is the simplest method to transfer ownership of a google sheets file from a service account to any arbitrary email address?


Solution

  • The problem you are currently having is not related to the API or the Gspread library. The problem is with how Google Drive Works since you cannot transfer the file ownership to a different domain. You can review this information in this Documentation:

    Known limitations and alternatives:

    You can't transfer ownership to or from an external user, such as a personal Google Account or a user in another organization. This limitation is to protect user and company data from unauthorized transfer and access. Depending on your organization’s sharing policies, you may be able to use the following alternatives.

    The workarounds will depend if you have access to the Workspace account (@domain.com email address) or not.

    If you have access to the Workspace account, you can share the file owned by the services account with the user. After that, create a new services account under the domain, impersonate the user, and make a copy of the file. You can see an example of making a copy in GSpread here

    Or add the file to a Share File, both of those alternatives can be found in the same documentation.