SMTP.host variable issue - delphi

Here is my Issue. I'm using Delphi 5 and Indy 9. I have no option to upgrade either at the moment. I am trying to send an email via gmail, and i hard code the string as 'smtp.google.com' it works just fine. however, if smtp.host is getting the host name from a variable it fails with error 11001, and i havent been able to figure out why. I'm new using indy so i'm probably missing something silly, but i don't understand why it could accept a string as the host, but not a variable holding the string. (It's got to be a variable because i need to pass the procedure different SMTP hosts based on the user signed in. Here is the code:
procedure TFormEmail.SendSimpleMail(ToEmail, MyAttachment: string);
var
Msg: TIdMessage;
DestAddr: TIdEmailAddressItem;
SMTP: TIdSMTP;
SSLHandler : TidSSLIOHandlerSocket;
Attachment: TIdAttachment;
SMTPHost1 :string;
begin
Msg := idMessage1;
Msg.From.Text := EmailName(My_User);
Msg.From.Address := EmailAddress(My_User);
msg.Subject := 'Test';//email subject
DestAddr := Msg.Recipients.Add;
DestAddr.Text := '';//receiver's name (optional)
DestAddr.Address := ToEmail;//where its going
Msg.Body.Add(edtEmailBody.text); //email body
SMTP := IdSMTP1;
SMTP.IOHandler := idSSLIOHandlerSocket1;
SMTPhost1 := SMTPHost(My_User);
SMTPhost1 := 'smtp.google.com';
//SMTP.Host := SMTPhost1; //<--FAILS
SMTP.Host := 'smtp.google.com'; //<--SUCCEEDS
SMTP.Port := SMTPPort(My_User);
SMTP.AuthenticationType := atLogin; //error here (2 error)
SMTP.Username := EmailAddress(My_User);
SMTP.Password := SMTPPassword(My_User);
If not empty(MyAttachment) then
Attachment := TIdAttachment.Create(Msg.MessageParts, MyAttachment);//loads Att
Try
SMTP.Connect;
except
SMTP.Connect;//refire if exception (issue with INDY)
end;
if useSSL(My_User) then
SMTP.SendCmd('STARTTLS');//load TLS
SMTP.Authenticate;
SMTP.Send(Msg);
SMTP.Disconnect;//disconnect from server
end;
I marked the one that fails and the one that succeeds, but i don't understand what i'm doing wrong. Any help would be appreciated

Seems you have more issues in one question, I can only help you with one.
I had the same issue with Connect, I simply called the Load method from IdSSLOpenSSLHeaders.
Try the following:
SMTP := IdSMTP1;
IdSSLOpenSSLHeaders.Load;
SMTP.IOHandler := idSSLIOHandlerSocket1;

Related

How do I solve [EIdSMTPReplyError] Authentication unsuccessful?

I'm trying to use SMTP with TLS and Office365. I'm able to successfully send an email using powershell and TLS but with the below example I'm currently stuck with error:
Project SMTP_SSL_Example.exe raised exception class EIdSMTPReplyError
with message 'Authentication unsuccessful
[JN2P275CA0026.ZAFP275.PROD.OUTLOOK.COM]'
The connection is successful but the authentication part in the code fails. I've previously been told that the response is coming from the server. If I get a successful mail using PowerShell how come this differs? Any ideas?
I'm using Indy 10.6.2.5366.
Update: I'm also getting the same kind of error with another component suit. I just don't understand why Powershell is allowing me to send the mail but I can't programmatically.
procedure TForm28.Method2Click(Sender: TObject);
var
idSMTP1: TIdSMTP;
idSASLLogin: TIdSASLLogin;
idUserPassProvider: TIdUserPassProvider;
begin
idSMTP1 := TIdSMTP.Create(nil);
try
idSMTP1.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(idSMTP1);
idSMTP1.UseTLS := utUseExplicitTLS;
TIdSSLIOHandlerSocketOpenSSL(idSMTP1.IOHandler).SSLOptions.Method := sslvTLSv1;
idSMTP1.Host := 'smtp.office365.com';
idSMTP1.Port := StrToInt(cbPort.Text);
idSASLLogin := TIdSASLLogin.Create(idSMTP1);
idUserPassProvider := TIdUserPassProvider.Create(idSASLLogin);
idSASLLogin.UserPassProvider := idUserPassProvider;
idUserPassProvider.Username := 'my username';
idUserPassProvider.Password := 'my passowrd';
idSMTP1.AuthType := satSASL;
idSMTP1.SASLMechanisms.Add.SASL := idSASLLogin;
try
idSMTP1.Connect;
try
idSMTP1.Authenticate;
SendEmail(idSMTP1);
finally
idSMTP1.Disconnect;
end;
ShowMessage('OK');
except
on E: Exception do
begin
ShowMessage(Format('Failed!'#13'[%s] %s', [E.ClassName, E.Message]));
raise;
end;
end;
finally
idSMTP1.Free;
end;
end;
procedure TForm28.Mehod1Click(Sender: TObject);
var
idSMTP1: TIdSMTP;
begin
idSMTP1 := TIdSMTP.Create(nil);
try
idSMTP1.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(idSMTP1);
idSMTP1.UseTLS := utUseExplicitTLS;
TIdSSLIOHandlerSocketOpenSSL(idSMTP1.IOHandler).SSLOptions.Method := sslvTLSv1;
idSMTP1.Host := 'smtp.office365.com';
idSMTP1.Port := StrToInt(cbPort.Text);
idSMTP1.AuthType := satDefault;
idSMTP1.Username := 'my username';
idSMTP1.Password := 'my password';
try
idSMTP1.Connect;
try
idSMTP1.Authenticate;
SendEmail(idSMTP1);
finally
idSMTP1.Disconnect;
end;
ShowMessage('OK');
except
on E: Exception do
begin
ShowMessage(Format('Failed!'#13'[%s] %s', [E.ClassName, E.Message]));
raise;
end;
end;
finally
idSMTP1.Free;
end;
end;
Office 365 will soon require TLS 1.2, but your code is forcing Indy to use TLS 1.0 instead. Office 365 officially does not support TLS 1.0 or 1.1 anymore, but it still accepts 1.0/1.1 sessions for the time being, but that will change in the coming months.
So, at the very least, you need to change this:
TIdSSLIOHandlerSocketOpenSSL(idSMTP1.IOHandler).SSLOptions.Method := sslvTLSv1;
To this:
TIdSSLIOHandlerSocketOpenSSL(idSMTP1.IOHandler).SSLOptions.Method := sslvTLSv1_2;
Or better, to this:
TIdSSLIOHandlerSocketOpenSSL(idSMTP1.IOHandler).SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
That being said, using TIdSASLLogin as the sole SASL mechanism is exactly the same as using TIdSMTP.AuthType=satDefault. They both send the same AUTH LOGIN command to the server. And that command is what is failing. But there is no way to know for sure exactly why that is happening. "Authentication unsuccessful" is too generic an error message, and there are many reasons why that error occurs in Office 365. Maybe you are using the wrong username/password. Maybe the IP address resolved from the hostname being sent by TIdSMTP in its EHLO command 1 is not whitelisted on the server. Who knows.
1: try setting the TIdSMTP.HeloName property to a FQDN for your client machine, which you can get from GetComputerNameEx().

How to set password connecting to a web service with client-authentication for KeyFile?

I have to write a program (Delphi XE5, Indy 10: TIdHTTP & TIdSSLIOHandlerSocketOpenSSL) which can connect to a web service with client authentication. With several days of working, finally it has become success. I can connect using the authentication, setting the TIdSSLIOHandlerSocketOpenSSL’s SSLOptions.CertFile and SSLOptions.KeyFile properties. It’s fine. (I've got a pfx file from my partner, I exported it to a certificate and a private key file with OpenSSL so I use these 2 files in the program.)
I have one TButton, TMemo and TIdHTTP component on the form.
Source code (Button's click event - the IdHTTP1.Request.ContentType := '.......' line is necessary just for the communication because of the server settings):
procedure TForm1.Button1Click(Sender: TObject);
var
URL: string;
XML: TStrings;
S: string;
Req: TStream;
SL: TStringList;
SSL1 : TIdSSLIOHandlerSocketOpenSSL;
begin
XML := TStringList.Create;
XML.Add('<soap:Envelope xmlns:ns="http://docs.oasis-open.org/ws-sx/ws-trust/200512" ' +
'xmlns:soap="http://www.w3.org/2003/05/soap-envelope">');
…
XML.Add(' <soap:Body>');
…
XML.Add(' </soap:Body>');
XML.Add('</soap:Envelope>');
URL := 'https://…………………….';
end
Req := TStringStream.Create(XML.Text, TEncoding.UTF8);
try
SSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
SSL1.SSLOptions.CertFile := 'd:\certificate.pem';
SSL1.SSLOptions.KeyFile := 'd:\private.pem';
SSL1.SSLOptions.Mode := sslmClient;
try
SSL1.SSLOptions.Method := sslvSSLv23;
IdHTTP1.IOHandler := SSL1;
IdHTTP1.Request.ContentType := 'application/soap+xml;charset=UTF-8;action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue"';
S := IdHTTP1.Post(URL, Req);
finally
SSl1.Free;
end;
finally
Req.Free;
end;
ResultMemo.Lines.Add(Format('Response Code: %d', [IdHTTP1.ResponseCode]));
ResultMemo.Lines.Add(Format('Response Text: %s', [IdHTTP1.ResponseText]));
SL := TStringList.Create;
try
SL.Text := S;
ResultMemo.Lines.AddStrings(SL);
finally
SL.Free;
end;
end;
The problem is: my partner said this case is not the best if the file I use is not password-protected. They told me how to create a password-protected (and encrypted) file for the KeyFile with OpenSSL. When I set this password-protected file to the SSLOptions.KeyFile I get the following error message: „Could not load key, check password. error:0906A068:PEM routines:PEM_do_header:bad password read.”
I tried to set the password in the idHTTP1.Request.Password property, but the result is the same.
Question: how and where do I have to set the password for the KeyFile if I have to use a password-protected keyfile? Because I have to publish the certification files, too, the best solution would be to set the password in the program and use the password-protected KeyFile, instead of using not the password-protected KeyFile.
Thanks a lot.
Regards,
Attila
Use the IdSSLIOHandlerSocketOpenSSL.OnGetPassword event and set it here.
procedure TForm1.IdSSLIOHandlerSocketOpenSSL1GetPassword(var Password: string);
begin
Password := 'thepassword';
end;

Send email using indy component delphi xe2 SSL negotiation faild

I tried with Indy component to send email in XE2, and it works fine on my laptop that I compiled my project on.
But if I take my exe project to another PC, it shows an error message
Connection closed gracefully
or, sometimes I get
SSL Negotiation failed
Actually I tried many times to solve my problem, but I can't.
This is my code - where is my mistake? I need a practical solution.
procedure Gmail(username, password, totarget, subject, body :string);
var
DATA : TIdMessage;
SMTP : TIdSMTP;
SSL : TIdSSLIOHandlerSocketOpenSSL;
result:Boolean;
begin
try
SMTP := TIdSMTP.Create(nil);
DATA := TIdMessage.Create(nil);
SSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
SSL.Destination := 'smtp.gmail.com:587';
SSL.Host := 'smtp.gmail.com';
// SSL.MaxLineAction.maException;
SSL.Port:= 587;
SSL.SSLOptions.Method := sslvTLSv1;
SSL.SSLOptions.Mode := sslmUnassigned;
SSL.SSLOptions.VerifyMode := [];
SSL.SSLOptions.VerifyDepth := 0;
DATA.From.Address := username;
DATA.Recipients.EMailAddresses := totarget;
DATA.Subject := subject;
DATA.Body.Text := body;
if FileExists('D:\Test1.txt') then
TIdAttachmentFile.Create(DATA.MessageParts, 'D:\Test1.txt');
SMTP.IOHandler := SSL;
SMTP.Host := 'smtp.live.com';
SMTP.Port := 587 ;
SMTP.Username := username;
SMTP.Password := password;
// SMTP.SASLMechanisms;
SMTP.UseTLS := utUseExplicitTLS;
try
try
SMTP.Connect;
SMTP.Send(DATA);
Result := True;
except
on E:Exception do
begin
ShowMessage('Cannot send E-Mail: ' + E.Message);
Result := False;
end;
end;
finally
if SMTP.Connected then SMTP.Disconnect;
end;
except
on E : Exception do
begin
ShowMessage('Error in the function SendEmailDelphi: ' + E.Message);
Result := False;
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Timer1.Enabled:= True;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
mail_username := 'email#gmail.com';
mail_password := 'pass';
mail_to := 'email#gmail.com';
mail_subject := 'Text email from Delphi project';
mail_body := 'this is a test email sent from Delphi project, do not reply';
try
begin
Gmail(mail_username, mail_password, mail_to , mail_subject, mail_body);
end;
finally
end;
end;
DO NOT set the SSL.Destination, SSL.Host, or SSL.Port properties manually! TIdTCPClient.Connect() handles that for you. Besides, don't you think it's odd that you are setting SSL.Destination/Host to smtp.gmail.com but are setting SMTP.Host to smtp.live.com instead? Gmail and Live are not the same service provider.
Also, SSL.SSLOptions.Mode should be set to sslmClient instead of sslmUnassigned. Not too important, TIdSSLIOHandlerSocketOpenSSL will simply flip it when it configures the connection. But you should do it anyway, since you know your code is acting as a client.
And lastly, try setting SMTP.UseTLS before setting SMTP.Port, as setting UseTLS may change the Port, so you want to make sure you are really connecting to the correct port you are expecting.
With that said, the SSL Negotiation failed error means the TLS handshake was started but failed part-way through the negotiation. Try assigning handlers to TIdSSLIOHandlerSocketOpenSSL's OnStatusInfo/Ex events to see how far the handshake is actually getting. And if you are using a relatively modern version of Indy 10, try looking at the raised exception's InnerException property, it might give you a clue as to what went wrong before the EIdTLSClientTLSHandShakeFailed exception was raised afterwards.

Sending mail with delphi (Connection closed Gracefully) [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Delphi + Indy: Connection closed gracefully
I want to send some E-mails with delphi, i had this little code :
procedure TForm1.Button1Click(Sender: TObject);
var i : integer;
begin
IdMsgSend := TIdMessage.Create(nil);
SSLHandler :=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
try
with IdMsgSend do
begin
ContentType := 'text/plain';
Body.Text := 'Test test text';
From.Text := 'USERNAME#gmail.com';
ReplyTo.EMailAddresses := 'Recipient#server.com';
Recipients.EMailAddresses := 'Recipient#server.com';
Subject := 'i just came to say hello';
end;
SMTP := TIdSMTP.Create(nil);
try
SMTP.Username := 'USERNAME#gmail.com';
SMTP.Password := 'PASSWODD';
SMTP.Host := 'smtp.gmail.com';
SMTP.Port := 465;
SMTP.IOHandler := SSLHandler;
SSLHandler.SSLOptions.Method := sslvSSLv3;
SMTP.UseTLS := utUseExplicitTLS;
SMTP.Connect;
try
IdMsgSend.Body.Text := 'The body';
IdMsgSend.Subject := 'The subject';
SMTP.Send(IdMsgSend);
finally
SMTP.Disconnect;
end;
finally
FreeAndNil(SMTP);
end;
finally
FreeAndNil(IdMsgSend);
end;
end;
It used to work just fine! now, everytime i try to send an email i get this error at the SMTP.Send(IdMsgSend) :
Connection closed Gracefully
I've read that it might be from the antivirus or firewall, so i disabled them both, but still same problem?
What is wrong here? did gmail changed its SMTP options or something like that?
According to this article, it's an exception that's not correctly handled by Delphi. Try to do the shown modification on your Debugger Options and the problem will be solved.

Delphi Indy 10 Smtp Error "Unable to authenticate at present"

I am using this piece of code to mail a test message from delphi indy.
I have a TidSMTP,TIdMessage and IdSSLIOHandlerSocketOpenSSL;
In the belowe code if i set it up to use gmail with ssl it works fine, but as soon as i replace my the server details with my cpanel mail server detials it does not work error:
" unable to authenticate at present".
I used same details I would use to setup my account in outlook 2007. Here is the code
IdSSLIOHandlerSocketOpenSSL details.
method := sslvsslv3
mode := sslmUnassigned
//rest default values
procedure Tfrmnotification.btnSendClick(Sender: TObject);
var
IdMsg : TIdMessage;
begin
begin
IdMsg := TIdMessage.Create(nil);
try
with TIdSMTP.Create(nil) do
try
// UserName := 'something#gmail.com';
// Password := 'pass';
// Host := 'smtp.gmail.com';
// IOHandler := IdSSLIOHandlerSocketOpenSSL;
// Port := 587;
UserName := 'something#sasra.co.za';
Password := 'password';
Host := 'outgoing server detials';// same as outlooks
IOHandler := IdSSLIOHandlerSocketOpenSSL;
Port := 465;// this is correct port
UseTLS:= utUseExplicitTLS;
IdMsg.Body.Add('test');
IdMsg.Recipients.emailAddresses := 'something#gmail.com';
IdMsg.Subject := 'test';
IdMsg.From.Address := 'something#sasra.co.za';
IdMsg.From.Name := 'john';
Connect;
Send(IdMsg);
Disconnect;
finally
Free;
end;
finally
IdMsg.free;
end;
showmessage('done');
end;
Any help would be appricated.
Port 465 is used for SMTP over implicit SSL. You have set UseTLS to utUseExplicitTLS. The correct value should (most likely) be utUseImplicitTLS.

Resources