Problem sending emails from my application

Hi All,

Trying to send emails from my app but having some issues, It seems that the RefreshToken string is empty but I don’t understand how to resolve this

Could someone please have a look and send me some guidance. My “SendMessage” procedure is listed below

I’m using GmailAuthSMTP as a guide

My setup is

Delphi 12 
IdSMTP1: TIdSMTP;
IdMessage1: TIdMessage;
IdSSLIOHandlerSocketSMTP: TIdSSLIOHandlerSocketOpenSSL;
JSON file located in the same directory as the exe file (ie the debug file)

In my FormCreate procedure I have

  /// ///////
  Provider.AuthenticationType := TIdSASLXOAuth;
  Provider.AuthorizationEndpoint := 'https://accounts.google.com/o/oauth2/auth?access_type=offline';
  Provider.AccessTokenEndpoint := 'https://accounts.google.com/o/oauth2/token';
  Provider.LogoutEndpoint := 'https://www.google.com/accounts/Logout';
  Provider.ClientID := 'XXXXXXXXXXXX.apps.googleusercontent.com';
  Provider.ClientSecret := 'XXXXXXXXXXXXXXXXXXXXX';
  Provider.Scopes := 'https://mail.google.com/ openid email';
  Provider.SmtpHost := 'smtp.gmail.com';
  Provider.SmtpPort := 465;
  Provider.AuthName := 'Google';
  Provider.TLS := utUseImplicitTLS;
  Provider.TwoLinePOPFormat := False;
  /// ///////
  LFilename := ChangeFileExt(ParamStr(0), '.ini');
  FIniSettings := TIniFile.Create(LFilename);
  /// ///////
  FOAuth2_Enhanced := TEnhancedOAuth2Authenticator.Create(nil);
  SetupAuthenticator;

This is the Send message procedure Im using

procedure TEmail_Frm.SendMessage;
var
  IdMessage: TIdMessage;
  xoauthSASL: TIdSASLListEntry;
  oldRefreshToken: string;
  LTokenName: string;
  recepient: TIdEMailAddressItem;
begin
  // if we only have refresh_token or access token has expired
  // request new access_token to use with request
  FOAuth2_Enhanced.ClientID := Provider.ClientID;
  FOAuth2_Enhanced.ClientSecret := Provider.ClientSecret;


  /// /////// <<<<<<<<< Exception raised here at line 120 of REST.Authenticator.EnhancedOAuth;
  FOAuth2_Enhanced.RefreshAccessTokenIfRequired;   // <<<<<<<<< Exception raised here
  /// ///////   if RefreshToken = '' then
  /// ///////  raise EOAuth2Exception.Create(SRefreshTokenNeeded);


  if (oldRefreshToken <> FOAuth2_Enhanced.RefreshToken) and (not FOAuth2_Enhanced.RefreshToken.IsEmpty) then
    begin
      LTokenName := Provider.AuthName + 'Token';
      FIniSettings.WriteString('Authentication', LTokenName, FOAuth2_Enhanced.RefreshToken);
    end;
  /// ///////
  if FOAuth2_Enhanced.AccessToken.Length = 0 then
    begin
      Exit;
    end;
  /// ///////
  IdSMTP1.Host := Provider.SmtpHost; // 'smtp.gmail.com';
  IdSMTP1.Port := Provider.SmtpPort; // 465;
  IdSMTP1.UseTLS := Provider.TLS;
  IdSMTP1.AuthType := satSASL;
  IdSMTP1.Username := Grant_Brown_Txt;
  IdSMTP1.Password := Brownes_Block_House_Password;
  /// ////////
  xoauthSASL := IdSMTP1.SASLMechanisms.Add;
  xoauthSASL.SASL := Provider.AuthenticationType.Create(nil);
  TIdSASLOAuthBase(xoauthSASL.SASL).Token := FOAuth2_Enhanced.AccessToken;
  TIdSASLOAuthBase(xoauthSASL.SASL).User := Brownes_Block_House_Email_Address; // fromAddress;
  IdSSLIOHandlerSocketSMTP.SSLOptions.SSLVersions := [sslvTLSv1_2];
  /// //////// Configure the Message component
  IdMessage1.From.Name := Current_Sender_User_Name;
  IdMessage1.From.Address := Brownes_Block_House_Email_Address;
  IdMessage1.subject := Trim(Subject_EditBx.Text);
  IdMessage1.Priority := mpHighest;
  IdMessage1.Organization := Brownes_Block_House_Name;
  IdMessage1.ContentType := 'text/plain';
  /// // Send the email message
  try
    IdSMTP1.Connect;
    IdSMTP1.Authenticate;
    IdSMTP1.Send(IdMessage);
  finally
    IdSMTP1.Disconnect;
  end;
end;

Many many thanks in advance,

Thank you
Grant

FOAuth2_Enhanced.AccessType := ‘offline’; // Request offline access

Did you try adding this line before fetching refresh token.

Hi Grant,

I am the creator of that project. I think the reason why you don’t have a refresh_token is because you haven’t gone through the browser login process to get a refresh_token and if you have… you haven’t saved it.

I also note from the code above you have the following code - which is not the correct way. The username and password are entered in the web browser.

I designed the project so that you could just add the EmailOAuthDm.pas datamodule into your project, create the datamodule object and use the functions in that file.

I recently updated the project as well to make it support TLS 1.3 with TaurusTLS and added a function that can send HTML email messages with inline images and attachments.

1 Like

Grant, Geoff

I am looking for some code to send emails to outlook.com.

Do you have any examples?

Geoff, will your code do it?

Regards
Graeme