Sending email using Delphi is not difficult, you just need to know the carious bits and pieces that go together to make it happen. Over the years Indy has changed its classes and methods so your version of Indy might function slightly different to mine, Indy 10.5.5, its just the one that I have to hand right now. I'm also using Rad Studio 2010. To send email using GMail and Indy you'll need to download the Open SSL libraries. This is because GMail sensibly requires a secure connection while sending, and also receiving email.
You can download the Open SSL libraries here: http://www.openssl.org/related/binaries.html (32-bit builds only at time of writing). You need to place 2 of the files contained in the download (libeay32.dll, and ssleay32.dll) into your system's path or just place them into the same directory as the executable you are building/running. Now for the Delphi part.
I create the Indy components dynamically rather than using ones dropped on the Form during design time because its generally more memory efficient for normal use.
This code is fairly specific to Gmail because passing anything other than utNoTLSSupport as the IdSmtp UseSSL property will then set the IdSSLIOHandlerSocketOpenSSL.SSLOptions.Method to sslvTLSv1. So mightn't work with another SSL only email service. Easy to change though.
These are the namespaces you need to add to your units uses section:
Add this method declaration to the Private section of the unit
The method itself. Ive commented out the lines where the TIdSMTP and TIdSSLIOHandlerSocketOpenSSL events are assigned. If you want to include these events and trace through the network connection, handshake, encoding, sending and disconnection stages of the SMTP session, then uncomment these lines and include the events at the bottom of this article.
Here's the code to call the send mail method (in an auto generated button click event)
If you opted to trace through the network events, then uncomment the commented lines in the method above and add these declarations just before the Private declaration of your unit.
...and add these procedures to your units implementation (As well as dropping a TMemo onto your Form and naming it 'Memo1')
You can download the Open SSL libraries here: http://www.openssl.org/related/binaries.html (32-bit builds only at time of writing). You need to place 2 of the files contained in the download (libeay32.dll, and ssleay32.dll) into your system's path or just place them into the same directory as the executable you are building/running. Now for the Delphi part.
I create the Indy components dynamically rather than using ones dropped on the Form during design time because its generally more memory efficient for normal use.
This code is fairly specific to Gmail because passing anything other than utNoTLSSupport as the IdSmtp UseSSL property will then set the IdSSLIOHandlerSocketOpenSSL.SSLOptions.Method to sslvTLSv1. So mightn't work with another SSL only email service. Easy to change though.
These are the namespaces you need to add to your units uses section:
uses IdIOHandler, IdIOHandlerSocket,
IdIOHandlerStack, IdSSL, IdSSLOpenSSL, IdBaseComponent, IdComponent,
IdTCPConnection, IdTCPClient, IdExplicitTLSClientServerBase,
IdSMTPBase, IdSMTP, IdMessage, IdAttachment,IdAttachmentFile;
Add this method declaration to the Private section of the unit
function SendEmail(sendTo: string;
subject: string;
body: string;
attachFiles: TStringList;
smtpHost: string;
smtpPort: Integer;
smtpUser: string;
smtpPass: string;
tls: TIdUseTLS): boolean;
The method itself. Ive commented out the lines where the TIdSMTP and TIdSSLIOHandlerSocketOpenSSL events are assigned. If you want to include these events and trace through the network connection, handshake, encoding, sending and disconnection stages of the SMTP session, then uncomment these lines and include the events at the bottom of this article.
function TForm1.SendEmail(sendTo: string;
subject: string;
body: string;
attachFiles: TStringList;
smtpHost: string;
smtpPort: Integer;
smtpUser: string;
smtpPass: string;
tls: TIdUseTLS): boolean;
var
smtp: TIdSmtp;
ssl: TIdSSLIOHandlerSocketOpenSSL;
msg: TIdMessage;
i: Integer;
begin
smtp:=TIdSmtp.Create(nil);
ssl:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
msg:=TIdMessage.Create(nil);
try
try
smtp.Host:=smtpHost;
smtp.Port:=smtpPort;
smtp.Username:=smtpUser;
smtp.Password:=smtpPass;
//smtp.OnConnected :=IdSMTP1Connected;
//smtp.OnDisconnected :=IdSMTP1Disconnected;
//smtp.OnFailedRecipient :=IdSMTP1FailedRecipient;
//smtp.OnStatus :=IdSMTP1Status;
//smtp.OnTLSNotAvailable :=IdSMTP1TLSNotAvailable;
//smtp.OnWork :=IdSMTP1Work;
if not (tls=utNoTLSSupport) then begin
ssl.Destination:=smtpHost + ':' + IntToStr(smtpPort);
ssl.Host:=smtpHost;
ssl.Port:=smtpPort;
ssl.SSLOptions.Method:=sslvTLSv1;
//ssl.OnStatusInfo:=IdSSLIOHandlerSocketOpenSSL1StatusInfo;
//ssl.OnGetPassword:=IdSSLIOHandlerSocketOpenSSL1GetPassword;
//ssl.OnStatus:=IdSSLIOHandlerSocketOpenSSL1Status;
smtp.IOHandler:=ssl;
smtp.UseTLS:=tls;
end;
msg.Recipients.EMailAddresses := sendTo;
msg.Subject:=subject;
msg.Body.Text:=body;
if(Assigned(attachFiles)) then begin
for i := 0 to attachFiles.Count - 1 do begin
if FileExists(attachFiles[i]) then
TIdAttachmentFile.Create(msg.MessageParts, attachFiles[i]);
end;
end;
smtp.Connect;
smtp.Send(msg);
smtp.Disconnect;
result:=true;
finally
msg.Free;
ssl.Free;
smtp.Free;
end;
except
result:=false;
end;
end;
NOTE: Do not forget about SMTP.HeloName if exists!
Here's the code to call the send mail method (in an auto generated button click event)
procedure TForm1.Button1Click(Sender: TObject);
var
attachmentFiles: TStringList;
begin
attachmentFiles:=TStringList.Create;
try
attachmentFiles.Add('c:\file1.txt');
attachmentFiles.Add('c:\file2.jpg');
try
SendEmail( 'mybuddy@example.com',
'This is the subject',
'This is the body of the email....',
attachmentFiles,
'smtp.gmail.com',
587,
'myusername@gmail.com',
'mypassword', utUseExplicitTLS);
except
on E : Exception do
begin
ShowMessage('EXCEPTION: message=' + E.Message);
end;
end;
finally
attachmentFiles.Free;
end;
end;
If you opted to trace through the network events, then uncomment the commented lines in the method above and add these declarations just before the Private declaration of your unit.
procedure IdSMTP1Connected(Sender: TObject);
procedure IdSMTP1Disconnected(Sender: TObject);
procedure IdSMTP1FailedRecipient(Sender: TObject; const AAddress, ACode,
AText: string; var VContinue: Boolean);
procedure IdSMTP1Status(ASender: TObject; const AStatus: TIdStatus;
const AStatusText: string);
procedure IdSMTP1Work(ASender: TObject; AWorkMode: TWorkMode;
AWorkCount: Int64);
procedure IdSMTP1TLSNotAvailable(Asender: TObject; var VContinue: Boolean);
procedure IdSSLIOHandlerSocketOpenSSL1GetPassword(var Password: AnsiString);
procedure IdSSLIOHandlerSocketOpenSSL1Status(ASender: TObject;
const AStatus: TIdStatus; const AStatusText: string);
procedure IdSSLIOHandlerSocketOpenSSL1StatusInfo(const AMsg: string);
...and add these procedures to your units implementation (As well as dropping a TMemo onto your Form and naming it 'Memo1')
procedure TForm1.IdSMTP1Connected(Sender: TObject);
begin
self.Memo1.Lines.Add('IdSMTP1Connected');
end;
procedure TForm1.IdSMTP1Disconnected(Sender: TObject);
begin
self.Memo1.Lines.Add('IdSMTP1Disconnected');
end;
procedure TForm1.IdSMTP1FailedRecipient(Sender: TObject; const AAddress, ACode,
AText: string; var VContinue: Boolean);
begin
self.Memo1.Lines.Add('IdSMTP1FailedRecipient AAddress:=' + AAddress + ' ACode=' + ACode + ' AText='+AText);
VContinue:=true;
end;
procedure TForm1.IdSMTP1Status(ASender: TObject; const AStatus: TIdStatus;
const AStatusText: string);
begin
self.Memo1.Lines.Add('IdSMTP1Status AStatusText:=' + AStatusText);
end;
procedure TForm1.IdSMTP1TLSNotAvailable(Asender: TObject;
var VContinue: Boolean);
begin
self.Memo1.Lines.Add('IdSMTP1TLSNotAvailable: not continuing');
VContinue:=false;
end;
procedure TForm1.IdSMTP1Work(ASender: TObject; AWorkMode: TWorkMode;
AWorkCount: Int64);
begin
self.Memo1.Lines.Add('IdSMTP1Work AWorkCount:=' + IntToStr(AWorkCount));
end;
procedure TForm1.IdSSLIOHandlerSocketOpenSSL1GetPassword(
var Password: AnsiString);
begin
self.Memo1.Lines.Add('IdSSLIOHandlerSocketOpenSSL1GetPassword Password:=' + Password);
end;
procedure TForm1.IdSSLIOHandlerSocketOpenSSL1Status(ASender: TObject;
const AStatus: TIdStatus; const AStatusText: string);
begin
self.Memo1.Lines.Add('IdSSLIOHandlerSocketOpenSSL1Status AStatusText:=' + AStatusText);
end;
procedure TForm1.IdSSLIOHandlerSocketOpenSSL1StatusInfo(const AMsg: string);
begin
self.Memo1.Lines.Add('IdSSLIOHandlerSocketOpenSSL1StatusInfo AMsg:=' + AMsg);
end;
procedure TMain.SendEmailIndy(
const SMTPServer: string;
const FromName, FromAddress: string;
const ToAddresses: string; //comma separated list of e-mail addresses
const CCAddresses: string; //comma separated list of e-mail addresses
const BCCAddresses: string; //comma separated list of e-mail addresses
const Subject: string;
const EmailBody: string;
const IsBodyHtml: Boolean);
var
smtp: TIdSMTP; // IdSmtp.pas
msg: TidMessage; // IdMessage.pas
builder: TIdMessageBuilderHtml; //IdMessageBuilder.pas
begin
msg := TidMessage.Create(nil);
try
builder := TIdMessageBuilderHtml.Create;
try
if IsBodyHtml then
begin
builder.Html.Text := EmailBody;
builder.HtmlCharSet := 'utf-8';
builder.HtmlContentTransfer := 'quoted-printable';
end else
begin
builder.PlainText.Text := EmailBody;
builder.PlainTextCharSet := 'utf-8';
builder.PlainTextContentTransfer := 'quoted-printable';
end;
if Realization.AttachmentD.FileName <> '' then
begin
builder.Attachments.Add(Realization.AttachmentD.FileName);
ShowMessage('Sending: ' + Realization.AttachmentD.FileName);
end;
builder.FillMessage(msg);
finally
builder.Free;
end;
msg.From.Name := FromName;
msg.From.Address := FromAddress;
msg.Subject := Subject;
msg.Recipients.EmailAddresses := ToAddresses;
msg.CCList.EmailAddresses := CCAddresses;
msg.BccList.EmailAddresses := BCCAddresses;
smtp := TIdSMTP.Create(nil);
try
smtp.Host := SMTPServer; // IP Address of SMTP server
Smtp.UseTLS := utNoTLSSupport;
smtp.Port := 587; //The default already is port 25 (the SMTP port)
smtp.Username := _GlobalData.EMail;
smtp.Password := _GlobalData.Password;
smtp.AuthType := satDefault;
smtp.Connect;
try
smtp.Send(msg);
finally
smtp.Disconnect;
end;
finally
smtp.Free;
end;
finally
msg.Free;
end;
ShowMessage('Wiadomość wysłana.');
Realization.AttachmentD.FileName := '';
end;
Немає коментарів:
Дописати коментар