I am writing a program for Android using Delphi to send an email with data. As is, my app is having connectivity issues.
I have
set the host to smtp.gmail.com,
put in my username and password for my gmail account,
put valid information in for the address and body fields of a TIdMessage,
made and added an attachment file,
set the SSL Options for a TIdSSLIOHandlerSocketOpenSSL according to the online examples, and
added all of the SASL Mechanisms Indy offers.
I am using port 587 and have connected to TLS explicitly.
type
TForm1 = class(TForm)
SendBtn: TButton;
IdSMTP1: TIdSMTP;
IdMessage1: TIdMessage;
IdSASLAnonymous1: TIdSASLAnonymous;
IdSASLCRAMMD51: TIdSASLCRAMMD5;
IdSASLCRAMSHA11: TIdSASLCRAMSHA1;
IdSASLDigest1: TIdSASLDigest;
IdSASLExternal1: TIdSASLExternal;
IdSASLLogin1: TIdSASLLogin;
IdSASLOTP1: TIdSASLOTP;
IdSASLOTP2: TIdSASLOTP;
IdSASLPlain1: TIdSASLPlain;
IdSASLSKey1: TIdSASLSKey;
IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;
procedure SendBtnClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Attachment : TIdAttachmentFile;
implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
begin
IdSMTP1.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(idSMTP1);
IdSMTP1.UseTLS := utUseExplicitTLS;
IdSMTP1.AuthType := satSASL;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLCRAMSHA11;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLAnonymous1;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLCRAMMD51;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLDigest1;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLExternal1;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLLogin1;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLOTP1;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLOTP2;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLPlain1;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLSKey1;
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1;
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode := sslmUnassigned;
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyMode := [];
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyDepth := 0;
end;
procedure TForm1.SendBtnClick(Sender: TObject);
begin
if IdSMTP1.Connected=True then IdSMTP1.Disconnect;
IdMessage1.From.Address := '[email protected]';
IdMessage1.Recipients.EMailAddresses := '[email protected]';
IdMessage1.BccList.Add.Address := '';
IdMessage1.CCList.Add.Address := '';
IdMessage1.Priority := mpHigh;
IdMessage1.Sender.Address := '[email protected]';
IdMessage1.Subject := 'Test Data'; //Add Date/time
IdMessage1.Body.Add('Hello!');
Attachment := TIdAttachmentFile.Create(IdMessage1.MessageParts, (GethomePath+'/Test.txt'));
IdSMTP1.Connect;
IdSMTP1.Authenticate;
IdSMTP1.Send(IdMessage1);
IdSMTP1.Disconnect;
end;
Fails at:
IdSMTP1.Connect;
Is there a know problem with connecting to Android in this manner?
On this line:
IdSMTP1.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(idSMTP1);
You are creating and assigning a new default-initialized SSLIOHandler
, instead of using your existing SSLIOHandler
that is on the Form.
The line should be this instead:
IdSMTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL1;
In fact, everything you are doing in FormCreate()
can (and should) be done in the Form Designer at design-time instead. You don't need to do it in code.
Also, I do not see a TIdUserPassProvider
on your Form. Most of the SASL components you are using require one for their username/password. The TIdSMTP.UserName
and TIdSMTP.Password
properties are only used when AuthType
is satDefault
, not satSASL
.
Other than that, I would suggest some additional changes in SendBtnClick()
:
You should call IdMessage1.Clear()
so you don't carry over existing data from previous sends. You are appending new values to IdMessage1.BccList
, IdMessage1.CCList
, IdMessage1.Body
, and IdMessage1.MessageParts
without clearing out the old values first.
You do not need to call Authenticate()
, Send()
does that internally for you.
Send()
should be in a try/finally
or try/except
block so you can call Disconnect()
even if Send()
fails.
you are not configuring TIdMessage
correctly for mixing text and attachments together. You should add a TIdText
to the MessageParts
instead of using TIdMessage.Body
(however, if TIdMessage.ConvertPreamble
is true, it will convert TIdMessage.Body
into a TIdText
for you if there are any attachments present). But either way, you need to set the TIdMessage.ContentType
property to 'multipart/mixed'
so the receiver knows there are multiple pieces.
Try this instead:
type
TForm1 = class(TForm)
SendBtn: TButton;
IdSMTP1: TIdSMTP;
IdMessage1: TIdMessage;
IdSASLAnonymous1: TIdSASLAnonymous;
IdSASLCRAMMD51: TIdSASLCRAMMD5;
IdSASLCRAMSHA11: TIdSASLCRAMSHA1;
IdSASLDigest1: TIdSASLDigest;
IdSASLExternal1: TIdSASLExternal;
IdSASLLogin1: TIdSASLLogin;
IdSASLOTP1: TIdSASLOTP;
IdSASLOTP2: TIdSASLOTP;
IdSASLPlain1: TIdSASLPlain;
IdSASLSKey1: TIdSASLSKey;
IdUserPassProvider1: TIdUserPassProvider;
IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;
procedure SendBtnClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
begin
// all of this code can be handled at design-time instead!
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1;
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode := sslmUnassigned;
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyMode := [];
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyDepth := 0;
IdSMTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL1;
IdSMTP1.UseTLS := utUseExplicitTLS;
IdSMTP1.AuthType := satSASL;
IdSASLCRAMSHA11.UserPassProvider := IdUserPassProvider1;
IdSASLCRAMMD51.UserPassProvider := IdUserPassProvider1;
IdSASLDigest1.UserPassProvider := IdUserPassProvider1;
IdSASLLogin1.UserPassProvider := IdUserPassProvider1;
IdSASLOTP1.UserPassProvider := IdUserPassProvider1;
IdSASLOTP2.UserPassProvider := IdUserPassProvider1;
IdSASLPlain1.UserPassProvider := IdUserPassProvider1;
IdSASLSKey1.UserPassProvider := IdUserPassProvider1;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLCRAMSHA11;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLAnonymous1;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLCRAMMD51;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLDigest1;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLExternal1;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLLogin1;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLOTP1;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLOTP2;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLPlain1;
IdSMTP1.SASLMechanisms.Add.SASL := IdSASLSKey1;
// end design-time capable hookups
IdSMTP1.Host := ...;
IdSMTP1.Port := ...;
IdUserPassProvider1.UserName := ...;
IdUserPassProvider1.Password := ...;
end;
procedure TForm1.SendBtnClick(Sender: TObject);
var
Text: TIdText;
Attachment : TIdAttachmentFile;
begin
if IdSMTP1.Connected then IdSMTP1.Disconnect;
IdMessage1.Clear;
IdMessage1.From.Address := '[email protected]';
IdMessage1.Recipients.EMailAddresses := '[email protected]';
IdMessage1.Priority := mpHigh;
IdMessage1.Sender.Address := '[email protected]';
IdMessage1.Subject := 'Test Data'; //Add Date/time
//IdMessage1.Body.Add('Hello!');
Text := TIdText.Create(IdMessage1.MessageParts);
Text.ContentType := 'text/plain';
Text.Body.Add('Hello!');
Attachment := TIdAttachmentFile.Create(IdMessage1.MessageParts, (GethomePath+'/Test.txt'));
IdMessage1.ContextType := 'multipart/mixed';
IdSMTP1.Connect;
try
IdSMTP1.Send(IdMessage1);
finally
IdSMTP1.Disconnect;
end;
end;