Я хочу загрузить любые вложения, полученные с определенного адреса электронной почты за последние 12 часов, через платформу Google API с использованием Python. Я использую следующий код.
import base64
from datetime import datetime, timedelta
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
import json
from google.oauth2.service_account import Credentials
# Load service account credentials from JSON file
creds = Credentials.from_service_account_file(r'token.json',
scopes['https://www.googleapis.com/auth/gmail.readonly'])
# Create Gmail API service
service = build('gmail', 'v1', credentials=creds)
# Calculate the date 12 hours ago from now
now = datetime.utcnow()
time_threshold = now - timedelta(hours=12)
formatted_time_threshold = time_threshold.strftime('%Y-%m-%dT%H:%M:%S.%fZ')
# Define the email address of the sender you want to filter by
sender_email = '[email protected]'
# Define the query to retrieve messages from the sender received in the last 12 hours
query = f'from:{sender_email} after:{formatted_time_threshold}'
print(query)
try:
# Get messages that match the query
response = service.users().messages().list(q=query, userId='me').execute()
messages = response.get('messages', [])
# Iterate through messages and download attachments
for msg in messages:
message = service.users().messages().get(userId='me', id=msg['id']).execute()
payload = message['payload']
# Check if message has any attachments
if 'parts' in payload:
for part in payload['parts']:
# Check if part is an attachment
if part['filename']:
filename = part['filename']
data = part['body']['data']
file_data = base64.urlsafe_b64decode(data.encode('UTF-8'))
# Save attachment to local disk
with open(filename, 'wb') as f:
f.write(file_data)
print(f'Saved attachment: {filename}')
except HttpError as error:
print(f'An error occurred: {error}')
Когда я запускаю это, я получаю HttpError, и когда я проверяю URL-адрес ошибки, я получаю следующее сообщение.
"error": {
"code": 401,
"message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"errors": [
{
"message": "Login Required.",
"domain": "global",
"reason": "required",
"location": "Authorization",
"locationType": "header"
}
],
"status": "UNAUTHENTICATED"}
Я не уверен, в чем здесь проблема. Я неправильно аутентифицируюсь с помощью API или мне нужно настроить что-то еще для этого процесса.
Файл token.json, который я использую для установления соединения, имеет следующую структуру.
{
"type": "service_account",
"project_id": "mailer-attachments-download",
"private_key_id": "",
"private_key": "",
"client_email": "attachment-downloader@mailer-attachments-download.iam.gserviceaccount.com",
"client_id": "",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/attachment-downloader%40mailer-attachments-download.iam.gserviceaccount.com"
}
Я хотел бы знать, что я делаю неправильно, или есть ли другие альтернативные средства, с помощью которых я могу достичь своей цели.






Поскольку ошибка конкретно касается учетных данных аутентификации, я считаю довольно безопасным предположить, что проблема находится здесь:
creds = Credentials.from_service_account_file(r'token.json',
scopes['https://www.googleapis.com/auth/gmail.readonly'])
Поскольку это единственная строка, которую мне удалось найти, которая касается учетных данных, я считаю, что проблема в том, что отправляемые учетные данные фактически исходят от самой учетной записи службы, проблема заключается в том, что учетная запись службы сама по себе не имеет доступа к чьи-либо данные электронной почты. Это точно можно исправить! И это делается путем добавления олицетворения следующим образом:
creds = Credentials.from_service_account_file(r'token.json',
scopes['https://www.googleapis.com/auth/gmail.readonly'])
delegated_credentials = credentials.with_subject('Email_address_of_the_recipient')
Добавление адреса электронной почты получателя в кавычки приведенного выше кода сообщит коду о необходимости отправки запроса от имени пользователя, электронные письма которого вы пытаетесь получить. Однако имейте в виду, что для этого вам необходимо предоставить сервисному аккаунту широкое делегирование домена
Я предоставил широкое делегирование домена, но, похоже, это не решает мою проблему.
Делегирование на уровне домена предназначено только для того, чтобы разрешить учетным записям службы отправлять запросы от имени других пользователей, чтобы сообщить скрипту, от кого будет отправляться запрос. Этого можно добиться, добавив параметр with_subject в строки аутентификации, например: creds = Credentials.from_service_account_file(r'token.json', scopes['https://www.googleapis.com/auth/gmail.readonly']) delegated_credentials = credentials.with_subject('[email protected]') Пожалуйста, не забудьте заменить «[email protected]» на получателя писем.
В ответе прямо говорится: В запросе отсутствуют необходимые учетные данные для аутентификации. Ожидаемый токен доступа OAuth 2, файл cookie для входа или другие действительные учетные данные для аутентификации. См. Developers.google.com/identity/sign-in/web/devconsole-project.