You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google Workspace用户邮箱使用报告代码HttpError 400报错排查

问题描述

执行Python代码调用Google Admin Directory API获取用户邮箱信息时,在users = service.users().list().execute()处抛出400错误:

HttpError 400 when requesting https://admin.googleapis.com/admin/directory/v1/users?alt=json returned "Bad Request". Details: "[{'message': 'Bad Request', 'domain': 'global', 'reason': 'badRequest'}]"

完整代码如下:

from __future__ import print_function
import os.path
import csv
import io
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build

# If modifying these scopes, delete the file token.json.
#SCOPES = ['https://www.googleapis.com/auth/admin.directory.user.readonly']
SCOPES = ['https://admin.googleapis.com/admin/directory/v1/users']

creds = None
    # The file token.json stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
    # If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.json', 'w') as token:
            token.write(creds.to_json())

service = build('admin', 'directory_v1', credentials=creds)
print('Getting users in the domain')
users = service.users().list().execute()

    # Create a dictionary to store the user data.
user_data = {}

    # Iterate over the list of users and get their first name, last name, and mailbox size.
for user in users[\"users\"]:
        user_data[user[\"primaryEmail\"]] = {
        \"firstName\": user[\"name\"][\"givenName\"],
        \"lastName\": user[\"name\"][\"familyName\"],
        \"mailboxSize\": user[\"storage\"][\"quotaUsage\"],
    }

# Open the CSV file for writing.
with open(\"user_data.csv\", \"w\", newline=\"\") as f:
    writer = csv.writer(f)

    # Write the header row.
    writer.writerow([\"email\", \"firstName\", \"lastName\", \"mailboxSize\"])

    # Iterate over the user data and write each user's data to a new row in the CSV file.
    for email, data in user_data.items():
        writer.writerow([email, data[\"firstName\"], data[\"lastName\"], data[\"mailboxSize\"]])

# Close the CSV file.
f.close()

已确认凭证正确,尝试过不同Scope,询问操作错误点。

错误分析与解决方法
  • 权限范围错误:你用的https://admin.googleapis.com/admin/directory/v1/users不是合法的API权限范围,应使用https://www.googleapis.com/auth/admin.directory.user.readonly(只读权限足够)。修改后必须删除本地的token.json文件,重新授权生成新凭证。

  • 缺少必填参数:users.list()方法必须指定customer或domain参数才能调用成功。如果是G Suite管理员,用customer='my_customer';如果指定域名,用domain='你的域名.com'。示例:

    users = service.users().list(customer='my_customer').execute()
    
  • 邮箱容量字段获取方式错误:Directory API的users.list接口默认只返回用户基础信息(如邮箱、姓名),不会包含storage字段。要获取邮箱容量,需对每个用户调用users.get方法,并指定projection='full'参数,示例:

    user_detail = service.users().get(userKey=user['primaryEmail'], projection='full').execute()
    mailbox_size = user_detail.get('storage', {}).get('quotaUsage', 'N/A')
    
  • 代码缩进问题:原代码存在多处缩进错误(如creds = None后的注释、if os.path.exists块的缩进),会导致Python解释器报错,需修正为正确的缩进格式。

修正后的完整代码
from __future__ import print_function
import os.path
import csv
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build

# 正确的只读权限范围,修改后请删除token.json重新授权
SCOPES = ['https://www.googleapis.com/auth/admin.directory.user.readonly']

creds = None
# token.json存储用户的访问和刷新令牌,首次授权自动创建
if os.path.exists('token.json'):
    creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# 无有效凭证时重新登录授权
if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
        creds.refresh(Request())
    else:
        flow = InstalledAppFlow.from_client_secrets_file(
            'credentials.json', SCOPES)
        creds = flow.run_local_server(port=0)
    # 保存凭证供下次使用
    with open('token.json', 'w') as token:
        token.write(creds.to_json())

service = build('admin', 'directory_v1', credentials=creds)
print('正在获取域内用户信息...')
# 添加customer参数,my_customer代表当前管理员管理的所有用户
users_result = service.users().list(customer='my_customer', maxResults=500).execute()
users = users_result.get('users', [])

user_data = {}

for user in users:
    # 调用get接口获取完整用户信息(包含storage字段)
    user_detail = service.users().get(userKey=user['primaryEmail'], projection='full').execute()
    user_data[user['primaryEmail']] = {
        'firstName': user_detail['name']['givenName'],
        'lastName': user_detail['name']['familyName'],
        'mailboxSize': user_detail.get('storage', {}).get('quotaUsage', '无数据')
    }

# 写入CSV文件
with open("user_data.csv", "w", newline="", encoding='utf-8') as f:
    writer = csv.writer(f)
    writer.writerow(["邮箱", "名", "姓", "邮箱容量"])
    for email, data in user_data.items():
        writer.writerow([email, data["firstName"], data["lastName"], data["mailboxSize"]])

print('数据已成功导出到user_data.csv')

内容的提问来源于stack exchange,提问作者Yuri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 16:59:53