Jump to content
JIMSMITH

Sending Email VIA Google.

Recommended Posts

For some reason I have to authorize my application through google to send email again.  During the process I check the box indicates read, compuse, send email.  I encounter an error   indicated in the image below.  The firewall has been turned off on this computer.  Does anyone know how to resolve this error?

 

gmailauth.png

Share this post


Link to post

Why are you connecting to localhost? What exact steps are you doing to reach this error? What API are you using to access Google?

Share this post


Link to post
10 hours ago, Remy Lebeau said:

Why are you connecting to localhost? What exact steps are you doing to reach this error? What API are you using to access Google?

Not sure why I end up with local.  The application is in dev/test mode.  I  get to a web page that says google has not verified this app.  Thanks for your help

Google uses localhost for OAuth2 authentication during development to simplify the process of testing and debugging. When you're developing an application, you can use localhost as the redirect URI to avoid the complexities of setting up a public server for testing purposes. This allows developers to run and test their applications locally without exposing their credentials and tokens to the internet.

Edited by JIMSMITH

Share this post


Link to post
8 hours ago, JIMSMITH said:

Not sure why I end up with local.  The application is in dev/test mode.  I  get to a web page that says google has not verified this app.  Thanks for your help

This error page seems to be a step further in the normal OAuth2 process. You accepted the non-verified app, accepted the terms and now you end up on localhost with the desired code for getting the access token in the url parameters. You need to catch that url with a small http server. After getting that code from the url you can go ahead with the process of getting the access and refresh token.

 

  • Like 1

Share this post


Link to post
5 hours ago, rvk said:

This error page seems to be a step further in the normal OAuth2 process. You accepted the non-verified app, accepted the terms and now you end up on localhost with the desired code for getting the access token in the url parameters. You need to catch that url with a small http server. After getting that code from the url you can go ahead with the process of getting the access and refresh token.

 

Do I find a http server on the web and install it?  I will be checking for solutions in the meanwhile.  The core of the app that I am testing is from Geoffrey Smith's GmailAuthsmtp demo.  This entire oauth2 process is new to me and a little unclear.   I think it has an http server component internally.  Not sure if I broke it an it no longer works.

 

Share this post


Link to post
1 minute ago, JIMSMITH said:

Do I find a http server on the web and install it?

No no, because you want to catch that URL it's easiest to create your own listening thread.

I have an example for OAuth2 in combination with Lazarus/FPC and Synpase.

(You can also use Synapse on Delphi but you could also use Indy)

 

https://github.com/rvk01/google-oauth2

 

Relevant snippet:

This is a minimalistic http server which server a string saying your program now has access and you can close the window.

 

type
  THTTPServerThread = class(TThread)
  private
    ListenerSocket: TTCPBlockSocket;
    ConnectionSocket: TTCPBlockSocket;
  public
    Authorize_token: string;
    procedure Execute; override;
    procedure CancelThread(Sender: TObject; var CanClose: boolean);
  end;

procedure THTTPServerThread.CancelThread(Sender: TObject; var CanClose: boolean);
begin
  Terminate;
end;

procedure THTTPServerThread.Execute;
var
  S: string;
  method, uri, protocol: string;
  OutputDataString: string;
  SendDataString: string;
