批量释放或拒绝邮件

如果您需要一次性对多封隔离邮件执行操作,请使用 Mail Admin Quarantine API 中 customers.quarantinedMessages 资源的批量方法:

这两种方法都是异步的。API 接受请求,返回长时间运行的操作,并在后台处理消息。然后,您轮询 customers.operations 资源的 get 方法,直到操作完成并从响应中读取每条消息的结果。

与在循环中调用单消息方法相比,批量方法无论包含多少条消息,都算作一个写入请求,计入配额用量。

前提条件

  • 您已完成设置 API 中的步骤。
  • 一个访问令牌,用于模拟具有管理员隔离区权限的管理员,并包含 https://www.googleapis.com/auth/gmail.admin.quarantine 范围。请参阅使用全网域授权进行授权。
  • 处于 PENDING_TRIAGE 状态的多达 500 条隔离邮件的资源名称,这些名称可通过列出和搜索隔离邮件获取。

启动批量操作

如需批量释放消息,请向 customers.quarantinedMessages 资源上的 :batchRelease 自定义方法发送 POST 请求。requests 数组包含每条消息的一个对象,每个对象都包含消息的资源名称:

POST https://mailadminquarantine.googleapis.com/v1/customers/CUSTOMER_ID/quarantinedMessages:batchRelease
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json

{
  "requests": [
    {"name": "customers/CUSTOMER_ID/quarantinedMessages/user1@example.com:18d3ef45a8b2c1d0"},
    {"name": "customers/CUSTOMER_ID/quarantinedMessages/user2@example.com:18d3ef45a8b2c1d1"}
  ]
}

如需拒绝批处理中的消息,请改为向 customers.quarantinedMessages 资源上的 :batchDeny 自定义方法发送相同的请求正文:

POST https://mailadminquarantine.googleapis.com/v1/customers/CUSTOMER_ID/quarantinedMessages:batchDeny

每个请求必须包含 1 到 500 个条目。每条消息都必须属于请求路径中的客户。包含超过 500 个条目的请求会返回 400 INVALID_ARGUMENT 错误。

该 API 会立即返回 Operation 资源:

{
  "name": "customers/01abc23de/operations/7f1c2a0e-5b7d-4d3a-9c1e-2f4b6a8d0e13",
  "metadata": {
    "@type": "type.googleapis.com/google.gmail.mailadminquarantine.v1.BatchReleaseQuarantinedMessagesMetadata",
    "state": "PROCESSING",
    "processedCount": 0,
    "totalCount": 2
  },
  "done": false
}

存储操作的 name。您需要使用该名称来检查操作进度。

查看批处理操作的状态

如需检查批量操作的进度,请向操作的资源名称上的 get 方法发送 GET 请求:

GET https://mailadminquarantine.googleapis.com/v1/customers/CUSTOMER_ID/operations/OPERATION_ID
Authorization: Bearer ACCESS_TOKEN

get 方法接受任一 Admin Quarantine API 范围,因此只读集成可以监控其他系统启动的操作。

在操作运行期间,done 字段设置为 false,metadata 字段报告进度:

元数据字段 说明
state PROCESSING(在处理消息时),然后是 SUCCEEDED 或 FAILED。
processedCount 目前已处理的消息数量。
totalCount 批次中的消息总数。

操作完成后,done 字段会设置为 true,并且 response 字段会包含批处理中每条消息的结果:

{
  "name": "customers/01abc23de/operations/7f1c2a0e-5b7d-4d3a-9c1e-2f4b6a8d0e13",
  "metadata": {
    "@type": "type.googleapis.com/google.gmail.mailadminquarantine.v1.BatchReleaseQuarantinedMessagesMetadata",
    "state": "SUCCEEDED",
    "processedCount": 2,
    "totalCount": 2
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.gmail.mailadminquarantine.v1.BatchReleaseQuarantinedMessagesResponse",
    "results": [
      {
        "name": "customers/01abc23de/quarantinedMessages/user1@example.com:18d3ef45a8b2c1d0",
        "status": {},
        "quarantinedMessage": {
          "name": "customers/01abc23de/quarantinedMessages/user1@example.com:18d3ef45a8b2c1d0",
          "messageId": "18d3ef45a8b2c1d0",
          "messageOwner": "user1@example.com",
          "state": "RELEASED"
        }
      },
      {
        "name": "customers/01abc23de/quarantinedMessages/user2@example.com:18d3ef45a8b2c1d1",
        "status": {
          "code": 5,
          "message": "Quarantined message not found"
        }
      }
    ]
  }
}

results 中的每个条目都描述了一条消息的结果:

结果字段 说明
name 消息的资源名称。
status google.rpc.Status。空对象(代码 0、OK)表示操作成功。否则,code 和 message 会说明跳过该消息的原因。
quarantinedMessage 更新后的消息及其新 state。仅当 status 为 OK 时才会存在。

即使某些个别消息失败,批量操作也会成功。请始终检查每个结果的 status,而不要仅依赖于操作的 state。

如果整个操作失败(例如,由于后端不可用),则 done 字段会设置为 true,并且 error 字段包含 google.rpc.Status 而不是 response。

示例:批量发布和轮询完成情况

以下 Python 示例会启动批量发布,并每隔几秒轮询一次操作,直到操作完成:

import time
import requests

BASE_URL = 'https://mailadminquarantine.googleapis.com/v1'
CUSTOMER_ID = '01abc23de'  # Your customer ID without the leading 'C'.
headers = {
    'Authorization': f'Bearer {access_token}',
    'Content-Type': 'application/json',
}

# message_names is a list of up to 500 quarantined message resource names.
batch_url = f'{BASE_URL}/customers/{CUSTOMER_ID}/quarantinedMessages:batchRelease'
body = {'requests': [{'name': name} for name in message_names]}
operation = requests.post(batch_url, headers=headers, json=body)
operation.raise_for_status()
operation_name = operation.json()['name']

while True:
  status = requests.get(f'{BASE_URL}/{operation_name}', headers=headers)
  status.raise_for_status()
  operation = status.json()
  if operation.get('done'):
    break
  metadata = operation.get('metadata', {})
  print(f"Processed {metadata.get('processedCount', 0)} of "
        f"{metadata.get('totalCount', 0)} messages...")
  time.sleep(5)

if 'error' in operation:
  raise RuntimeError(f"Batch failed: {operation['error']}")

for result in operation['response'].get('results', []):
  if result.get('status', {}).get('code', 0) == 0:
    print(f"Released: {result['name']}")
  else:
    print(f"Skipped {result['name']}: {result['status'].get('message')}")

后续步骤