Reputation: 35
When i try to send an email with attachment using indy my program freezes and i don't know why. Here's the full code for the form i'm using for sending emails.
unit Dok_sutisana;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdMessage, IdBaseComponent, IdComponent, IdTCPConnection,
IdTCPClient, IdExplicitTLSClientServerBase, IdMessageClient, IdSMTPBase,
IdSMTP, StdCtrls, Buttons, ComCtrls, IdAttachmentFile;
type
TForm14 = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
Label1: TLabel;
Label2: TLabel;
BitBtn1: TBitBtn;
FontDialog1: TFontDialog;
RichEdit1: TRichEdit;
IdSMTP1: TIdSMTP;
IdMessage1: TIdMessage;
BitBtn2: TBitBtn;
procedure BitBtn2Click(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form14: TForm14;
implementation
uses Autentif, EDGA;
{$R *.dfm}
procedure TForm14.BitBtn1Click(Sender: TObject);
begin
if FontDialog1.Execute() then
RichEdit1.Font:=FontDialog1.Font;
end;
procedure TForm14.BitBtn2Click(Sender: TObject);
var s:string;
begin
form3.ADOTable1.Active:=true;
//setup SMTP
IdSMTP1.Host := form3.adotable1['smtp'];
IdSMTP1.Port := form3.adotable1['ports'];
IdSMTP1.Username:= '******@gmail.com';
IdSMTP1.Password:='******';
//setup mail message
IdMessage1.From.Address := form3.adotable1['e-pasts'];
IdMessage1.From.Name:= form3.adotable1['Vards']+' '+ form3.adotable1['Uzvards'];
IdMessage1.Recipients.EMailAddresses := edit1.Text;;
IdMessage1.Subject := edit2.Text;
IdMessage1.Body.Add(RichEdit1.Text + form3.ADOTable1['paraksts']);
s:= GetCurrentDir + form1.ADOTable1['Dok_adr'];
TIdAttachmentFile.Create(IdMessage1.MessageParts, s ) ;
//send mail
IdSMTP1.Connect() ;
IdSMTP1.Send(IdMessage1) ;
IdSMTP1.Disconnect;
IdMessage1.Free;
IdSMTP1.Free;
form3.ADOTable1.Active:=false;
Form14.Close;
end;
end.
I hope that whit this I can get some help for my problem.
Upvotes: 3
Views: 1338
Reputation: 82
I deleted the use of ADO from your code and used hard-coded values for my email accounts (removed for security reasons here - you can the placeholders replace with working accounts).
This code works - it sends an attachment.
I also:
Need to remove the previous attachment as well otherwise your second email ends up with the attachment from the first
IdSMTP1.Host := '******';
IdSMTP1.Port := 25;
IdSMTP1.Username:= '******@gmail.com';
IdSMTP1.Password:='******';
IdMessage1.From.Address := '******';
IdMessage1.From.Name:= '******';
IdMessage1.Recipients.EMailAddresses := '******';
IdMessage1.Subject := '******';
IdMessage1.Body.Clear; // Clear the email body
IdMessage1.Body.Add('******');
s:= GetCurrentDir + '\******';
IdMessage1.MessageParts.Clear;
TIdAttachmentFile.Create(IdMessage1.MessageParts, s ) ;
IdSMTP1.ConnectTimeout := 2400 ;
IdSMTP1.Connect();
try
IdSMTP1.Send(IdMessage1) ;
finally
IdSMTP1.Disconnect;
end;
As this simple example works, your problem could be:
When I changed ISPs, the old one did not work (access requires SMTPS) but when I swapped to use the email account provided by my broadband supplier, this did not require SMTPS but worked on plain SMTP as it was inside their network and therefore trusted
Upvotes: 0
Reputation: 596256
Indy uses blocking operations, and you are using Indy in the context of the main UI thread. So while TIdSMTP
is busy, your main thread is blocked from processing new messages, giving the appearance of an app freeze, until TIdSMTP
is finished.
To avoid the freezing, you can either:
(preferred solution) Move your TIdSMTP
code into a separate worker thread.
Drop a TIdAntiFreeze
component onto your Form. This will allow the main message queue to continue processing new messages while other Indy components are operating in the main thread.
For good measure, you should also set the TIdSMTP.ConnectTimeout
and TIdSMTP.ReadTimeout
properties so Connect()
and Send()
do not block for long periods of time. If a timeout occurs, an appropriate exception will be raised to abort the operation.
Upvotes: 3