I have successfully sent email using GMail's SMTP server with the code below. I'm using Delphi 2006 and the latest version of Indy (10.6.2) and latest fulgan ssl libraries. The problem is that I had to turn down the GMail security settings as explained in the Google link. With the default high settings I get a cryptic error something like this: "https://accounts.google.com/ContinueSignIn?[...] Please log in via your web browser and then try again. Learn more at https://support.google.com/mail/bin/answer.py?answer=78754 [...] - gsmtp". How can I adjust the code below to use GMail's high security settings?
IdSMTP1.host:='smtp.gmail.com';
IdSMTP1.username:='[deleted]#gmail.com';
IdSMTP1.Password:='[deleted]';
IdSMTP1.port:=587;
IdSMTP1.UseTLS:=utUseExplicitTLS;
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode := sslmClient;
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method:= sslvTLSv1;
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyDepth := 2;
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyMode := [];
IdSSLIOHandlerSocketOpenSSL1.Host := IdSMTP1.Host;
IdSSLIOHandlerSocketOpenSSL1.Port := IdSMTP1.Port;
IdMessage1.From.address := '[deleted]#gmail.com';
IdMessage1.CClist.EMailAddresses:= edit1.Text;
IdMessage1.Subject:= 'Subject is here';
IdMessage1.Body.Clear;
Idmessage1.Body.Add('Body is here');
IdSMTP1.Connect;
try
try
idSMTP1.Send(IdMessage1);
except on E:Exception do
Memo1.Lines.Insert(0, 'ERROR: ' + E.Message);
end;
finally
if idSMTP1.Connected then idSMTP1.Disconnect;
end;
Related
I'm trying to POST to a https Web service from Delphi 7. Initially the error was "Unable to Load SSL library". So placed ssleay32.dll & libeay32.dll (from indy_openssl096k.zip in https://indy.fulgan.com/SSL/Archive/) in the folder containing my executable.
Now the error is "Error connecting to SSL". In the exception, I also used WhichFailedToLoad() function and below is also reported
"Failed To Load: EVP_md5 X509_digest X509_NAME_hash"
From different sites, I could understand, above functions is part of libeay32.dll. But why is this still reported as FailedToLoad ?
I saw suggestions that updating to Indy10 ca solve this. But the applications I'm working on uses Indy functions on large number of modules and I don't want to cause any issues if Indy update fails. Is there anyway to resolve this error with Indy9. Any help is greatly appreciated.
I have been trying to find out a solution for the past few days and can't get one. Could someone kindly help me please ?
My Code
Protocol := TIdHTTP.Create(nil);
try
jsonToSend := TStringList.create;
Id_HandlerSocket := TIdSSLIOHandlerSocket.create(nil);
Id_HandlerSocket.SSLOptions.Method := sslvTLSv1;
Id_HandlerSocket.SSLOptions.Mode := sslmClient;
Id_HandlerSocket.SSLOptions.VerifyMode := [];
Id_HandlerSocket.SSLOptions.VerifyDepth := 0;
try
jsonToSend.Add('{"Branch":"' + branch + '", "Country":"' + country + '"}');
Protocol.IOHandler := Id_HandlerSocket;
Protocol.Request.ContentType := 'application/json';
Protocol.Request.Accept := '*/*';
Protocol.Post(ServerURL,jsonToSend);
except
on E:EIdOSSLConnectError do
begin
showmessage(E.Message);
showmessage('Failed to Load: ' + IdSSLOpenSSLHeaders.WhichFailedToLoad);
end;
end;
finally
Protocol.Destroy;
Id_HandlerSocket.Free;
jsonToSend.Destroy;
end;
My question is: why gmail gives me that error:
Username and Password not accepted. Learn more at
http://support.google.com/mail/bin/answer.py?answer=14257 lp8sm18275694wic.17 - gsmtp
I tried everything, whole bunch of options: SSL, TSL, SASL and still nothing. Somewhere I found that google demands some OAUTH2 SASL method wchich is to be done in Indy.
Of course on Delphi 6 and Indy 9 with proper eay dlls on port 465 with ssl works fine.
Anyone has some idea what to do with that?
O course I installed http://slproweb.com/products/Win32OpenSSL.html i anyone asked...
here is the code:
procedure send(Recipientemail, AccountName, Pass, EmailSMTP,EmailPortNo :string);
var
lTextPart: TIdText;
lImagePart: TIdAttachmentfile;
IdSMTP1: TIdSMTP;
IdMsg: TIdMessage;
SSLHandler:TIdSSLIOHandlerSocketOpenSSL;
IdUserPassProv1: TIdUserPassProvider;
IdSASLLogin1: TIdSASLLogin;
IdSASLCRAMMD5: TIdSASLCRAMMD5;
IdSASLCRAMSHA1: TIdSASLCRAMSHA1;
IdSASLPlain: TIdSASLPlain;
IdSASLLogin: TIdSASLLogin;
IdSASLSKey: TIdSASLSKey;
IdSASLOTP: TIdSASLOTP;
IdSASLAnonymous: TIdSASLAnonymous;
IdSASLExternal: TIdSASLExternal;
begin
IdSMTP1:=TIdSMTP.Create(nil);
IdMsg:=TIdMessage.Create(nil);
IdSMTP1.Host:=EmailSMTP;
IdSMTP1.Port:=EmailPortNo;
//IdSMTP1.Username:=trim(AccountName);//tried with or without
//IdSMTP1.Password:=trim(Pass);//tried with or without
TIdSSLContext.Create.Free;
SSLHandler:=TIdSSLIOHandlerSocketOpenSSL.Create(IdSMTP1);
SSLHandler.SSLOptions.Method := sslvSSLv3;
SSLHandler.SSLOptions.Mode := sslmClient;
IdSMTP1.IOHandler := SSLHandler;
if (IdSMTP1.port = 465) then
IdSMTP1.UseTLS := utUseImplicitTLS
else
IdSMTP1.UseTLS := utUseExplicitTLS;
IdSASLLogin1:=TIdSASLLogin.Create(IdSMTP1);
IdUserPassProv1:=TIdUserPassProvider.Create(IdSMTP1);
IdUserPassProv1.Password:=trim(EmailHasloKonta);
IdUserPassProv1.Username:=trim(EmailNazwaKonta);
IdSMTP1.AuthType:=satSASL;
IdSASLCRAMSHA1 := TIdSASLCRAMSHA1.Create(idSMTP1);
IdSASLCRAMSHA1.UserPassProvider := IdUserPassProv1;
IdSASLCRAMMD5 := TIdSASLCRAMMD5.Create(idSMTP1);
IdSASLCRAMMD5.UserPassProvider := IdUserPassProv1;
IdSASLSKey := TIdSASLSKey.Create(idSMTP1);
IdSASLSKey.UserPassProvider := IdUserPassProv1;
IdSASLOTP := TIdSASLOTP.Create(idSMTP1);
IdSASLOTP.UserPassProvider := IdUserPassProv1;
IdSASLAnonymous := TIdSASLAnonymous.Create(idSMTP1);
IdSASLExternal := TIdSASLExternal.Create(idSMTP1);
IdSASLLogin := TIdSASLLogin.Create(idSMTP1);
IdSASLLogin1.UserPassProvider:=IdUserPassProv1;
IdSASLPlain := TIdSASLPlain.Create(idSMTP1);
IdSASLPlain.UserPassProvider := IdUserPassProv1;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLCRAMSHA1;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLCRAMMD5;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLSKey;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLOTP;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLAnonymous;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLExternal;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLLogin1;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLPlain;
IdMsg.CharSet:=CmbEncod.Text;
IdMsg.From.Address:=EmailAdresNadawcy;
IdMsg.From.Name:=ToISO_8859_2(true, EmailNadawca);
IdMsg.Recipients.Add.Address:=email;
if EmailDoWiad<>'' then IdMsg.BccList.Add.Address:=EmailDoWiad;
IdMsg.ContentType:='multipart/relative';//; charset='+CmbEncod.Text;
IdMsg.Subject:=ifthen(TytulEmaila='',translate('Potwierdzenie rezerwacji'),TytulEmaila);
IdMsg.Body.Clear;
IdMsg.Body.Text:='';
lTextPart := TIdText.Create(IdMsg.MessageParts);
lTextPart.Body.text:='Some body text';
lTextPart.ContentType := 'text/plain';
try
IdSMTP1.Connect;
//IdSMTP1.Authenticate; //tried with or without
try
try
IdSMTP1.Send(IdMsg);
except
on e: exception do
MessageDlg('Sending error:'#13+
e.message,
mtinformation,[mbok],0);
end;
finally
IdSMTP1.Disconnect;
end;
finally
IdSMTP1.Disconnect;
IdUserPassProv1.free;
IdSASLLogin1.free;
IdSASLCRAMMD5.free;
IdSASLCRAMSHA1.free;
IdSASLPlain.free;
IdSASLLogin.free;
IdSASLSKey.free;
IdSASLOTP.free;
IdSASLAnonymous.free;
IdSASLExternal.free;
lTextPart.Free;
lImagePart.Free;
SSLHandler.free;
IdSMTP1.Free;
IdMsg.Free;
SSLHandler.Free;
end;
end;
Using the latest Indy version (10.6.1), I can successfully connect and authenticate TIdSMTP to Gmail using Indy's SASL components with both SSL (UseTLS=utUseImplicitTLS on port 465) and TLS (UseTLS=utUseExplicitTLS on port 587) using similar code to what you have shown. Despite popular belief, OAUTH2 is not required yet.
The fact that you are getting a human-readable authentication error means the SSL/TLS portion is working fine, so this is strictly a SASL issue.
If your Gmail account is using 2-step verification, make sure you have created an Application Password in your Gmail account settings, you cannot use your primary Gmail password. Read Gmail's documentation for more details:
Application-specific password required
Sign in using App Passwords
With that said, the only changes I would suggest you make to the code you have showed are:
setting the UseTLS property may change the Port property value, so you should set UseTLS first and then set the Port to the desired value afterwards:
if (EmailPortNo = 465) then
IdSMTP1.UseTLS := utUseImplicitTLS
else
IdSMTP1.UseTLS := utUseExplicitTLS;
IdSMTP1.Port := EmailPortNo;
you do not need to create and destroy a TIdSSLContext object, so get rid of that. The only reason to create a TIdSSLContext manually is so it can call the IdSSLOpenSSL.LoadOpenSSLLibrary() function, which is public so you can call it directly if needed (which you don't really need to in this situation).
multipart/relative is not a valid ContentType. Did you mean multipart/related instead? Your TIdMessage does not contain multiple parts so you should not be using multipart ContentType to begin with.
Most of your calls to Free() are redundant since you assigned the TIdSMTP as the Owner for everything except the TIdMessage. You don't need to free the SASL components manually, you can let TIdSMTP do that for you.
you are calling IdSMTP1.Disconnect() twice. You don't need that.
Here is the solution:
After all tries is seems to I have had the wrong version of two dlls libeay.dll and ssleay.dll.
I am using this simple code to send emails it works for most SMTP servers but for the Servers which using SMTP AUTH extension as defined in RFC 2554. it shows this error:
ERROR: valid RCPT command must precede DATA
here is the code :
SMTP.Host := 'host.com';
SMTP.Port := 25;
SMTP.Username:= 'user#host.com';
SMTP.Password:= 'pass';
MailMessages.From.Address:='address#address.com';
MailMessages.From.Name:= 'Ehsan';
MailMessages.Subject := 'Test';
MailMessages.Body.Text := 'the body is going to test';
MailMessages.ReceiptRecipient.Address := 'ehsan.hesam13#gmail.com';
try
try
SMTP.Connect;
SMTP.Authenticate;
SMTP.Send(MailMessages);
except on E:Exception do
StatusMemo.Lines.Insert(0, 'ERROR: ' + E.Message);
end;
finally
if SMTP.Connected then SMTP.Disconnect;
end;
end;
how can i solve this problem in XE2?
thankx
Make sure you are filling in the TIdMessage.Recipients, TIdMessage.CCList, or TIdMessage.BCCList properties. Those are the properties where TIdSMTP gets the addresses for its SMTP RCPT TO commands. You cannot send an email without specify the recipient(s) for it. You are only filling in the TIdMessage.ReceiptRecipient property, which is only meant for specifying the return address that recipients send read receipts to, if recipients support read recipients.
Also, you do not need to call Authenticate() manually. Send() calls it internally for you when needed.
Thank you all , I have filled the Recipients.EMailAddresses and it worked :D
here is the correct code :
SMTP.Host := 'host.com';
SMTP.Port := 25;
SMTP.Username:= 'user#host.com';
SMTP.Password:= 'pass';
MailMessages.From.Address:='address#address.com';
MailMessages.From.Name:= 'Ehsan';
MailMessages.Subject := 'Test';
MailMessages.Body.Text := 'the body is going to test';
MailMessages.Recipients.EMailAddresses:='ehsan.hesam13#gmail.com';
try
try
SMTP.Connect;
SMTP.Authenticate;
SMTP.Send(MailMessages);
except on E:Exception do
StatusMemo.Lines.Insert(0, 'ERROR: ' + E.Message);
end;
finally
if SMTP.Connected then SMTP.Disconnect;
end;
end;
Thank you again.
Hello I'm trying to send a message from delphi (indy) to a gmail address. When I go to Gmail I found my message in spam folder. If I try to send the same message with PHPMailer from web it works correctly. This is the code.
Thanks
//setup SMTP
SMTP.Port := 25;
SMTP.ConnectTimeout := 1000;
SMTP.Host := 'smtp.xxxxxx.it';
SMTP.Username := 'info#xxxxxx.it';
SMTP.Password := 'xxxxxx';
SMTP.Connect();
if SMTP.Authenticate then
begin
//setup mail message
MailMessage.From.Name := 'xxxxxx';
MailMessage.From.Address := 'info#xxxxxx.it';
MailMessage.Recipients.EMailAddresses := 'xxxxxx#gmail.com';
MailMessage.Subject := ledSubject.Text;
MailMessage.ContentType := 'multipart/mixed';
htmpart := TIdText.Create(MailMessage.MessageParts, nil);
htmpart.Body := Body.Lines;
htmpart.ContentType := 'text/html';
//send mail
try
try
SMTP.Send(MailMessage);
except on E:Exception do
StatusMemo.Lines.Insert(0, 'ERROR: ' + E.Message);
end;
finally
if SMTP.Connected then SMTP.Disconnect;
end;
end;
Probably I've found the problem. I look the message in 'original mode' I found in the header that google says 'MISSING ID' and I try to add this code:
MailMessage.MsgId := '1234567890#drinkmessage.it';
MailMessage.ExtraHeaders.Values['Message-Id'] := MailMessage.MsgId;
Now it seems to work fine.
thanks
Have you tried changing HeloName and MailAgent of IdSMTP? If you use the same domain with PHPMailer, my guess is GMail considers emails coming from your application as spam because it doesn't detect/like the application which is sending them.
Using Delphi XE2, Indy 10 that ships with it and OpenSSL dll's version 1.0.1c.
We are in the final stages of converting our Delphi 6 project to Delphi XE2.
We have solved every show stopper so far but I am running into one trying to connect to Gmail smtp server.
Our Delphi 6 app works fine using SSL v2.3 and SSL v3 and Indy 9 components connecting to port 465 per Google's own documentation. Google Support
Our Delphi XE2 app does not connect at all. The call to connect goes into the ether and nothing happens for some 7 minutes until I get bored waiting for the thing to timeout and kill it off. I actually traced the program execution all the way to the IdWinsock2 funcion here:
function Stub_select(nfds: Integer; readfds, writefds, exceptfds: PFDSet; timeout: PTimeVal): Integer; stdcall;
begin
#select := FixupStub(hWinSockDll, 'select'); {Do not Localize}
Result := select(nfds, readfds, writefds, exceptfds, timeout);//<-this line never returns and timeout is always nil
end;
I need to maintain the old SSL connectivity for existing users' configurations.
New users will be able to connect using TLS (to port 587) and that DOES work!?!?
I am at a loss as to why the non-TLS SSL options do not work and do not report any error and do not time out but just go off to Never-Never Land. Please help!
TJ
Here is the code:
SMTPClient.Host := trim(EditSMTPServer.Text);
SMTPClient.Port := EditSMTPServerPort.AsInteger;//<- value from custom edit box
SMTPClient.Username := trim(EditSMTPLogon.Text);
SMTPClient.Password := trim(EditSMTPPassword.Text);
SMTPClient.AuthType := satDefault;
if CheckBoxUseSSL.Checked then begin
SMTPClient.IOHandler := IdSSLIOHandlerSocket1;
IdSSLIOHandlerSocket1.ReadTimeout := 30000;//30 second timeout which does not appear to work
case ComboBoxSSLMode.ItemIndex of
0 : IdSSLIOHandlerSocket1.SSLOptions.Method := sslvSSLv2;
1 : IdSSLIOHandlerSocket1.SSLOptions.Method := sslvSSLv23;
2 : IdSSLIOHandlerSocket1.SSLOptions.Method := sslvSSLv3;
3 : begin
IdSSLIOHandlerSocket1.SSLOptions.Method := sslvTLsv1;
SMTPClient.UseTLS := utUseImplicitTLS;
end;
end;//case
IdSSLIOHandlerSocket2.SSLOptions.Method := IdSSLIOHandlerSocket1.SSLOptions.Method;
IdSSLIOHandlerSocket2.PassThrough := False;
end
else begin
SMTPClient.IOHandler := nil;
end;
try
SMTPClient.Connect;
if SMTPClient.Connected then begin
if SMTPClient.Authenticate then begin
... do some work ...
end;
end;
except
on e:Exception do begin
showmessage(e.message);
end;
end;
EDIT:
As usual, after I post a question I have stumbled across a workaround.
If I set the UsetTLS property to utUseImplicitTLS for all NON-SSL transactions and set it to utUseExplicitTLS for TLS transactions my connections appear to work in a timely manner.
Hopefully this helps someone out.
updated code:
if CheckBoxUseSSL.Checked then begin
SMTPClient.IOHandler := IdSSLIOHandlerSocket1;
SMTPClient.UseTLS := utUseImplicitTLS;
case ComboBoxSSLMode.ItemIndex of
0 : IdSSLIOHandlerSocket1.SSLOptions.Method := sslvSSLv2;
1 : IdSSLIOHandlerSocket1.SSLOptions.Method := sslvSSLv23;
2 : IdSSLIOHandlerSocket1.SSLOptions.Method := sslvSSLv3;
3 : begin
IdSSLIOHandlerSocket1.SSLOptions.Method := sslvTLsv1;
SMTPClient.UseTLS := utUseExplicitTLS;
end;
end;//case
IdSSLIOHandlerSocket2.SSLOptions.Method := IdSSLIOHandlerSocket1.SSLOptions.Method;
IdSSLIOHandlerSocket2.PassThrough := False;
end
else begin
SMTPClient.UseTLS := utNoTLSSupport;//reset TLS support flag
SMTPClient.IOHandler := nil;
end;
What you discovered is what you are supposed to be doing. SSL and TLS have different semantics, so you have to set UseTLS accordingly.
For SSL on port 465, the server expects your client to initiate an SSL handshake immediately upon connecting, before the server then sends an encrypted Greeting. UseTLS=utUseImplicitTLS does that, but UseTLS=utUseExplicitTLS does not. When UseTLS=utUseExplicitTLS, TIdSMTP will expect the server to send an unencrypted Greeting immediately, which would explain the hang in select() - the server is not sending any data!
For TLS on port 587, the server is expecting the client to connect initially unencrypted and then send an explicit STARTTLS command when it is ready to initiate encryption. UseTLS=utUseExplicitTLS does that, but UseTLS=utUseImplicitTLS does not.