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 trying to send an email with a PDF attachment, stored in a BLOB field, using TIdSMTP. For this I am using a TIdAttachmentMemory, but the code as shown results in 'refused by spam filter';
Omitting IdMessage.ContentType := 'multipart/mixed' works but the attachment is not sent (or received?) - as expected.
Leaving this statement and creating the attachment from a file (as in the commented code) it all works fine (i.e. mail correctly received with attachment).
Clearly I am missing something. I am suspecting something in the direction of the attachment not being "closed off" correctly (i.e. left in an incomplete state) or perhaps the incorrect ContentType?
All suggestions welcome. Thanks!
procedure TfrmSendMail.btnSendClick(Sender: TObject);
var
ms: TMemoryStream;
Attachment: TIdAttachmentMemory;
// Attachment: TIdAttachmentFile;
begin
memStatus.Clear;
IdSSLIOHandlerSocketOpenSSL.Destination := teHost.Text + ':587';
IdSSLIOHandlerSocketOpenSSL.Host := teHost.Text;
// IdSSLIOHandlerSocketOpenSSL.MaxLineAction := maException;
IdSSLIOHandlerSocketOpenSSL.Port := 587;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.Method := sslvTLSv1_2;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.Mode := sslmUnassigned;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyMode := [];
IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyDepth := 0;
IdSMTP.Host := teHost.Text;
IdSMTP.Port := 587;
IdMessage.From.Address := teFrom.Text;
IdMessage.Recipients.EMailAddresses := teTo.Text;
IdMessage.Subject := teSubject.Text;
IdMessage.Body.Text := memBody.Text;
IdMessage.Body.Add('Timestamp: ' + FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()));
IdMessage.ContentType := 'multipart/mixed';
if not sqlPDFPDF_Incasso.IsNull then
begin
ms := TMemoryStream.Create;
try
try
TBlobField(sqlPDF.FieldByName('PDF_Incasso')).SaveToStream(ms);
ms.Position := 0;
Attachment := TIdAttachmentMemory.Create(IdMessage.MessageParts, ms);
Attachment.ContentType := 'application/pdf';
Attachment.FileName := 'Invoice.pdf';
except
on E: Exception do
messageDlg('Error creating attachment' + #13#10 + E.Message, mtError, [mbOK], 0);
end;
finally
ms.Free;
end;
end;
// if FileExists(beAttachment.Text) then
// Attachment := TIdAttachmentFile.Create(IdMessage.MessageParts, beAttachment.Text);
Screen.Cursor := crHourGlass;
try
try
IdSMTP.Connect;
IdSMTP.Send(IdMessage);
memStatus.Lines.Insert(0, 'Email sent - OK.');
except
on E: Exception do
memStatus.Lines.Insert(0, 'ERROR: ' + E.Message);
end;
finally
if assigned(Attachment) then
Attachment.Free;
if IdSMTP.Connected then
IdSMTP.Disconnect(true);
Screen.Cursor := crDefault;
end;
end;
You are not populating the TIdMessage correctly (see this blog article for details - your use-case would fall under the "HTML and non-related attachments and no plain-text" section, but replacing HTML with Plain-Text).
In a nutshell, if you include the attachment, setting the TIdMessage.ContentType to 'multipart/mixed' is fine, but you need to put the body text into a TIdText object in the TIdMessage.MessageParts instead of in the TIdMessage.Body. And if you don't include the attachment, using the TIdMessage.Body is fine, but you need to set the TIdMessage.ContentType to 'text/plain' instead.
Try this:
procedure TfrmSendMail.btnSendClick(Sender: TObject);
var
Text: TIdText;
Attachment: TIdAttachmentMemory;
Strm: TStream;
begin
memStatus.Clear;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.Method := sslvTLSv1_2;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.Mode := sslmClient;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyMode := [];
IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyDepth := 0;
IdSMTP.Host := teHost.Text;
IdSMTP.Port := 587;
try
IdMessage.Clear;
IdMessage.From.Address := teFrom.Text;
IdMessage.Recipients.EMailAddresses := teTo.Text;
IdMessage.Subject := teSubject.Text;
//if FileExists(beAttachment.Text) then
if not sqlPDFPDF_Incasso.IsNull then
begin
IdMessage.ContentType := 'multipart/mixed';
Text := TIdText.Create(IdMessage.MessageParts, nil);
Text.Body.Text := memBody.Text;
Text.Body.Add('Timestamp: ' + FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()));
Text.ContextType := 'text/plain';
//Attachment := TIdAttachmentFile.Create(IdMessage.MessageParts, beAttachment.Text);
Attachment := TIdAttachmentMemory.Create(IdMessage.MessageParts);
Attachment.ContentType := 'application/pdf';
Attachment.FileName := 'Invoice.pdf';
Strm := Attachment.PrepareTempStream;
try
TBlobField(sqlPDFPDF_Incasso).SaveToStream(Strm);
finally
Attachment.FinishTempStream;
end;
end else
begin
IdMessage.ContentType := 'text/plain';
IdMessage.Body.Text := memBody.Text;
IdMessage.Body.Add('Timestamp: ' + FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()));
end;
Screen.Cursor := crHourGlass;
try
IdSMTP.Connect;
try
IdSMTP.Send(IdMessage);
finally
IdSMTP.Disconnect;
end;
memStatus.Lines.Insert(0, 'Email sent - OK.');
finally
Screen.Cursor := crDefault;
end;
except
on E: Exception do
memStatus.Lines.Insert(0, 'ERROR: ' + E.Message);
end;
end;
Alternatively, Indy has a TIdMessageBuilderPlain class that can setup the TIdMessage properly for you (see this blog article for details - your use-case would fall under the "Plain-text and HTML and attachments: Non-related attachments only" section):
uses
..., IdMessageBuilder;
procedure TfrmSendMail.btnSendClick(Sender: TObject);
var
Strm: TStream;
Bldr: TIdMessageBuilderPlain;
begin
memStatus.Clear;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.Method := sslvTLSv1_2;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.Mode := sslmClient;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyMode := [];
IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyDepth := 0;
IdSMTP.Host := teHost.Text;
IdSMTP.Port := 587;
try
IdMessage.Clear;
IdMessage.From.Address := teFrom.Text;
IdMessage.Recipients.EMailAddresses := teTo.Text;
IdMessage.Subject := teSubject.Text;
Strm := nil;
try
Bldr := TIdMessageBuilderPlain.Create;
try
Bldr.PlainText.Text := memBody.Text;
Bldr.PlainText.Add('Timestamp: ' + FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()));
//if FileExists(beAttachment.Text) then
if not sqlPDFPDF_Incasso.IsNull then
begin
//Bldr.Attachments.Add(beAttachment.Text);
Strm := sqlPDFPDF_Incasso.DataSet.CreateBlobStream(sqlPDFPDF_Incasso, bmRead);
Bldr.Attachments.Add(Strm, 'application/pdf').WantedFileName := 'Invoice.pdf';
end;
Bldr.FillMessage(IdMessage);
finally
Bldr.Free;
end;
finally
Strm.Free;
end;
Screen.Cursor := crHourGlass;
try
IdSMTP.Connect;
try
IdSMTP.Send(IdMessage);
finally
IdSMTP.Disconnect;
end;
memStatus.Lines.Insert(0, 'Email sent - OK.');
finally
Screen.Cursor := crDefault;
end;
except
on E: Exception do
memStatus.Lines.Insert(0, 'ERROR: ' + E.Message);
end;
end;
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;
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