Link to home
Start Free TrialLog in
Avatar of Zsolt
ZsoltFlag for Hungary

asked on

Delphi: Assign doesn't *just* copy the object properties?

Hello,

I have a Thread object for sending emails. My problem is that I create a local TidSmtp object and  copy the properties of a class var, but after Connect, the class var will open too:


private
  class var     fSmtp                         : TidSmtp;

Open in new window

The fSmtp class var is initialized during create correctly. 

Then in the Execute part:

var
  SmtpLocal            : TidSmtp; Begin   SmtpLocal := TidSmtp.Create(nil);
    SmtpLocal.IOHandler := fIdSSLIOHandlerSocketOpenSSL;
  SmtpLocal.Assign(fSMTP) ; //at this point SmtpLocal.Connected=False AND fSMTP.Connected=False ...     If SmtpLocal.Connected=False Then
      SmtpLocal.Connect; //After this, BOTH SmtpLocal.Connected=True AND fSMTP.Connected=True 

Open in new window


Can't thread object handle class vars correctly or is there some other problem?

Thank you!




Avatar of Ferruccio Accalai
Ferruccio Accalai
Flag of Italy image

Is fIdSSLIOHandlerSocketOpenSSL  a class declared in your Thread?
There's no code about how fSmtp is constructed, but I guess that fIdSSLIOHandlerSocketOpenSSL is the IOHandler wich fSmtp points to,
If so, even if you assign your object to fSTMP, you've already set the IOHandler property := fIdSSLIOHandlerSocketOpenSSL.
If you need a separate IOHandler assign it to fIdSSLIOHandlerSocketOpenSSL (to copy its propeties) instead of copy its references.
I mean something like
SmtpLocal := TidSmtp.Create(nil);
SmtpLocal.Assign(fSMTP);
SmtpLocal.IOHandler.Assign(fIdSSLIOHandlerSocketOpenSSL);
 

Open in new window

Avatar of Zsolt

ASKER

Hello Ferruccio,

Thank you for your asnwer.
Unfortunately "SmtpLocal.IOHandler.Assign(fIdSSLIOHandlerSocketOpenSSL); " gives me this error:

First chance exception at $774AB982. Exception class EConvertError with message 'Cannot assign a TIdSSLIOHandlerSocketOpenSSL to a TIdSSLIOHandlerSocketOpenSSL'.

However there might be another solution you might be able to help me with: I intended this whole thing to decrease the resources and speed up the email sending.

My original email sending code was something like this (using thread):

procedure TEK_EmailThread.Execute;
var
  Smtp                          : TidSmtp;
  IdSSLIOHandlerSocketOpenSSL   : TIdSSLIOHandlerSocketOpenSSL;
  MailMessage                   : TidMessage;
  
Begin  
  Smtp                := TIdSMTP.Create(nil);
  Smtp.Host           := fEmailInputRekord.SmtpHost;
  Smtp.Username       := fEmailInputRekord.SmtpUsername;
  Smtp.Password       := fEmailInputRekord.SmtpPassword;
  Smtp.Port           := fEmailInputRekord.SmtpPort;
  Smtp.ConnectTimeout := fEmailInputRekord.SmtpConnectionTimeOut;
...
  Try
    SMTP.Connect;
  Except on E:Exception do
    Begin
   ...
  End;

 ... //set the email subject, body etc.

    try
      SMTP.Send(MailMessage);
      MailMessage.Body.Clear;
      SMTP.Disconnect;
      SMTP.Free;

Open in new window

However when the user wants to send an email to - let's say - 500 of his clients from my software, my program creates 500 times the TIdSMTP and connects 500 times.

My first approach was to use only the

class var
    fSmtp                         : TidSmtp;

Open in new window

... so as I would initialize once (at first use) and in the next threads I will just send the emails using the already open fSmtp. But it didn't work at the second time, I don't know if threads can handle well class vars?
I mean using directly the class var fSmtp worked when sending the first email, but at the second, third etc.  it couldn't see the fSmtp properties (it seemed for the next threads that it is uninitialized).

After the code above didn't worked I tried the code I started this Question with: to create a local TidSmtp and assign the values.
But if there is a better approach I am open to it.

Thank you!











"However when the user wants to send an email to - let's say - 500 of his clients from my software, my program creates 500 times the TIdSMTP and connects 500 times. "
Do you mean the same email to multiple recipients?
In this case I'd use another approach.
Once you've created your thread and initialized your SMTP component, then add all email recipients addresses to IdMessage.Recipients.


Avatar of Zsolt

ASKER

"Do you mean the same email to multiple recipients?"
No, before each email the program changes some parts of the body and the subject e.g. changes the company name, recipient name, and the file attachment  is different.

Imagine like the program user sends emails to all of his customers about what they spent in his shop in the last month. So a bunch of emails, but with different context -> I need to generate an email for every customer, but these emails uses the same Smpt connection.
ASKER CERTIFIED SOLUTION
Avatar of Ferruccio Accalai
Ferruccio Accalai
Flag of Italy image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial