I have developed an app for Android and iOS. I am using Delphi 10.2.3 Tokyo, with Indy 10.
I wrote a function for sending an email via Gmail with some help.
Although the function often works properly, sometimes it gets the error below when some participants log in Gmail with their own phones.
https://accounts.google.com/signIn/continue?sarp=1&scc=1sdf[...] Please log in via your web browser and then try again. Learn more at https://support.google.com/mail/answer/78754 y4-v6sm15938458pgy.18 - gsmtp
I have already seen Send e-mail using gmail and Indy, but I don't understand how I should use TIdSMTP.Password.
How should I revise my function to avoid this error?
The code is below.
type
TIdSMTPAccess = class(TIdSMTP)
end;
procedure MailSend;
var
IdSMTP: TIdSMTP;
Msg: TIdMessage;
begin
IdSMTP := TIdSMTP.Create(nil);
try
SSL := TIdSSLIOHandlerSocketOpenSSL.Create(IdSMTP);
IdSMTP.IOHandler := SSL;
IdSMTP.Host := 'smtp.gmail.com';
IdSMTP.Port := 587;
IdSMTP.Username := 'xxxx#gmail.com';
IdSMTP.Password := 'xxxx';
IdSMTP.UseTLS := utUseExplicitTLS;
TIdSMTPAccess(IdSMTP).IPVersion := Id_IPv6;
try
IdSMTP.Connect;
except
TIdSMTPAccess(IdSMTP).IPVersion := Id_IPv4;
try
IdSMTP.Connect;
except
// unable to connect!
Exit;
end;
end;
try
Msg := TIdMessage.Create(nil);
try
Msg.OnInitializeISO := IdMessage_InitializeISO;
Msg.ContentType := 'text/plain';
Msg.CharSet := 'UTF-8';
Msg.ContentTransferEncoding := 'BASE64'; // BASE64 (7bit)
//Msg.ContentTransferEncoding := '8bit'; // RAW(8bit)
Msg.From.Name := SsNoSt;
Msg.From.Address := 'xxxx#gmail.com';
Msg.Recipients.EMailAddresses := 'xxxx#gmail.com';
Msg.Subject := SsNoSt;
Msg.Body.Text := 'Unicode String (body)';
IdSMTP.Send(Msg);
finally
Msg.Free;
end;
finally
IdSMTP.Disconnect;
end;
finally
IdSMTP.Free;
end;
end;
Related
I tried to send mail using office365 smtp server but i am getting error "SSL Negotiation Failed". I have the latest openssl dll files. So the host in that case is smtp.office365.com.
I also tried a code sample from other post but with no success.
Can you help me please ?
procedure TForm7.Button3Click(Sender: TObject);
var
IdSMTPa: TIdSMTP;
IdMessage1: TIdMessage;
IdSSL: TIdSSLIOHandlerSocketOpenSSL;
begin
IdSMTPa := TIdSMTP.Create(nil);
try
IdSMTPa.Host := 'smtp.office365.com';
IdSMTPa.Port := 587;
IdSMTPa.Username := 'mymail#mydomain.gr';
IdSMTPa.Password := 'mypwd';
IdSMTPa.AuthType := satDefault;
// IO HANDLER Settings //
IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(IdSMTPa);
IdSSL.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
IdSSL.SSLOptions.Mode := sslmUnassigned;
IdSSL.SSLOptions.VerifyMode := [];
IdSSL.SSLOptions.VerifyDepth := 0;
IdSMTPa.IOHandler := IdSSL;
IdSMTPa.UseTLS := utUseExplicitTLS;
IdMessage1 := TIdMessage.Create(nil);
try
IdMessage1.From.Address := 'mymail#mydomain.gr';
IdMessage1.Recipients.EMailAddresses := 'user1#mydomain.gr';
IdMessage1.CCList.EMailAddresses := 'user1#mydomain.gr';
IdMessage1.Subject := 'Test Email Subject';
IdMessage1.Body.Add('Test Email Body');
IdMessage1.Priority := mpHigh;
try
IdSMTPa.Connect();
try
IdSMTPa.Send(IdMessage1);
ShowMessage('Email sent');
finally
IdSMTPa.Disconnect();
end;
except
on e: Exception do
begin
ShowMessage('ERROR : '+e.Message);
end;
end;
finally
IdMessage1.Free;
end;
finally
IdSMTPa.Free;
end;
end;
If I send a basic email via TidSMTP (ignore the try/finally blocks, this is just an example):
var
SMTP : TidSMTP;
MSG : TidMessage;
LHandler : TIdSSLIOHandlerSocketOpenSSL;
begin
SMTP := TIdSMTP.Create(nil);
Msg := TIdMessage.Create(nil);
LHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
Msg.Body.Text := 'Test Simple Email';
Msg.Subject := 'Test Simple Email Subject';
Msg.From.Address := 'test#domain.com';
MSG.ContentType := 'text/html';
Msg.Priority := mpHighest;
SMTP.Host := 'smtp.server.com';
SMTP.Username := 'test#domain.com';
SMTP.Port := 587;
SMTP.Password := 'testPassword';
SMTP.IOHandler := LHandler;
try
with Msg.Recipients.Add do
begin
Address := 'test#domain.com'
end;
try
SMTP.Connect;
SMTP.Send(Msg);
SMTP.Disconnect;
finally
Screen.Cursor := crDefault;
end;
finally
LHandler.Free;
Msg.Free;
SMTP.Free;
end;
And then call a DLL which makes an HTTPS request via TidHTTP:
var
myHTTP : TIdHTTP;
LHandler: TIdSSLIOHandlerSocketOpenSSL;
FJSON : String;
GetStr : String;
begin
GetStr := URLEncode('6421 E ROAD, GREELEY,CO,80634');
GetStr := 'https://maps.googleapis.com/maps/api/geocode/json?address=' + GetStr + '&key=' + 'someGoogleAPIKey';
myHTTP := TIdHTTP.Create(nil);
try
LHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
try
LHandler.SSLOptions.SSLVersions := [sslvTLSv1_2];
myHTTP.IOHandler := LHandler;
try
FJSON := myHTTP.Get(GetStr);
except
on E: Exception do
begin
raise
end;
end;
showmessage(FJSON);
finally
LHandler.Free;
end;
finally
myHTTP.Free;
end;
And then try the email a second time, I'm receiving the error "Error creating SSL context", specifically "error:140A90F1:SSL routines: SSL_CTX_new: unable to load ssl2 md5 routines"
If I change this slightly by feeding in the TidSMTP component into the TidSSLIOHandlerSocketOpenSSL Create method:
LHandler := TIdSSLIOHandlerSocketOpenSSL.Create(SMTP);
...
//SMTP.IOHandler := lHandler;
Then it works. But I can't use that. This is a completely stripped down version of the problem. In reality I'm using ReportBuilder (digital-metaphors) to send the email, and they don't allow one to send in the TidSMTP during the TidSSLIOHandlerSocketOpenSSL Create method.
This error does not happen when the HTTPS request is made within the same program as the SMTP request. Only when crossing into a DLL. This error does not happen if I do the HTTPS/DLL first and then SMTP. There is something happening during the first SMTP call that sets it up for the error down the road.
Should I take this over to Digital-Metaphors, or is there something going on during the HTTPS/DLL call that I could be doing better?
I am developing an email sending function in my iOS and Android apps.
It is a function to send an email via Gmail using OpenSSL.
I am using Delphi 10.2.3 Tokyo, with Indy 10.
I submitted my iOS app to iTunes Connect, but they rejected my app because this function does not work in IPv6.
They said
We discovered one or more bugs in your app when reviewed on iPad and iPhone running iOS 11.4.1 on Wi-Fi connected to an IPv6 network.
They also send me a screenshot of the error saying
An error occurred when resolving address smtp.gmail.com: (8)
How can I fix this error to work with IPv6 properly? My code is below:
Procedure MailSend;
Var
Connected: Boolean;
Begin
IdSMTP := TIdSMTP.Create(nil);
try
IdSMTP.Host := 'smtp.gmail.com';
IdSMTP.Port := 587;
IdSMTP.Username := 'xxxx#gmail.com'; // UserName
IdSMTP.Password := 'xxxx'; // Password
SSL := TIdSSLIOHandlerSocketOpenSSL.Create;
try
SSL.Host := IdSMTP.Host;
SSL.Port := IdSMTP.Port;
SSL.Destination := SSL.Host + ':' + IntToStr(SSL.Port);
IdSMTP.IOHandler := SSL;
IdSMTP.UseTLS := utUseExplicitTLS;
IdSMTP.Socket.IPVersion := Id_IPv6;
try
IdSMTP.Connect;
Connected := True;
except
Connected := False;
end;
If Connected = False then
Begin
IdSMTP.Socket.IPVersion := Id_IPv4;
IdSMTP.Connect;
End;
Msg := TIdMessage.Create(IdSMTP);
try
Msg.OnInitializeISO := IdMessage_InitializeISO;
Msg.ContentType := 'text/plain';
Msg.CharSet := 'UTF-8';
Msg.ContentTransferEncoding := 'BASE64'; // BASE64 (7bit)
//Msg.ContentTransferEncoding := '8bit'; // RAW(8bit)
Msg.From.Name := SsNoSt;
Msg.From.Address := 'xxxx#gmail.com';
Msg.Recipients.EMailAddresses := 'xxxx#gmail.com';
Msg.Subject := SsNoSt;
Msg.Body.Text := 'Unicode String (body)';
IdSMTP.Send(Msg);
finally
Msg.Free;
end;
IdSMTP.Disconnect;
finally
SSL.Free;
end;
finally
IdSMTP.Free;
End;
End;
I see a few problems with your SMTP code:
you need to set the IdSMTP.IPVersion property instead of the IdSMTP.Socket.IPVersion property. The default value of the IPVersion property is Id_IPv4 (bug - it is not respecting the ID_DEFAULT_IP_VERSION constant in the IdGlobal unit). Connect() overwrites the Socket.IPVersion property value with the IPVersion property value, so you are actually attempting to connect using Id_IPv4 twice, which will fail on an IPv6-only network (which Apple requires apps to support).
you are not catching any errors from the 2nd Connect(). That is likely the error that Apple is ultimately seeing.
you should not be setting the SSL.Host, SSL.Port, and SSL.Destination properties manually. Let Connect() handle that for you.
Try this instead:
// this accessor class is needed because TIdSMTP derives from TIdTCPClientCustom
// instead of TIdTCPClient. The IPVersion property is protected in
// TIdTCPClientCustom and not published by TIdSMTP or its ancestors.
//
// See https://github.com/IndySockets/Indy/issues/184 ...
//
type
TIdSMTPAccess = class(TIdSMTP)
end;
procedure MailSend;
var
IdSMTP: TIdSMTP;
Msg: TIdMessage;
begin
IdSMTP := TIdSMTP.Create(nil);
try
SSL := TIdSSLIOHandlerSocketOpenSSL.Create(IdSMTP);
IdSMTP.IOHandler := SSL;
IdSMTP.Host := 'smtp.gmail.com';
IdSMTP.Port := 587;
IdSMTP.Username := 'xxxx#gmail.com';
IdSMTP.Password := 'xxxx';
IdSMTP.UseTLS := utUseExplicitTLS;
TIdSMTPAccess(IdSMTP).IPVersion := Id_IPv6;
try
IdSMTP.Connect;
except
TIdSMTPAccess(IdSMTP).IPVersion := Id_IPv4;
try
IdSMTP.Connect;
except
// unable to connect!
Exit;
end;
end;
try
Msg := TIdMessage.Create(nil);
try
Msg.OnInitializeISO := IdMessage_InitializeISO;
Msg.ContentType := 'text/plain';
Msg.CharSet := 'UTF-8';
Msg.ContentTransferEncoding := 'BASE64'; // BASE64 (7bit)
//Msg.ContentTransferEncoding := '8bit'; // RAW(8bit)
Msg.From.Name := SsNoSt;
Msg.From.Address := 'xxxx#gmail.com';
Msg.Recipients.EMailAddresses := 'xxxx#gmail.com';
Msg.Subject := SsNoSt;
Msg.Body.Text := 'Unicode String (body)';
IdSMTP.Send(Msg);
finally
Msg.Free;
end;
finally
IdSMTP.Disconnect;
end;
finally
IdSMTP.Free;
end;
end;
Alternatively:
type
TIdSMTPAccess = class(TIdSMTP)
end;
procedure MailSend;
var
IdSMTP: TIdSMTP;
Msg: TIdMessage;
Connected: Boolean;
begin
IdSMTP := TIdSMTP.Create(nil);
try
SSL := TIdSSLIOHandlerSocketOpenSSL.Create(IdSMTP);
IdSMTP.IOHandler := SSL;
IdSMTP.Host := 'smtp.gmail.com';
IdSMTP.Port := 587;
IdSMTP.Username := 'xxxx#gmail.com';
IdSMTP.Password := 'xxxx';
IdSMTP.UseTLS := utUseExplicitTLS;
Connected := False;
if GStack.SupportsIPv6 then
begin
TIdSMTPAccess(IdSMTP).IPVersion := Id_IPv6;
try
IdSMTP.Connect;
Connected := True;
except
end;
end;
if (not Connected) and GStack.SupportsIPv4 then
begin
TIdSMTPAccess(IdSMTP).IPVersion := Id_IPv4;
try
IdSMTP.Connect;
Connected := True;
except
end;
end;
if not Connected then
begin
// unable to connect!
Exit;
end;
try
Msg := TIdMessage.Create(nil);
try
Msg.OnInitializeISO := IdMessage_InitializeISO;
Msg.ContentType := 'text/plain';
Msg.CharSet := 'UTF-8';
Msg.ContentTransferEncoding := 'BASE64'; // BASE64 (7bit)
//Msg.ContentTransferEncoding := '8bit'; // RAW(8bit)
Msg.From.Name := SsNoSt;
Msg.From.Address := 'xxxx#gmail.com';
Msg.Recipients.EMailAddresses := 'xxxx#gmail.com';
Msg.Subject := SsNoSt;
Msg.Body.Text := 'Unicode String (body)';
IdSMTP.Send(Msg);
finally
Msg.Free;
end;
finally
IdSMTP.Disconnect;
end;
finally
IdSMTP.Free;
end;
end;
I have to send an XML-File to a Website with a secure Connection. Delphi 2010, Indy 10.5.9. The Code used is as follows:
Params: TIdMultiPartFormDataStream;
ResponseStr: string;
begin
result := 0;
sRootCertFile := 'xxx\Digital.pem';
sCertFile := 'xxx\Digital.pem';
sKeyFile := 'xxx\Digital.pem';
with FAdminSetup.RDWSSLHandler do
begin
SSLOptions.VerifyMode := [];
SSLOptions.VerifyDepth := 0;
SSLOptions.RootCertFile := sRootCertFile;
SSLOptions.CertFile := sCertFile;
SSLOptions.KeyFile := sKeyFile;
end;
sURL := 'https://xxx/xxxservice';
begin
IdHttpVVO := TIdHttp.Create(nil);
try
// IdHttpVVO.Request.ContentType := 'multipart/form-data';
// IdHttpVVO.ProtocolVersion := pv1_1;
// IdHttpVVO.HTTPOptions := [hoKeepOrigProtocol,hoForceEncodeParams];
// IdHttpVVO.Request.Connection := 'Keep-Alive';
// IdHttpVVO.Request.CacheControl := 'no-cache';
// IdHttpVVO.Request.ContentLength := Length(sAnsiXML); // <-- new
IdHttpVVO.IOHandler := FAdminSetup.RDWSSLHandler;
Params := TIdMultiPartFormDataStream.Create;
try
with Params do
begin
AddFile('file', filename, GetMIMETypeFromFile(filename));
end;
resultStr := IdHttpVVO.Post(sURL, Params);
finally
Params.Free;
end;
ShowMessage(resultstr);
The result is always the same:
'HTTP/1.0 500 Error'
when doing the post part.
All the remarks have been tried and did not give any change. The Password for the connection is supplied as follows:
procedure TFAdminSetup.RDWSSLHandlerGetPasswordEx(ASender: TObject;
var VPassword: AnsiString; const AIsWrite: Boolean);
begin
VPassword := 'xxx';
end;
The Website is working, the certificates seem to be ok, as there is a small tool included written in C that works.
Where is my mistake? Thanks
IdMessage1.Clear;
IdSSLIOHandlerSocketOpenSSL1 := TIdSSLIOHandlersocketopenSSL.Create(nil);
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1;
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode := sslmUnassigned;
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyMode := [];
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyDepth := 0;
IdSSLIOHandlerSocketOpenSSL1.Host := 'smtp.gmail.com';
IdSSLIOHandlerSocketOpenSSL1.Port := 587;
IdSMTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL1;
IdSMTP1.UseTLS := utUseExplicitTLS;
IdMessage1.Body.Append('h');
IdMessage1.From.Name := '******';
IdMessage1.From.Address := '****';
IdMessage1.Recipients.EMailAddresses :='*****';
IdMessage1.Subject := 'POWIADOMIENIE';
IdSMTP1.UserName := '*******';
IdSMTP1.Password := '*******';
IdSMTP1.Host :='smtp.gmail.com';
IdSMTP1.Port := 587 ;
//IdSMTP1.AuthType := satDefault;
// IdSMTP1.Authenticate;
IdSMTP1.Connect;
IdSMTP1.Send(IdMessage1);
IdSMTP1.Disconnect;
//idSMTP1.Authenticate;
end;
Hello, trying to send email to gmail using INDY and Delphi XE7 . Unfortunately, I get the error
"SSL in not availaible on this server "
screen from Wireshark
Changing libeay32.dll and ssleay32.dll to the current Version solves the problem!