Вопрос или проблема
Я пытаюсь создать простое приложение на Python, которое смогло бы удалять и добавлять фильтры в Gmail. Используя различные SCOPES, я могу легко перечислять метки, фильтры и т. д., но при попытке добавить новый фильтр я получаю ошибку.
Приведенный ниже код является упрощением моего реального кода (который разбит на набор функций), но по сути выполняет то же самое, что и мой полный код.
import os.path
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
def main():
scope = ['https://www.googleapis.com/auth/gmail.settings.basic']
credentials_file="credentials.json"
token_file = f'token_test.json'
credentials = None
if os.path.exists(token_file):
credentials = Credentials.from_authorized_user_file(token_file, scope)
if not credentials or not credentials.valid:
if credentials and credentials.expired and credentials.refresh_token:
credentials.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(credentials_file, scope)
credentials = flow.run_local_server(port=0)
with open(token_file, 'w') as token:
token.write(credentials.to_json())
service = build('gmail', 'v1', credentials=credentials)
filter_body = {'criteria': {'from': '[email protected]'}, 'action': {'removeLabelsIds': ['SPAM']}}
result = (
service.users()
.settings()
.filters()
.create(userId='me', body=filter_body)
.execute())
return result
if __name__ == '__main__':
main()
Я получаю эту ошибку:
Traceback (most recent call last):
File "C:\DATA\WORK\Assets\Development\Python\GmailManager\src\temp.py", line 36, in <module>
main()
File "C:\DATA\WORK\Assets\Development\Python\GmailManager\src\temp.py", line 31, in main
.execute())
^^^^^^^^^
File "C:\DATA\WORK\Assets\Development\Python\GmailManager\.venv\Lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\DATA\WORK\Assets\Development\Python\GmailManager\.venv\Lib\site-packages\googleapiclient\http.py", line 938, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 400 when requesting https://gmail.googleapis.com/gmail/v1/users/me/settings/filters?alt=json returned "Filter doesn't have any actions". Details: "[{'message': "Filter doesn't have any actions", 'domain': 'global', 'reason': 'invalidArgument'}]">
Информация по ссылке https://gmail.googleapis.com/gmail/v1/users/me/settings/filters?alt=json следующая:
{
"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",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "CREDENTIALS_MISSING",
"domain": "googleapis.com",
"metadata": {
"method": "caribou.api.proto.MailboxService.ListFilters",
"service": "gmail.googleapis.com"
}
}
]
}
}
что довольно странно, так как в данный момент я не знаю, является ли ошибка следствием содержания фильтра или ошибкой аутентификации.
Ответ или решение
Доброго времени суток!
Ваша проблема заключается в том, что вы пытаетесь создать фильтр для Gmail, но не указываете корректно действия, которые должны быть выполнены в результате применения этого фильтра. Обратите внимание на вывод ошибки:
googleapiclient.errors.HttpError: <HttpError 400 when requesting ... returned "Filter doesn't have any actions".
Это означает, что фильтр, который вы пытаетесь создать, не содержит никаких действий, которые Gmail должен выполнить на ваши сообщения.
Исправление кода
Для добавления фильтра необходимо правильно указать и критерии, и действия. Вот пример того, как должен выглядеть ваш код с добавленными корректными действиями для фильтра:
import os.path
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
def main():
scope = ['https://www.googleapis.com/auth/gmail.settings.basic']
credentials_file = "credentials.json"
token_file = 'token_test.json'
credentials = None
if os.path.exists(token_file):
credentials = Credentials.from_authorized_user_file(token_file, scope)
if not credentials or not credentials.valid:
if credentials and credentials.expired and credentials.refresh_token:
credentials.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(credentials_file, scope)
credentials = flow.run_local_server(port=0)
with open(token_file, 'w') as token:
token.write(credentials.to_json())
service = build('gmail', 'v1', credentials=credentials)
filter_body = {
'criteria': {
'from': 'example@example.com',
},
'action': {
'removeLabelIds': ['SPAM'], # Уберите метку 'SPAM'
'addLabelIds': ['IMPORTANT'] # Можно добавить метку 'IMPORTANT' или другие метки
}
}
# Создание фильтра
result = (
service.users()
.settings()
.filters()
.create(userId='me', body=filter_body)
.execute()
)
print(f"Фильтр успешно создан: {result}")
if __name__ == '__main__':
main()
Основные моменты:
-
Действия фильтра: Убедитесь, что у вас есть хотя бы одно действие в разделе
'action'
. В текущем примере я добавил действиеaddLabelIds
, чтобы добавить меткуIMPORTANT
. Вы можете изменить или добавить другие метки по вашему усмотрению. -
Проверка аутентификации: Убедитесь, что файл
token_test.json
содержит действительные учетные данные OAuth 2.0. Если файл недоступен или нестандартный, выполните аутентификацию заново, чтобы создать новый токен. -
Тестирование: Проверьте введенные вами значения в критериях и действиях фильтра. Если вы получаете другие ошибки, убедитесь, что все метки указаны правильно.
Заключение
Если все сделано верно, после выполнения вашего кода фильтр должен быть успешно создан в вашем Gmail. Если возникнут дополнительные проблемы, ознакомьтесь с документацией Gmail API и удостоверьтесь, что у вас достаточно прав доступа для выполнения всех операций. Надеюсь, это поможет вам решить вашу задачу!