Подключение к Gmail через API
Клиентская библиотека Google API, согласие OAuth2 и выбор области доступа Gmail.
«Подключение к Gmail через API» — бесплатный урок AI Agents на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения AI Agents, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс AI Agents содержит 4 уроков всего.
Почему вместо SMTP следует использовать Gmail API?
В традиционной автоматизации электронной почты используются SMTP/IMAP, но Gmail API предлагает гораздо больше возможностей: чтение цепочек писем, поиск по запросу, управление метками и отправку с полноценной аутентификацией. Он также поддерживает OAuth 2.0, поэтому агенту не нужно хранить пароль — достаточно токена доступа с ограниченной областью действия.
Gmail API входит в состав API Google Workspace и используется через библиотеку google-api-python-client.
# Install required libraries:
# pip install google-api-python-client google-auth google-auth-oauthlib
# The Gmail API lets agents:
# - List and search messages (labels, queries)
# - Read full message content and attachments
# - Send messages via OAuth (no password needed)
# - Manage labels and threads
# - Watch for new messages via push notifications
print('Gmail API is part of Google Workspace APIs')Аутентификация: сервисный аккаунт и аутентификация пользователя
Для Gmail API существуют два подхода к аутентификации:
- Сервисный аккаунт: лучше всего подходит для рабочих пространств и организаций с делегированием полномочий на уровне домена; взаимодействие с пользователем не требуется
- OAuth пользователя (OAuth2 с экраном согласия): требуется для личных аккаунтов Gmail; пользователь один раз предоставляет доступ, после чего агент использует токен обновления
Для большинства задач автоматизации с агентами сервисные аккаунты предпочтительнее благодаря своей надёжности.
# Service Account approach:
# 1. Go to Google Cloud Console -> APIs & Services -> Credentials
# 2. Create a Service Account
# 3. Download the JSON key file
# 4. In Google Workspace Admin: enable domain-wide delegation
# 5. Grant required scopes to the service account
# User OAuth approach:
# 1. Create OAuth 2.0 Client ID (Desktop or Web App type)
# 2. Download credentials.json
# 3. First run: user sees consent screen and grants access
# 4. Agent stores token.json with refresh token for subsequent runs
print('Choose service account for org automation, OAuth for personal Gmail')Структура JSON учётных данных OAuth2
Google предоставляет учётные данные в JSON-файле, который агент загружает для аутентификации. Для OAuth пользователя это файл credentials.json, загруженный из Google Cloud Console. Файл содержит ID клиента, секретный ключ и URI перенаправления — никогда не добавляйте его в систему контроля версий.
# credentials.json structure (User OAuth — Desktop app type):
# {
# "installed": {
# "client_id": "123456789.apps.googleusercontent.com",
# "client_secret": "GOCSPX-abc123xyz",
# "redirect_uris": ["urn:ietf:wg:oauth:2.0:oob", "http://localhost"],
# "auth_uri": "https://accounts.google.com/o/oauth2/auth",
# "token_uri": "https://oauth2.googleapis.com/token"
# }
# }
# service-account.json structure:
# {
# "type": "service_account",
# "project_id": "my-project",
# "private_key_id": "abc123",
# "private_key": "-----BEGIN PRIVATE KEY-----\n...",
# "client_email": "agent@my-project.iam.gserviceaccount.com",
# "client_id": "..."
# }
print('Store credential files outside your git repository')Области доступа Gmail API
Области доступа OAuth точно определяют, к каким данным может обращаться агент. Запрашивайте только необходимые области доступа — это принцип наименьших привилегий. Области доступа Gmail варьируются от доступа только для чтения до полного доступа.
gmail.readonly— чтение всей почтыgmail.send— только отправка, без чтенияgmail.modify— чтение, отправка и изменение метокgmail.compose— только создание черновиков
# Gmail API scope constants
SCOPE_READONLY = 'https://www.googleapis.com/auth/gmail.readonly'
SCOPE_SEND = 'https://www.googleapis.com/auth/gmail.send'
SCOPE_MODIFY = 'https://www.googleapis.com/auth/gmail.modify'
SCOPE_COMPOSE = 'https://www.googleapis.com/auth/gmail.compose'
# Calendar scopes (often used alongside Gmail)
SCOPE_CALENDAR_READ = 'https://www.googleapis.com/auth/calendar.readonly'
SCOPE_CALENDAR_EVENTS = 'https://www.googleapis.com/auth/calendar.events'
# Combine scopes your agent actually needs
AGENT_SCOPES = [
SCOPE_READONLY,
SCOPE_SEND,
SCOPE_CALENDAR_EVENTS
]
print(f'Using {len(AGENT_SCOPES)} scopes')OAuth пользователя: поток первой аутентификации
При первом запуске агента пользователем открывается браузер, чтобы предоставить разрешение. Агент сохраняет полученный токен в token.json. При последующих запусках он загружает сохранённый токен и автоматически обновляет его — взаимодействие с браузером не требуется.
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
import os
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
def get_credentials(token_file='token.json', creds_file='credentials.json'):
creds = None
# Load existing token if available
if os.path.exists(token_file):
creds = Credentials.from_authorized_user_file(token_file, SCOPES)
# Refresh or re-authenticate if needed
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request()) # auto-refresh
else:
# Opens browser for user consent (first time only)
flow = InstalledAppFlow.from_client_secrets_file(
creds_file, SCOPES
)
creds = flow.run_local_server(port=0)
# Save token for next run
with open(token_file, 'w') as f:
f.write(creds.to_json())
return credsАутентификация сервисного аккаунта
Для автоматизированных агентов, работающих без взаимодействия с пользователем, сервисные аккаунты подходят идеально. Агент проходит аутентификацию с помощью закрытого ключа, а затем действует от имени пользователя Google Workspace через делегирование полномочий на уровне домена. Экран согласия и браузер не нужны — требуется только JSON-файл с ключом.
from google.oauth2 import service_account
import os
SCOPES = [
'https://www.googleapis.com/auth/gmail.readonly',
'https://www.googleapis.com/auth/gmail.send'
]
def get_service_account_credentials(impersonate_user):
service_account_file = os.environ.get(
'GOOGLE_SERVICE_ACCOUNT_JSON',
'service-account.json'
)
credentials = service_account.Credentials.from_service_account_file(
service_account_file,
scopes=SCOPES
)
# Impersonate a real user (requires domain-wide delegation in Admin)
delegated = credentials.with_subject(impersonate_user)
return delegated
creds = get_service_account_credentials('agent@yourcompany.com')
print('Service account credentials ready')Создание объекта сервиса Gmail
Получив учётные данные, используйте googleapiclient.discovery.build(), чтобы создать объект сервиса Gmail. Это основной интерфейс для всех вызовов Gmail API. Передайте имя сервиса 'gmail' и версию 'v1'.
from googleapiclient.discovery import build
def build_gmail_service(credentials):
service = build(
'gmail',
'v1',
credentials=credentials,
cache_discovery=False # avoid file warnings in some environments
)
return service
# Full setup: credentials -> service
creds = get_credentials() # or get_service_account_credentials()
gmail = build_gmail_service(creds)
# Test: get user profile
profile = gmail.users().getProfile(userId='me').execute()
print('Email:', profile['emailAddress'])
print('Total messages:', profile['messagesTotal'])Создание объекта сервиса Календаря
Та же настройка учётных данных работает и для Google Calendar. Просто создайте сервис с параметрами 'calendar' и 'v3'. Если одному агенту нужны и Gmail, и Calendar, создайте оба сервиса из одного объекта учётных данных.
from googleapiclient.discovery import build
def build_google_services(credentials):
gmail = build(
'gmail', 'v1',
credentials=credentials,
cache_discovery=False
)
calendar = build(
'calendar', 'v3',
credentials=credentials,
cache_discovery=False
)
return gmail, calendar
# Use both in one agent
creds = get_credentials()
gmail_service, calendar_service = build_google_services(creds)
# Test calendar access
cal_list = calendar_service.calendarList().list().execute()
for cal in cal_list.get('items', []):
print(f'Calendar: {cal["summary"]}')Обработка ошибок API Google
Ошибки API Google возникают как googleapiclient.errors.HttpError. Ошибка содержит код состояния HTTP и тело JSON с подробностями. Всегда перехватывайте её и записывайте код состояния и сообщение в журнал для отладки.
from googleapiclient.errors import HttpError
import json
def safe_gmail_call(service, user_id='me'):
try:
profile = service.users().getProfile(userId=user_id).execute()
return profile
except HttpError as e:
status = e.resp.status
try:
error_body = json.loads(e.content.decode())
message = error_body.get('error', {}).get('message', str(e))
except Exception:
message = str(e)
if status == 401:
print('AUTH ERROR: Credentials invalid or expired')
elif status == 403:
print(f'PERMISSION ERROR: {message}')
print('Check scopes and domain-wide delegation settings')
elif status == 429:
print('QUOTA EXCEEDED: Gmail API rate limit hit')
else:
print(f'Gmail API error {status}: {message}')
return NoneКвоты и ограничения частоты запросов API Google
Для Gmail API установлены квоты использования: по умолчанию 1 миллиард единиц квоты в день, при этом каждый вызов стоит от 1 до 100 единиц в зависимости от операции. Чтение сообщений обходится дороже, чем получение списка. Используйте пакетные запросы и экспоненциальную задержку при ошибках 429/503, чтобы не превышать ограничения.
import time
from googleapiclient.errors import HttpError
def gmail_call_with_retry(func, max_retries=5):
for attempt in range(max_retries):
try:
return func()
except HttpError as e:
if e.resp.status in (429, 500, 503):
wait = (2 ** attempt) + 1
print(f'Quota/server error. Waiting {wait}s (attempt {attempt+1})')
time.sleep(wait)
elif e.resp.status == 403:
# Check if it's a quota exceeded vs permission error
import json
body = json.loads(e.content.decode())
reason = body.get('error', {}).get('errors', [{}])[0].get('reason', '')
if reason == 'rateLimitExceeded':
time.sleep(2 ** attempt)
else:
raise # real permission error, don't retry
else:
raise
raise Exception(f'Gmail API call failed after {max_retries} attempts')Безопасное хранение учётных данных
Никогда не добавляйте token.json, credentials.json или service-account.json в систему контроля версий. Добавьте их в .gitignore. В рабочей среде храните JSON сервисного аккаунта в переменной окружения или менеджере секретов и загружайте его во время выполнения.
import json
import os
from google.oauth2 import service_account
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
def get_credentials_from_env():
# Load service account JSON from environment variable
sa_json = os.environ.get('GOOGLE_SERVICE_ACCOUNT_JSON')
if not sa_json:
raise EnvironmentError(
'GOOGLE_SERVICE_ACCOUNT_JSON env var not set. '
'Set it to the contents of your service-account.json'
)
sa_info = json.loads(sa_json)
credentials = service_account.Credentials.from_service_account_info(
sa_info,
scopes=SCOPES
)
return credentials
# In production: export GOOGLE_SERVICE_ACCOUNT_JSON=$(cat service-account.json)
creds = get_credentials_from_env()
print('Service account loaded from env var')Быстрая проверка: сервисный аккаунт и OAuth пользователя
Проверьте, насколько хорошо Вы поняли методы аутентификации Gmail API.
Итоги подключения к Gmail API
Теперь Вы умеете подключать агента к Gmail:
- OAuth пользователя: используйте
InstalledAppFlowи сохраняйтеtoken.json; при последующих запусках токен обновляется автоматически - Сервисный аккаунт: загрузите JSON-ключ и вызовите
.with_subject(user_email)для делегирования полномочий - Области доступа: запрашивайте необходимый минимум (
gmail.readonly,gmail.send,calendar.events) - Создайте сервис с помощью
build('gmail', 'v1', credentials=creds) - Перехватывайте
HttpErrorдля обработки ошибок API; повторяйте запросы при ошибках 429/503 - Никогда не добавляйте файлы с учётными данными в систему контроля версий — в рабочей среде используйте переменные окружения
Часто задаваемые вопросы
Урок «Подключение к Gmail через API» бесплатный?
Да — полный текст урока «Подключение к Gmail через API» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс AI Agents, подпишись на CoddyKit PRO. Курс AI Agents содержит 4 уроков всего.
Чему я научусь в уроке «Подключение к Gmail через API»?
Клиентская библиотека Google API, согласие OAuth2 и выбор области доступа Gmail. Ты практикуешь AI Agents с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать AI Agents?
Предыдущий опыт не требуется. AI Agents на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Подключение к Gmail через API»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке AI Agents?
Да. Каждый урок AI Agents включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Подключение к Gmail через API
- Программное чтение и отправка электронных писем
- Создание и поиск событий календаря
- Создание простого агента — помощника по электронной почте