[Разработка веб-сайтов, PHP, Программирование, Проектирование и рефакторинг, Google API] Настройка Gmail API для замены расширения PHP IMAP и работы по протоколу OAuth2
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Оказавшись одним из счастливчиков, совершенно не готовым к тому, что с 15 февраля 2021 года авторизация в Gmail и других продуктах будет работать только через OAuth, я прочитал статью "Google хоронит расширение PHP IMAP" и загрустил начал предпринимать действия по замене расширения PHP IMAP в своём проекте на API Google. Вопросов было больше, чем ответов, поэтому заодно нацарапал мануал.
У меня PHP IMAP используется для следующих задач:
- Удаление старых писем из почтовых ящиков. К сожалению, в панели управления корпоративным аккаунтом G Suite можно настроить только срок удаления писем из всех почтовых ящиков организации через N дней после получения. Мне же требуется удалять письма только в заданных почтовых ящиках и через заданное разное количество дней после получения.
- Фильтрация, разбор и маркировка писем. С нашего сайта в автоматическом режиме отправляется множество писем, некоторые из которых не доходят до адресатов, о чём, соответственно, приходят отчёты. Нужно эти отчёты отлавливать, разбирать, находить клиента по email и формировать человекочитаемое письмо для менеджера, чтобы тот связался с клиентом и уточнил актуальность адреса электронной почты.
Эти две задачи мы и будем решать при помощи API Gmail в данной статье (а заодно и отключим в настройках почтовых ящиков доступ для небезопасных приложений, который был включён для работы PHP IMAP, и, собственно, перестанет работать в страшный день в феврале 2021). Использовать будем так называемый сервисный аккаунт приложения Gmail, который при соответствующей настройке даёт возможность подключения ко всем почтовым ящикам организации и выполнения в них любых действий.
1. Создаём проект в консоли разработчика Google API
При помощи этого проекта мы и будем осуществлять API-взаимодействие с Gmail, и в нём же создадим тот самый сервисный аккаунт.
Для создания проекта:
- Переходим в консоль разработчика Google API и логинимся по администратором G Suite (ну или кто у Вас там пользователь со всеми правами)
- Ищем кнопку «Создать проект».
Я нашёл здесь:
SPL
И затем здесь:
SPL
Заполняем имя проекта и сохраняем
Создание проекта
SPL
- Переходим к проекту и нажимаем кнопку «Включить API и сервисы»
2. Создаём и настраиваем сервисный аккаунт
Для этого можно воспользоваться официальным мануалом или продолжить чтение:
- Переходим в наш добавленный Gmail API, нажимаем кнопку «Создать учётные данные» и выбираем «Сервисный аккаунт»
Создание сервисного аккаунта
SPL
Что-нибудь заполняем и нажимаем «Создать»
Сведения о сервисном аккаунте
SPL
Всё остальное можно не заполнять
Права доступа для сервисного аккаунта
SPL
Предоставление пользователям доступа к сервисному аккаунту
SPL
- Далее, сервисному аккаунту нужно дать права на чтение или управление почтовыми ящиками. Для этого переходим в консоль администрирования G Suite, открываем главное меню и переходим в пункт «Безопасность — Управление API».
Управление API
SPL
- Прокручиваем страницу вниз и выбираем пункт «Настроить делегирование доступа к данным в домене»
Делегирование доступа к данным в домене
SPL
Нажимаем «Добавить», в поле «Идентификатор клиента» копируем соответствующую строку из карточки сервисного аккаунта, а поле «Области действия OAuth» вставляем права — одно или несколько из следующих значений через запятую:
- https://mail.google.com/ - для полного доступа
- https://www.googleapis.com/auth/gmail.modify - для редактирования меток
- https://www.googleapis.com/auth/gmail.readonly - для чтения
- https://www.googleapis.com/auth/gmail.metadata - для доступа к метаданным
Сведения о сервисном аккаунте
SPL
- Возвращаемся к карточке сервисного аккаунта и включаем ещё одну разрешающую галку «Включить делегирование доступа к данным в домене G Suite»:
Статус сервисного аккаунта
SPL
А также заполняем название Вашего продукта в поле ниже.
- Теперь нужно создать ключ сервисного аккаунта: это файл, который должен быть доступен в Вашем приложении. Он, собственно, и будет использоваться для авторизации.
Для этого со страницы «Учётные данные» Вашего проекта переходим по ссылке «Управление сервисными аккаунтами»
На этом настройка API Gmail закончена, далее будет немного моего кака-кода, собственно, реализующего функции, которые до сих пор решались расширением IMAP PHP.
3. Пишем код
По API Gmail есть вполне себе неплохая официальная документация (клик и клик), которой я и пользовался. Но раз уж взялся написать подробный мануал, то приложу и свой собственный кака-код.
Итак, первым делом устанавливаем Google Client Library (apiclient) при помощи composer:
composer require google/apiclient
(Сначала я, как истинный буквоед, установил именно версию 2.0 api-клиента, как указано в PHP Quickstart, но при первом же запуске на PHP 7.4 посыпались всякие ворнинги и алармы, поэтому Вам так же делать не советую)
Затем на основе примеров из официальной документации пишем свой класс для работы с Gmail, не забывая указать файл ключа сервисного аккаунта:
Класс для работы с Gmail
SPL
<?php
// Класс для работы с Gmail
class GmailAPI
{
private $credentials_file = __DIR__ . '/../Gmail/credentials.json'; // Ключ сервисного аккаунта
// ---------------------------------------------------------------------------------------------
/**
* Функция возвращает Google_Service_Gmail Authorized Gmail API instance
*
* @param string $strEmail Почта пользователя
* @return Google_Service_Gmail Authorized Gmail API instance
* @throws Exception
*/
function getService(string $strEmail){
// Подключаемся к почтовому ящику
try{
$client = new Google_Client();
$client->setAuthConfig($this->credentials_file);
$client->setApplicationName('My Super Project');
$client->setScopes(Google_Service_Gmail::MAIL_GOOGLE_COM);
$client->setSubject($strEmail);
$service = new Google_Service_Gmail($client);
}catch (Exception $e) {
throw new \Exception('Исключение в функции getService: '.$e->getMessage());
}
return $service;
}
// ---------------------------------------------------------------------------------------------
/**
* Функция возвращает массив ID сообщений в ящике пользователя
*
* @param Google_Service_Gmail $service Authorized Gmail API instance.
* @param string $strEmail Почта пользователя
* @param array $arrOptionalParams любые дополнительные параметры для выборки писем
* Из них мы сделаем стандартную строку поиска в Gmail вида after: 2020/08/20 in:inbox label:
* и запишем её в переменную q массива $opt_param
* @return array Массив ID писем или массив ошибок array('arrErrors' => $arrErrors), если они есть
* @throws Exception
*/
function listMessageIDs(Google_Service_Gmail $service, string $strEmail, array $arrOptionalParams = array()) {
$arrIDs = array(); // Массив ID писем
$pageToken = NULL; // Токен страницы в почтовом ящике
$messages = array(); // Массив писем в ящике
// Параметры выборки
$opt_param = array();
// Если параметры выборки есть, делаем из них строку поиска в Gmail и записываем её в переменную q
if (count($arrOptionalParams)) $opt_param['q'] = str_replace('=', ':', http_build_query($arrOptionalParams, null, ' '));
// Получаем массив писем, соответствующих условию выборки, со всех страниц почтового ящика
do {
try {
if ($pageToken) {
$opt_param['pageToken'] = $pageToken;
}
$messagesResponse = $service->users_messages->listUsersMessages($strEmail, $opt_param);
if ($messagesResponse->getMessages()) {
$messages = array_merge($messages, $messagesResponse->getMessages());
$pageToken = $messagesResponse->getNextPageToken();
}
} catch (Exception $e) {
throw new \Exception('Исключение в функции listMessageIDs: '.$e->getMessage());
}
} while ($pageToken);
// Получаем массив ID этих писем
if (count($messages)) {
foreach ($messages as $message) {
$arrIDs[] = $message->getId();
}
}
return $arrIDs;
}
// ---------------------------------------------------------------------------------------------
/**
* Удаляем сообщения из массива их ID функцией batchDelete
*
* @param Google_Service_Gmail $service Authorized Gmail API instance.
* @param string $strEmail Почта пользователя
* @param array $arrIDs массив ID писем для удаления из функции listMessageIDs
* @throws Exception
*/
function deleteMessages(Google_Service_Gmail $service, string $strEmail, array $arrIDs){
// Разбиваем массив на части по 1000 элементов, так как столько поддерживает метод batchDelete
$arrParts = array_chunk($arrIDs, 999);
if (count($arrParts)){
foreach ($arrParts as $arrPartIDs){
try{
// Получаем объект запроса удаляемых писем
$objBatchDeleteMessages = new Google_Service_Gmail_BatchDeleteMessagesRequest();
// Назначаем удаляемые письма
$objBatchDeleteMessages->setIds($arrPartIDs);
// Удаляем их
$service->users_messages->batchDelete($strEmail,$objBatchDeleteMessages);
}catch (Exception $e) {
throw new \Exception('Исключение в функции deleteMessages: '.$e->getMessage());
}
}
}
}
// ---------------------------------------------------------------------------------------------
/**
* Получаем содержиме сообщения функцией get
*
* @param Google_Service_Gmail $service Authorized Gmail API instance.
* @param string $strEmail Почта пользователя
* @param string $strMessageID ID письма
* @param string $strFormat The format to return the message in.
* Acceptable values are:
* "full": Returns the full email message data with body content parsed in the payload field; the raw field is not used. (default)
* "metadata": Returns only email message ID, labels, and email headers.
* "minimal": Returns only email message ID and labels; does not return the email headers, body, or payload.
* "raw": Returns the full email message data with body content in the raw field as a base64url encoded string; the payload field is not used.
* @param array $arrMetadataHeaders When given and format is METADATA, only include headers specified.
* @return object Message
* @throws Exception
*/
function getMessage(Google_Service_Gmail $service, string $strEmail, string $strMessageID, string $strFormat = 'full', array $arrMetadataHeaders = array()){
$arrOptionalParams = array(
'format' => $strFormat // Формат, в котором возвращаем письмо
);
// Если формат - metadata, перечисляем только нужные нам заголовки
if (($strFormat == 'metadata') and count($arrMetadataHeaders))
$arrOptionalParams['metadataHeaders'] = implode(',',$arrMetadataHeaders);
try{
$objMessage = $service->users_messages->get($strEmail, $strMessageID,$arrOptionalParams);
return $objMessage;
}catch (Exception $e) {
throw new \Exception('Исключение в функции getMessage: '.$e->getMessage());
}
}
// ---------------------------------------------------------------------------------------------
/**
* Выводим список меток, имеющихся в почтовом ящике
*
* @param Google_Service_Gmail $service Authorized Gmail API instance.
* @param string $strEmail Почта пользователя
* @return object $objLabels - объект - список меток
* @throws Exception
*/
function listLabels(Google_Service_Gmail $service, string $strEmail){
try{
$objLabels = $service->users_labels->listUsersLabels($strEmail);
return $objLabels;
}catch (Exception $e) {
throw new \Exception('Исключение в функции listLabels: '.$e->getMessage());
}
}
// ---------------------------------------------------------------------------------------------
/**
* Добавляем или удаляем метку (флаг) к письму
*
* @param Google_Service_Gmail $service Authorized Gmail API instance.
* @param string $strEmail Почта пользователя
* @param string $strMessageID ID письма
* @param array $arrAddLabelIds Массив ID меток, которые мы добавляем к письму
* @param array $arrRemoveLabelIds Массив ID меток, которые мы удаляем в письме
* @return object Message - текущее письмо
* @throws Exception
*/
function modifyLabels(Google_Service_Gmail $service, string $strEmail, string $strMessageID, array $arrAddLabelIds = array(), array $arrRemoveLabelIds = array()){
try{
$objPostBody = new Google_Service_Gmail_ModifyMessageRequest();
$objPostBody->setAddLabelIds($arrAddLabelIds);
$objPostBody->setRemoveLabelIds($arrRemoveLabelIds);
$objMessage = $service->users_messages->modify($strEmail,$strMessageID,$objPostBody);
return $objMessage;
}catch (Exception $e) {
throw new \Exception('Исключение в функции modifyLabels: '.$e->getMessage());
}
}
// ---------------------------------------------------------------------------------------------
}
При любом взаимодействии с Gmail первым делом мы вызываем функцию getService($strEmail) класса GmailAPI, которая возвращает «авторизованный» объект для работы с почтовым ящиком $strEmail. Далее этот объект уже передаётся в любую другую функцию для уже непосредственно выполнения нужных нам действий. Все остальные функции в классе GmailAPI уже выполняют конкретные задачи:
- listMessageIDs — находит письма по заданным критериям и возвращает их ID (передаваемая в функцию listUsersMessages Gmail API строка поиска писем должна быть аналогична строке поиска в веб-интерфейсе почтового ящика),
- deleteMessages — удаляет письма с переданными в неё ID (функция batchDelete API Gmail удаляет не более 1000 писем за один проход, поэтому пришлось разбить массив переданных в функцию ID на несколько массивов по 999 писем и выполнить удаление несколько раз),
- getMessage — получает всю информацию о сообщении с переданным в неё ID,
- listLabels — возвращает список флагов в почтовом ящике (я использовал её, чтобы получить ID флага, который изначально был создан в веб-интерфейсе ящика, и присваивается нужным сообщениям)
- modifyLabels — добавляет или удаляет флаги к сообщению
Далее, у нас есть задача удаления старых писем в различных почтовых ящиках. При этом старыми мы считаем письма, полученные своё количество дней назад для каждого почтового ящика. Для реализации этой задачи пишем следующий скрипт, ежедневно запускаемый cron'ом:
Удаление старых писем
SPL
<?php
/**
* Удаляем письма в почтовых ящиках Gmail
* Используем сервисный аккаунт и его ключ
*/
require __DIR__ .'/../general/config/config.php'; // Общий файл конфигурации
require __DIR__ .'/../vendor/autoload.php'; // Загрузчик внешних компонент
// Задаём количества дней хранения почты в ящиках
$arrMailBoxesForClean = array(
'a@domain.com' => 30,
'b@domain.com' => 30,
'c@domain.com' => 7,
'd@domain.com' => 7,
'e@domain.com' => 7,
'f@domain.com' => 1
);
$arrErrors = array(); // Массив ошибок
$objGmailAPI = new GmailAPI(); // Класс для работы с GMail
// Проходим по списку почтовых ящиков, из которых нужно удалить старые письма
foreach ($arrMailBoxesForClean as $strEmail => $intDays) {
try{
// Подключаемся к почтовому ящику
$service = $objGmailAPI->getService($strEmail);
// Указываем условие выборки писем в почтовом ящике
$arrParams = array('before' => date('Y/m/d', (time() - 60 * 60 * 24 * $intDays)));
// Получаем массив писем, подходящих для удаления
$arrIDs = $objGmailAPI->listMessageIDs($service,$strEmail,$arrParams);
// Удаляем письма по их ID в массиве $arrIDs
if (count($arrIDs)) $objGmailAPI->deleteMessages($service,$strEmail,$arrIDs);
// Удаляем все использованные переменные
unset($service,$arrIDs);
}catch (Exception $e) {
$arrErrors[] = $e->getMessage();
}
}
if (count($arrErrors)){
$strTo = 'my_email@domain.com';
$strSubj = 'Ошибка при удалении старых писем из почтовых ящиков';
$strMessage = 'При удалении старых писем из почтовых ящиков возникли следующие ошибки:'.
'<ul><li>'.implode('</li><li>',$arrErrors).'</li></ul>'.
'<br/>URL: '.filter_input(INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL);
$objMailSender = new mailSender();
$objMailSender->sendMail($strTo,$strSubj,$strMessage);
}
Скрипт подключается к каждому заданному почтовому ящику, выбирает старые письма и удаляет их.
Задача формирования отчётов для менеджера о недоставленных письмах на основании автоматических отчётов решается следующим скриптом:
Фильтрация и маркировка писем
SPL
<?php
/*
* Подключаемся к ящику a@domain.com
* Берём с него письма о том, что наши письма не доставлены: отправитель: mailer-daemon@googlemail.com
* Проверяем почтовые ящики в этих письмах. Если они есть у клиентов на нашем сайте, отправляем на b@domain.com
* письмо об этом
*/
require __DIR__ .'/../general/config/config.php'; // Общий файл конфигурации
require __DIR__ .'/../vendor/autoload.php'; // Загрузчик внешних компонент
$strEmail = 'a@domain.com';
$strLabelID = 'Label_2399611988534712153'; // Флаг reportProcessed - устанавливаем при обработке письма
// Параметры выборки
$arrParams = array(
'from' => 'mailer-daemon@googlemail.com', // Письма об ошибках приходят с этого адреса
'in' => 'inbox', // Во входящих
'after' => date('Y/m/d', (time() - 60 * 60 * 24)), // За последние сутки
'has' => 'nouserlabels' // Без флага
);
$arrErrors = array(); // Массив ошибок
$objGmailAPI = new GmailAPI(); // Класс для работы с GMail
$arrClientEmails = array(); // Массив адресов электронной почты, на которые не удалось отправить сообщение
try{
// Подключаемся к почтовому ящику
$service = $objGmailAPI->getService($strEmail);
// Находим в нём отчёты за последние сутки о том, что письма не доставлены
$arrIDs = $objGmailAPI->listMessageIDs($service,$strEmail, $arrParams);
// Для найденных писем получаем заголовок 'X-Failed-Recipients', в котором содержится адрес, на который пыталось быть отправлено письмо
if (count($arrIDs)){
foreach ($arrIDs as $strMessageID){
// Получаем метаданные письма
$objMessage = $objGmailAPI->getMessage($service,$strEmail,$strMessageID,'metadata',array('X-Failed-Recipients'));
// Заголовки письма
$arrHeaders = $objMessage->getPayload()->getHeaders();
// Находим нужный
foreach ($arrHeaders as $objMessagePartHeader){
if ($objMessagePartHeader->getName() == 'X-Failed-Recipients'){
$strClientEmail = mb_strtolower(trim($objMessagePartHeader->getValue()), 'UTF-8');
if (!empty($strClientEmail)) {
if (!in_array($strClientEmail, $arrClientEmails)) $arrClientEmails[] = $strClientEmail;
}
// Помечаем письмо флагом reportProcessed, чтобы не выбирать его в следующий раз
$objGmailAPI->modifyLabels($service,$strEmail,$strMessageID,array($strLabelID));
}
}
}
}
unset($service,$arrIDs,$strMessageID);
}catch (Exception $e) {
$arrErrors[] = $e->getMessage();
}
// Если найдены адреса электронной почты, на которые не удалось доставить сообщения, проверяем их в базе
if (count($arrClientEmails)) {
$objClients = new clients();
// Получаем все email всех клиентов
$arrAllClientsEmails = $objClients->getAllEmails();
foreach ($arrClientEmails as $strClientEmail){
$arrUsages = array();
foreach ($arrAllClientsEmails as $arrRow){
if (strpos($arrRow['email'], $strClientEmail) !== false) {
$arrUsages[] = 'как основной email клиентом "<a href="'.MANAGEURL.'?m=admin&sm=clients&edit='.$arrRow['s_users_id'].'">'.$arrRow['name'].'</a>"';
}
if (strpos($arrRow['email2'], $strClientEmail) !== false) {
$arrUsages[] = 'как дополнительный email клиентом "<a href="'.MANAGEURL.'?m=admin&sm=clients&edit='.$arrRow['s_users_id'].'">'.$arrRow['name'].'</a>"';
}
if (strpos($arrRow['site_user_settings_contact_email'], $strClientEmail) !== false) {
$arrUsages[] = 'как контактный email клиентом "<a href="'.MANAGEURL.'?m=admin&sm=clients&edit='.$arrRow['s_users_id'].'">'.$arrRow['name'].'</a>"';
}
}
$intUsagesCnt = count($arrUsages);
if ($intUsagesCnt > 0){
$strMessage = 'Не удалось доставить письмо с сайта по адресу электронной почты <span style="color: #000099;">'.$strClientEmail.'</span><br/>
Этот адрес используется';
if ($intUsagesCnt == 1){
$strMessage .= ' '.$arrUsages[0].'<br/>';
}else{
$strMessage .= ':<ul>';
foreach ($arrUsages as $strUsage){
$strMessage .= '<li>'.$strUsage.'</li>';
}
$strMessage .= '</ul>';
}
$strMessage .= '<br/>Пожалуйста, уточните у клиента актуальность этого адреса электронной почты.<br/><br/>
Это письмо было отправлено автоматически, не отвечайте на него';
if (empty($objMailSender)) $objMailSender = new mailSender();
$objMailSender->sendMail('b@domain.com','Проверьте email клиента',$strMessage);
}
}
}
if (count($arrErrors)){
$strTo = 'my_email@domain.com';
$strSubj = 'Ошибка при обработке отчётов о недоставленных письмах';
$strMessage = 'При обработке отчётов о недоставленных письмах возникли следующие ошибки:'.
'<ul><li>'.implode('</li><li>',$arrErrors).'</li></ul>'.
'<br/>URL: '.filter_input(INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL);
if (empty($objMailSender)) $objMailSender = new mailSender();
$objMailSender->sendMail($strTo,$strSubj,$strMessage);
}
Этот скрипт так же, как и первый, подключается к заданному почтовому ящику, выбирает из него нужные письма (отчёты о недоставленных сообщениях) без флага, находит в письме адрес электронной почты, на которой пыталось быть отправлено письмо и маркирует это письмо флагом «Обработано». Затем уже с найденным адресом электронной почты производятся манипуляции, в результате которых формируется человекочитаемое письмо ответственному сотруднику.
Исходники доступны на GitHub.
Вот и всё, что я хотел поведать в этой статье. Спасибо за прочтение! Если у Вас защипало в глазах от моего кода, просто сверните спойлер или напишите свои замечания — буду рад конструктивной критике.
===========
Источник:
habr.com
===========
Похожие новости:
- [Разработка веб-сайтов, Разработка под iOS, IT-компании] Apple отказалась от претензий к WordPress за отсутствие покупок внутри приложения
- [Разработка веб-сайтов, Open source, JavaScript, GitHub, VueJS] Создание библиотеки из VUE компонента и публикация на NPM
- [Разработка веб-сайтов, JavaScript] Web Push и Vue.js, еще раз о работе с веб-пуш сообщениями на фронтенде
- [Разработка веб-сайтов] Как использовать Websocket на примере простого Express API?
- [Разработка веб-сайтов, JavaScript, Тестирование веб-сервисов] Эффективное тестирование верстки
- [Разработка веб-сайтов] [HTML, CSS, JavaScript] Знакомство с Rome — компилятор, сборщик, линтер, тесты в одном флаконе
- [Разработка веб-сайтов, PHP] Xdebug через Windows Subsystem For Linux 2 (WSL2)
- [Программирование, .NET] Полезные приемы для работы с EntityFramework Core
- [IT-инфраструктура, Браузеры, Высокая производительность, Разработка веб-сайтов, Сетевые технологии] Почему CDN не нужны: развенчиваем старый миф
- [PHP, Проектирование и рефакторинг, Серверная оптимизация, Параллельное программирование] Пишем простую ORM с возможностью смены БД на лету
Теги для поиска: #_razrabotka_vebsajtov (Разработка веб-сайтов), #_php, #_programmirovanie (Программирование), #_proektirovanie_i_refaktoring (Проектирование и рефакторинг), #_google_api, #_imap, #_php, #_oauth2, #_gmail_api, #_razrabotka_vebsajtov (
Разработка веб-сайтов
), #_php, #_programmirovanie (
Программирование
), #_proektirovanie_i_refaktoring (
Проектирование и рефакторинг
), #_google_api
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 20:18
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Оказавшись одним из счастливчиков, совершенно не готовым к тому, что с 15 февраля 2021 года авторизация в Gmail и других продуктах будет работать только через OAuth, я прочитал статью "Google хоронит расширение PHP IMAP" и загрустил начал предпринимать действия по замене расширения PHP IMAP в своём проекте на API Google. Вопросов было больше, чем ответов, поэтому заодно нацарапал мануал. У меня PHP IMAP используется для следующих задач:
Эти две задачи мы и будем решать при помощи API Gmail в данной статье (а заодно и отключим в настройках почтовых ящиков доступ для небезопасных приложений, который был включён для работы PHP IMAP, и, собственно, перестанет работать в страшный день в феврале 2021). Использовать будем так называемый сервисный аккаунт приложения Gmail, который при соответствующей настройке даёт возможность подключения ко всем почтовым ящикам организации и выполнения в них любых действий. 1. Создаём проект в консоли разработчика Google API При помощи этого проекта мы и будем осуществлять API-взаимодействие с Gmail, и в нём же создадим тот самый сервисный аккаунт. Для создания проекта:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 20:18
Часовой пояс: UTC + 5