How do I use OAuth 2.0 to send Gmail from Indy?
Asked Answered
L

1

17

The following code successfully sends an e-mail using Google's Gmail servers, but only after lowering the Google account security settings to "Allow less secure apps."

The code offered below (originally from Remy LeBeau) does not incorporate OAuth 2.0, which is required if you do not want to ask your users to make the seemingly tough decision to lower their security setting to allow your application to succeed. How do I incorporate OAuth 2.0 into the Indy solution to satisfy Google's higher security standard?

Working Solution:

function TTabbedwithNavigationForm.SendEmailNow(FromStr, ToStr, Subject,
MessageBody, Host: String; Port: Integer; UserName, Pass: String): Boolean;
  begin

///From Remy LeBeau Indy SMTP with SSL via gmail host
Result := False;

try
  IdMessage1 := nil;
  IdSSLIOHandlerSocketOpenSSL1 := nil;
  IdSMTP1 := nil;
  try
    //setup mail message
    try
      IdMessage1                         := TIdMessage.Create(nil);
      IdMessage1.From.Address                := FromStr;//// change to league email
      IdMessage1.Recipients.EMailAddresses   := ToStr;
      IdMessage1.Subject                     := Subject;
      IdMessage1.Body.Text                   := MessageBody;
      //if FileExists(datafilename) then
      //  IdAttachmentFile := TIdAttachmentFile.Create(IdMessage1.MessageParts, datafilename);
    except
      Exception.RaiseOuterException(Exception.Create('Could not create message, please try again later'));
    end;

//setup TLS
try
  IdSSLIOHandlerSocketOpenSSL1                    := TIdSSLIOHandlersocketopenSSL.Create(nil);
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method      := sslvTLSv1;
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode        := sslmUnassigned;
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyMode  := [];
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyDepth := 0;
except
  Exception.RaiseOuterException(Exception.Create('Could not create SSL handler, please try again later'));
end; // of try ssl

//setup SMTP
try
  IdSMTP1           := TIdSMTP.Create(nil);
  IdSMTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL1;
  IdSMTP1.UseTLS    := utUseExplicitTLS;
  IdSMTP1.Host      := Host;//'smtp.gmail.com';
  IdSMTP1.Port      := Port;//587;
  IdSMTP1.Username  := UserName;  // '[email protected]';
  IdSMTP1.password  := Pass;  //***gmail account password';
except
  Exception.RaiseOuterException(Exception.Create('Could not create SMTP handler, please try again later'));
end; // of try

try
  IdSMTP1.Connect;
  try
    IdSMTP1.Send(IdMessage1) ;
  finally
    IdSMTP1.Disconnect;
  end;
except
  Exception.RaiseOuterException(Exception.Create('Could not send secure email, please try again later'));
end;
  finally
    IdSMTP1.Free;
    IdSSLIOHandlerSocketOpenSSL1.Free;
    IdMessage1.Free;
    Result := True;
  end;
except
  on E: Exception do
  begin
    if E.InnerException <> nil then
      ShowMessage('ERROR: ' + E.Message + #13#13 + E.InnerException.Message)
    else
      ShowMessage('ERROR: ' + E.Message);
  end;
end;

/// End Remy LeBeau Code

end;
Layby answered 4/11, 2014 at 18:2 Comment(6)
Have you checked this thread and this project?Test
I have 2-step verification enabled on my Gmail account (which disables the "allow less secure apps" option), and I am able to login to Gmail with Indy using a Google app password instead of OAuth.Cockatrice
Hey I'm already talking to the author of the original solution -- very cool. I am hesitant to rely on any solution which requires the user to make a change to their Google account settings - before my application will succeed. If adding a Google app password to my Delphi XE5 mobile application means the user does not have to make any change to their Google account - then that would be a great solution. Could you explain how to add a Google app password to the Delphi project or the SMTP component properties?Layby
You don't add a password to your project, ImageBase. Rather, you continue requesting the user's password, same as always. However, rather than the regular password, the user provides an application-specific password that the user generates under his or her account's security settings. For example, I have an app-specific password for my old Android phone because its account setup predates Google's two-step OAuth mechanism.Bashemeth
Leonardo Herrera's comment was very helpful for better understanding the effort required to incorporate OAuth 2 with an Indy component. unfortunately, the component demonstrated is IMAP, not SMTP. My requirement is to send emails, not to fetch/read emails from the account's inbox.Layby
TMS and CData both have components that allow you to talk to the Gmail API directly (not using SMTP, but HTTP instead). Assuming that you are willing to part with some money. Both use OAuth.Nameplate
S
-5

You need to import lib BackgroundMailLibrary

BackgroundMail bm = new BackgroundMail(PasswordChangeActivity.this);
                                            bm.setGmailUserName(mail id);
                                            bm.setGmailPassword(Utils.decryptIt(password)); 
                                            bm.setMailTo(ownerEmail);
                                            bm.setFormSubject(subject);
                                            bm.setFormBody(body);
                                            bm.send();
Stupid answered 30/7, 2015 at 11:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.