руководство · gmail api
Как продуктовой команде безопасно внедрить Gmail API?
Внедряйте Gmail API как делегированный доступ к конкретному почтовому ящику Gmail, а не как универсальные учётные данные для доставки писем. Выберите минимальную область OAuth, достаточную для функции, защитите состояние авторизации и refresh-токены и привязывайте каждый почтовый ящик к тенанту. Собирайте письма с помощью зрелой библиотеки для интернет-сообщений, сохраняйте возвращённый ID письма Gmail и синхронизируйте изменения через Pub/Sub и записи истории. Считайте имперсонацию через сервисный аккаунт решением администратора Workspace. И наконец, разделяйте приём запроса API, доставку на принимающий сервер и попадание во «Входящие» как разные результаты.
Выберите модель работы с почтовым ящиком до написания кода
Gmail API работает с почтовым ящиком Gmail пользователя. Он подходит, когда продукт должен читать этот ящик, управлять его метками и цепочками, создавать черновики, отправлять письма от имени авторизованного пользователя или синхронизировать изменения ящика. Такие полномочия существенно шире, чем вызов email API приложения с подтверждённого домена продукта. Начните с того, чтобы точно назвать задачу, связанную с ящиком, и того, кто предоставляет доступ. Продукт для конечных пользователей обычно использует согласие OAuth для каждого подключённого аккаунта Google. Внутренняя автоматизация в Google Workspace может вместо этого использовать делегирование на уровне домена, одобренное администратором. Если единственное требование — отправлять чеки, ссылки для подтверждения, оповещения или другие письма, запускаемые продуктом, с домена, которым управляет компания, вообще откажитесь от доступа к ящику и рассмотрите API для транзакционных писем. Такое архитектурное решение убирает лишний доступ ещё до того, как его придётся компенсировать механизмами безопасности или экраном согласия.
Запрашивайте минимально необходимую область доступа
Настройте OAuth-клиент для правильного типа приложения, используйте точный зарегистрированный redirect URI и привязывайте ответ авторизации к браузерной сессии, которая его инициировала, с помощью непредсказуемого значения state. Запрашивайте доступ в контексте — когда пользователь включает функцию, которой он нужен. Для интеграции, которая только отправляет письма, `https://www.googleapis.com/auth/gmail.send` уже, чем области, позволяющие читать или изменять ящик. Google относит `gmail.send` к чувствительным (sensitive), а такие области, как `gmail.readonly`, `gmail.compose` и `gmail.modify`, — к ограниченным (restricted). Публичному приложению с чувствительным или ограниченным доступом может потребоваться верификация OAuth, а хранение или передача данных ограниченных областей на сервере может повлечь дополнительные требования к оценке безопасности. Запрашивайте офлайн-доступ, только если фоновая работа действительно нужна. Шифруйте refresh-токены, связывайте каждый токен с одним внутренним тенантом и субъектом Google, никогда не раскрывайте его браузерному коду или логам и предоставьте протестированный путь отключения, который удаляет локальные учётные данные и останавливает фоновую обработку.
Разберитесь в сервисных аккаунтах и делегировании на уровне домена
Сервисный аккаунт — это идентичность приложения, а не готовый почтовый ящик Gmail. Сам по себе он не получает доступа к письмам сотрудников. Для доступа к пользовательским данным Google Workspace суперадминистратор должен явно авторизовать числовой ID клиента сервисного аккаунта и точный список областей OAuth через делегирование на уровне домена. Затем приложение запрашивает делегированные учётные данные для конкретного пользователя, и каждый вызов API выполняется с правами этого пользователя в пределах авторизованных областей. Явно указывайте имперсонируемого субъекта в данных задач и журналах аудита, чтобы фоновый воркер не мог незаметно переключиться на другой ящик. Используйте отдельные сервисные аккаунты для существенно разных нагрузок, избегайте скачиваемых закрытых ключей, если среда выполнения может использовать управляемые учётные данные, и регулярно пересматривайте выданные права делегирования. У потребительских аккаунтов Gmail нет администратора Workspace, который мог бы выдать такое делегирование на уровне организации, поэтому для них используйте согласие пользователя через OAuth.
Отправляйте письма, не теряя контроля и возможности аудита
Gmail принимает полное интернет-сообщение в поле `raw`, закодированное в base64url, через `users.messages.send`; продукт также может создать черновик и отправить его позже. Используйте поддерживаемую библиотеку для формирования From, To, Cc, Bcc, Subject, Date, Message-ID, текстовой и HTML-части и структуры вложений, а не склеивайте строки заголовков вручную. Проверяйте получателей и содержимое до кодирования, отклоняйте внедрение заголовков и задавайте явные ограничения размера. Сделайте действие продукта идемпотентным до вызова Gmail: сохраните стабильный ключ события приложения, целевой субъект ящика и состояние попытки отправки. После успешного ответа сохраните возвращённые Gmail ID письма и ID цепочки вместе с этим событием. Если клиент получил тайм-аут уже после передачи запроса, сверьте состояние ящика перед повтором: письмо могло быть уже принято. Слепой повтор может привести к дублированию письма, даже если исходный ответ просто потерялся. Используйте создание черновика и ручную проверку, когда содержимое или получатели требуют одобрения.
Синхронизируйте изменения ящика через записи истории
Для серверной интеграции с почтовым ящиком механизм watch в Gmail публикует сигналы об изменениях через Google Cloud Pub/Sub. Уведомление — это сигнал к синхронизации, а не полное содержимое письма. Сохраните текущий history ID и срок действия из ответа watch, быстро подтверждайте уведомления и вызывайте `users.history.list` начиная с последнего успешно зафиксированного history ID, чтобы узнать об изменениях писем и меток. Загружайте только те письма, которые нужны функции, и сдвигайте контрольную точку после успешной локальной записи. Уведомления могут приходить с задержкой или дублироваться, поэтому обработка писем и истории должна быть идемпотентной. Gmail требует продлевать watch для ящика не реже чем раз в семь дней и рекомендует делать это ежедневно; планируйте продление заранее до истечения срока и настройте оповещения о сбоях. Если сохранённый history ID выходит за пределы доступного в Gmail диапазона, API возвращает HTTP 404. Считайте это заранее определённым сценарием восстановления: выполните контролируемую полную синхронизацию, установите новую контрольную точку и возобновите инкрементальную обработку, а не повторяйте бесконечно запрос с недействительным history ID.
Используйте поэтапный процесс внедрения и проверки
Во-первых, задокументируйте, отправляет ли функция письма, читает, изменяет или отслеживает почту, и сопоставьте каждую операцию с минимальной областью OAuth. Во-вторых, создайте отдельные проекты Google Cloud или OAuth-клиенты для разработки и продакшена с точными redirect URI и назначенными владельцами учётных данных. В-третьих, реализуйте авторизацию с проверкой state, офлайн-доступом только при необходимости, зашифрованным хранением токенов, отзывом токенов и проверками доступа на уровне тенанта. В-четвёртых, протестируйте на контролируемых ящиках: подключение, обновление истёкшего access-токена, отзыв согласия, повторное подключение, однократная отправка, имитация неоднозначного тайм-аута и проверка защиты от дублей. В-пятых, если нужно получать изменения, выдайте права Pub/Sub, запустите watch, обрабатывайте историю инкрементально, принудительно проверьте восстановление после устаревшей контрольной точки и убедитесь, что watch продлевается. В-шестых, добавьте очереди задач на каждого пользователя, ограниченную экспоненциальную задержку, структурированную классификацию ошибок и журналы аудита, которые по умолчанию не содержат тел писем и токенов. Перед запуском пройдите необходимую верификацию и проверку безопасности Google, опубликуйте точные сведения об использовании данных и отрепетируйте ротацию учётных данных и удаление пользовательских данных.
Учитывайте квоты, повторные попытки и частичные сбои
Gmail измеряет использование API в единицах квоты, а не только по числу запросов. На странице квот Google указано 1,200,000 единиц в минуту на проект и 6,000 единиц в минуту на пользователя в проекте. Для `messages.send`, `drafts.send` и `watch` указано по 100 единиц, а лимит составляет 500 получателей на письмо. Отдельные пользовательские лимиты отправки Gmail по-прежнему действуют для клиентов API, web и SMTP. Считайте Cloud console и актуальную документацию входными данными конфигурации во время выполнения, а не жёстко кодируйте опубликованные лимиты в бизнес-логике. Последовательно обрабатывайте или справедливо ставьте в очередь работу для каждого почтового ящика, ограничивайте параллелизм и выполняйте повторные попытки только при временных ответах с экспоненциальной задержкой с джиттером (jitter) и конечным сроком. Не повторяйте ошибки авторизации, политики, недействительного получателя или некорректного письма, как будто это проблемы ёмкости. Multipart batch уменьшает накладные расходы на подключение, но каждый внутренний вызов всё равно расходует квоту и может завершиться ошибкой независимо.
Разделяйте приём, доставку и попадание во «Входящие»
Успешный вызов `messages.send` означает, что Gmail принял авторизованный запрос API и вернул ресурс Gmail Message. Это не доказывает, что почтовые серверы всех получателей приняли письмо, и не показывает, как принимающая система его классифицировала. Доставка на сервер получателя означает, что система назначения приняла на себя ответственность за письмо по SMTP. Попадание во «Входящие» — более поздний результат фильтрации: основная папка, «Промоакции», карантин или «Спам». Поэтому API почтового ящика Gmail не заменяет поток событий провайдера, когда продукту нужна телеметрия доставки, отказов или жалоб для транзакционных писем. Сохраняйте ID письма Gmail для сверки, но точно описывайте видимое пользователю состояние как «отправлено» или «принято Gmail», если доставку не подтверждают отдельные данные. На дальнейшую обработку влияют аутентификация, ожидаемость писем для получателей, качество контента, поведение при отправке и политика получателя. Ответ API не может определить или гарантировать итоговую папку в ящике получателя.
Когда API для транзакционных писем решает другую задачу
Используйте Gmail API, когда продукту нужен авторизованный доступ к почтовому ящику Gmail человека или организации, включая цепочки писем, метки, черновики или синхронизацию ящика. Транзакционный email API подходит для другой архитектуры: сообщения, инициированные приложением, отправляются с доменов, которые контролирует организация, без делегированных прав на чтение ящика Gmail пользователя. Продукт может использовать оба типа систем при явных границах: например, Gmail OAuth для чтения подключённого ящика агента поддержки и отдельного подтверждённого транзакционного провайдера для отправки квитанций продукта. Храните учётные данные, согласия, хранилища сообщений, политики повторных попыток и записи аудита раздельно, чтобы полномочия ящика не перешли к отправке для всего приложения, а транзакционные учётные данные не могли читать Gmail пользователя.
Частые вопросы
Может ли сервисный аккаунт получить доступ к любому ящику Gmail?
Нет. Сервисный аккаунт не получает доступ к пользовательским данным Gmail автоматически. Суперадминистратор Google Workspace должен выдать делегирование на уровне домена для его числового ID клиента и одобренных областей, после чего приложение явно имперсонирует пользователя в этой организации. Для потребительских аккаунтов Gmail используйте согласие пользователя через OAuth.
Какую область OAuth запрашивать для интеграции Gmail, которая только отправляет письма?
Начните с оценки `https://www.googleapis.com/auth/gmail.send`: эта область позволяет отправлять письма от имени пользователя, не давая общего доступа к чтению почтового ящика. Прежде чем запрашивать более широкую область, убедитесь, что ни одно требование продукта действительно не нуждается в черновиках, чтении писем, метках или изменениях, и учтите правила Google по верификации чувствительных областей.
Означает ли успешная отправка через Gmail API, что письмо доставлено?
Нет. Это подтверждает, что Gmail принял авторизованную операцию API и вернул запись о письме. Приём принимающим сервером и попадание во «Входящие» — отдельные последующие состояния. Не помечайте письмо как доставленное и не обещайте попадание во «Входящие», если этот вывод не подтверждён другим надёжным сигналом.
Содержат ли push-уведомления Gmail новое письмо целиком?
Нет. Уведомление Pub/Sub сообщает, что состояние ящика изменилось, и содержит данные для продолжения синхронизации. Приложение должно запросить историю Gmail начиная с сохранённого history ID, загрузить нужные данные писем, обработать их идемпотентно и затем сдвинуть контрольную точку.
Как часто нужно продлевать watch для ящика Gmail?
Google требует вызывать `watch` не реже одного раза в семь дней и рекомендует продлевать ежедневно. Сохраняйте возвращённый срок действия, продлевайте заранее, отслеживайте сбои и держите резервную задачу синхронизации, чтобы пропущенное продление не создало незаметный и неограниченный пробел в данных.
Когда команде стоит использовать API для транзакционных писем вместо Gmail API?
Используйте API для транзакционных писем, когда задача — письма, которые запускает приложение, с доменов под контролем организации, и ни одной функции не нужен доступ к чьему-либо почтовому ящику Gmail. Используйте Gmail API, когда продукту именно нужны делегированный доступ к письмам, цепочкам, меткам, черновикам, настройкам ящика или право отправки от имени пользователя (send-as).
Источники
- Обзор Gmail API — Google for Developers
- Выбор областей Gmail API — Google for Developers
- Серверная авторизация — Google for Developers
- OAuth 2.0 для серверных веб-приложений — Google for Developers
- OAuth 2.0 для межсерверных приложений — Google for Developers
- Создание и отправка писем — Google for Developers
- Настройка push-уведомлений в Gmail API — Google for Developers
- Синхронизация клиентов с Gmail — Google for Developers
- Лимиты использования Gmail API — Google for Developers
- Устранение ошибок Gmail API — Google for Developers
- Политика Google Workspace API в отношении пользовательских данных и разработчиков — Google for Developers
- RFC 5322: формат интернет-сообщений — RFC Editor
- RFC 5321: простой протокол передачи почты (SMTP) — RFC Editor