Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Настройка отправки PDF-файлов через Gmail API в Delphi: решение проблемы "username and password not accepted" после подтверждения OAuth-подхода

Delphi , Интернет и Сети , Почтовый клиент

 

В статье рассматривается распространенная проблема, с которой сталкиваются разработчики, использующие Delphi для отправки электронных писем через Gmail с использованием OAuth 2.0. После успешного прохождения процесса подтверждения в Google Console и получения необходимых разрешений (scope), пользователи часто получают ошибку "username and password not accepted" при попытке отправить письмо. Данная статья предлагает анализ проблемы и предлагает решения, основанные на обсуждении в сообществе Delphi и Pascal.

Описание проблемы

Проблема возникает после того, как приложение успешно прошло процесс авторизации Google OAuth 2.0 и получило access token и refresh token. Приложение использует полученные токены для аутентификации при отправке письма через SMTP (Simple Mail Transfer Protocol). Однако, несмотря на успешную авторизацию, Gmail отклоняет запрос, выдавая ошибку "username and password not accepted".

Анализ проблемы

Обсуждение на форуме Delphi (emileverh, rvk, Remy Lebeau) выявило несколько потенциальных причин этой ошибки:

  • Необходимость CASA Tier 2 Security Assessment: Google требует прохождения оценки безопасности CASA Tier 2 для приложений, использующих Gmail API. Отсутствие прохождения этой оценки может привести к ограничению функциональности, включая возможность отправки писем. Однако, прохождение этой оценки сложно для приложений, работающих в автономном режиме (offline Windows application), что, по словам rvk, привело к отказу от процесса.
  • Неправильный scope: Несмотря на то, что scope https://www.googleapis.com/auth/gmail.send был запрошен и одобрен в Google Console, его использование в SMTP-аутентификации может быть не поддерживается.
  • Проблема с чекбоксом "Allow send" в Google Console: При прохождении процесса подтверждения в Google Console, не всегда по умолчанию включен чекбокс "Allow send". Необходимо убедиться, что этот чекбокс установлен.
  • Ограничение на использование gmail.send scope с SMTP: Согласно документации Google и информации, полученной на Stack Overflow, использование ограниченного gmail.send scope непосредственно с SMTP не поддерживается. Требуется использование Gmail API (через REST) для отправки писем.

Решение: Использование Gmail API (REST)

Наиболее надежным решением, подтвержденным сообществом, является переход от использования SMTP с OAuth 2.0 к прямому использованию Gmail API (REST). Это позволяет обойти ограничения, связанные с gmail.send scope и SMTP-аутентификацией.

Пример кода (Object Pascal - Delphi) для отправки письма через Gmail API:

uses
  IdHTTP,
  IdJSON,
  System.NetEncoding;

procedure SendEmailViaGmailAPI(const RecipientEmail: string; const Subject: string; const Body: string; const AttachmentPath: string);
var
  HTTP: TIdHTTP;
  JSONData: TJSONValue;
  AccessToken: string;
  URL: string;
  Response: string;