begin
  Authorize_token := '';
  FreeOnTerminate := False;
  ListenerSocket := TTCPBlockSocket.Create;
  ConnectionSocket := TTCPBlockSocket.Create;

  try
    ListenerSocket.CreateSocket;
    ListenerSocket.setLinger(True, 10);
    ListenerSocket.Bind('localhost', '1500');
    ListenerSocket.Listen;
    while not terminated do
    begin
      Sleep(1000);
      // Application.ProcessMessages;
      if ListenerSocket.CanRead(1000) and not terminated then
      begin
        ConnectionSocket.Socket := ListenerSocket.Accept;

        // read request line
        S := string(ConnectionSocket.RecvString(1000));
        method := fetch(S, ' ');
        uri := fetch(S, ' ');
        protocol := fetch(S, ' ');

        // read request headers
        repeat
          S := string(ConnectionSocket.RecvString(1000));
        until S = '';

        // /?code=4/fegArZQDUJqFdoCw-1DU16ohYsoA5116feRuCW0LiuQ
        // /?error=access_denied
        Authorize_token := '';
        if Pos('code=', uri) > 0 then
        begin
          Authorize_token := Copy(uri, Pos('code=', uri) + 5);
        end;

        if Authorize_token = '' then
        begin
          SendDataString :=
            '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' + ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' + CRLF + '<html><center><h1>Something went wrong.<br><br>Application does not have access.<br><br>You can close this page.</h1></center></html>' + CRLF;
        end
        else
        begin
          SendDataString :=
            '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' + ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' + CRLF + '<html><center><h1>Application now has access.<br><br>You can close this page.</h1></center></html>' + CRLF;
        end;

        OutputDataString := 'HTTP/1.0 200' + CRLF;
        OutputDataString := OutputDataString + 'Content-type: Text/Html' + CRLF;
        OutputDataString := OutputDataString + 'Content-length: ' + IntToStr(Length(SendDataString)) + CRLF;
        OutputDataString := OutputDataString + 'Connection: close' + CRLF;
        OutputDataString := OutputDataString + 'Date: ' + Rfc822DateTime(now) + CRLF;
        OutputDataString := OutputDataString + 'Server: Synapse' + CRLF;
        OutputDataString := OutputDataString + '' + CRLF;
        ConnectionSocket.SendString(ansistring(OutputDataString));
        ConnectionSocket.SendString(ansistring(SendDataString));

        ConnectionSocket.CloseSocket;

        Terminate;
      end;
    end;

  finally
    ConnectionSocket.Free;
    ListenerSocket.Free;
  end;

end;

 

Share this post


Link to post

BTW. You can still use app-passwords with Google. So if you are only doing this for you own account, creating an app password is easiest. If you need to allow your users to use their own account, then you need OAuth2.

 

Share this post


Link to post
4 hours ago, JIMSMITH said:

Do I find a http server on the web and install it?  I will be checking for solutions in the meanwhile.  The core of the app that I am testing is from Geoffrey Smith's GmailAuthsmtp demo. 

Geoffrey's demo uses Indy's TIdSMTP component to send email with an OAuth2 token. Indy has a TIdHTTPServer component (or TIdSimpleServer if you don't need a full-blown HTTP server). 

Share this post


Link to post
13 minutes ago, Remy Lebeau said:

Geoffrey's demo uses Indy's TIdSMTP component to send email with an OAuth2 token. Indy has a TIdHTTPServer component (or TIdSimpleServer if you don't need a full-blown HTTP server). 

Remy ,

The product has a datamodule with a idhttpserver on it.  I might have broken this part of the implementation.  This is new ground for me with additional complications beyond my daily scope and skill set.  I am digging into it to figure this oauth 2.0 process out.  All assistance/input has been greatly appreciated.  I need one of you sharp gents on retainer. 

Share this post


Link to post
6 hours ago, Remy Lebeau said:

Geoffrey's demo uses Indy's TIdSMTP component to send email with an OAuth2 token. Indy has a TIdHTTPServer component (or TIdSimpleServer if you don't need a full-blown HTTP server). 

Here is the latest information.  The referenced mail project does include a TidHTTPServer.  The port was changed and it no longer worked.  I have corrected this problem and it works.  Truth is I did not know that Oauth 2.0 communication required all of these pieces.  I wish there was a flow diagram.  Thanks for all of your help education.

Edited by JIMSMITH

Share this post


Link to post
23 minutes ago, JIMSMITH said:

I wish there was a flow diagram. 

Well... Type in Oauth 2.0 communication in Google (or similar search terms), then select Images... and there you go... Lots of flow diagrams :classic_biggrin:

Share this post


Link to post
1 hour ago, JIMSMITH said:

Truth is I did not know that Oauth 2.0 communication required all of these pieces.  I wish there was a flow diagram.

All of the major OAuth providers - Google, Microsoft, etc - should have full documentation about their workflows.

Share this post


Link to post
4 hours ago, Remy Lebeau said:

All of the major OAuth providers - Google, Microsoft, etc - should have full documentation about their workflows.

Correct! But... it's not an easy part of software to write!

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×