begin
  HTTP := TIdHTTP.Create(nil);
  try
    // Замените на ваш Access Token.  Реальный код должен получать его из безопасного хранилища.
    AccessToken := 'YOUR_ACCESS_TOKEN';

    // Создание URL для отправки письма
    URL := 'https://gmail.googleapis.com/upload/gmail/v1/users/me/messages/send';

    // Создание JSON данных для запроса
    JSONData := TJSONObject.Create;
    try
      JSONData.AddPair('raw', TJSONObject.Create);
      JSONData['raw'].AddPair('body', TJSONObject.Create);
      JSONData['raw']['body'].AddPair('data', TJSONString.Create(StringToUTF8(Body)));
      JSONData['raw']['body'].AddPair('filename', TJSONString.Create('message.eml'));
      JSONData['raw']['body'].AddPair('content_type', TJSONString.Create('text/plain'));

      // Добавление данных для заголовков
      JSONData['raw'].AddPair('headers', TJSONObject.Create);
      JSONData['raw']['headers'].AddPair('From', TJSONString.Create('me'));
      JSONData['raw']['headers'].AddPair('To', TJSONString.Create(RecipientEmail));
      JSONData['raw']['headers'].AddPair('Subject', TJSONString.Create(Subject));

      // Добавление вложения (если есть)
      if not Trim(AttachmentPath).IsEmpty() then
      begin
        // Чтение файла вложения
        var FileContent: string;
        FileContent := TEncoding.UTF8.GetString(TFile.ReadAllBytes(AttachmentPath));

        // Добавление данных для вложения
        JSONData['raw'].AddPair('attachments', TJSONObject.Create);
        JSONData['raw']['attachments'].AddPair('data', TJSONString.Create(StringToUTF8(FileContent)));
        JSONData['raw']['attachments'].AddPair('filename', TJSONString.Create(ExtractFileName(AttachmentPath)));
        JSONData['raw']['attachments'].AddPair('content_type', TJSONString.Create(GetFileContentType(AttachmentPath)));
      end;

      // Преобразование JSON в строку
      var JSONString: string;
      JSONString := TJSONObject.ToString(JSONData);

      // Отправка запроса
      HTTP.Request.ContentType := 'application/json';
      HTTP.Request.Accept := 'application/json';
      HTTP.Request.Headers.AddValue('Authorization', 'Bearer ' + AccessToken);
      Response := HTTP.Post(URL, JSONString);

      // Обработка ответа
      if HTTP.Response.StatusCode = 200 then
      begin
        ShowMessage('Email sent successfully!');
      end
      else
      begin
        ShowMessage('Error sending email: ' + HTTP.Response.StatusCode + ' - ' + HTTP.Response.Content);
      end;
    finally
      JSONData.Free;
    end;
  finally
    HTTP.Free;
  end;
end;

// Вспомогательная функция для определения типа контента файла
function GetFileContentType(const FileName: string): string;
begin
  // Реализация определения типа контента по расширению файла.
  // Это пример, и его необходимо расширить для поддержки большего количества типов файлов.
  if LowerCase(ExtractFileExt(FileName)) = '.pdf' then
    Result := 'application/pdf'
  else if LowerCase(ExtractFileExt(FileName)) = '.doc' then
    Result := 'application/msword'
  else if LowerCase(ExtractFileExt(FileName)) = '.docx' then
    Result := 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
  else
    Result := 'application/octet-stream'; // По умолчанию
end;

Альтернативные решения и рекомендации:

  • Использование Indy OAuth components: Remy Lebeau отметил, что Indy недавно получил новые компоненты OAuth, которые могут упростить процесс получения и обновления токенов. Однако, для отправки писем потребуется использовать TIdHTTP для взаимодействия с Gmail API.
  • Использование сторонних библиотек: Существуют сторонние библиотеки для Delphi, которые упрощают работу с Gmail API, предоставляя более удобные интерфейсы.
  • Проверка настроек Google Console: Убедитесь, что в Google Console правильно настроен scope https://www.googleapis.com/auth/gmail.send и включен чекбокс "Allow send".
  • App Passwords: Если использование Gmail API (REST) не подходит, можно рассмотреть использование App Passwords для SMTP-аутентификации, как это делал rvk. Однако, следует учитывать, что App Passwords могут быть отключены Google в будущем.

Заключение

Проблема "username and password not accepted" при отправке писем через Gmail с использованием OAuth 2.0 в Delphi часто связана с неправильной конфигурацией scope, необходимостью прохождения CASA Tier 2 Security Assessment или ограничением на использование gmail.send scope с SMTP. Наиболее надежным решением является переход к использованию Gmail API (REST) для отправки писем, что позволяет обойти эти ограничения и обеспечивает более стабильную и предсказуемую работу приложения. Использование Indy OAuth components или сторонних библиотек может упростить процесс интеграции с Gmail API.

Создано по материалам из источника по ссылке.

Статья посвящена решению проблемы, возникающей у разработчиков Delphi при отправке электронных писем через Gmail с использованием OAuth 2.0, когда после успешной авторизации Gmail отклоняет запрос с ошибкой "username and password not accepted".


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Почтовый клиент ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-06-16 09:02:54/0.0084190368652344/1