Arno,

I think you addressed the problem correctly ;)  All subsequent Connect() calls 
(except the first one) are located within the OnRequestDone event procedure, in 
case of RqType=smtpQuit. I now see this must be wrong.

For a safe reconnect, should the message below be posted from OnRequestDone or 
from OnSessionClose? I guess it's the latter because it would be triggered 
after RqType=smtpQuit, right? Does calling Abort() also call OnSessionClose?

Michael

> -----Original Message-----
> From: [EMAIL PROTECTED] 
> [mailto:[EMAIL PROTECTED]
> Behalf Of Arno Garrels
> Sent: Wednesday, January 17, 2007 9:24 AM
> To: ICS support mailing
> Subject: Re: [twsocket] Still problems while sending SMTP
> 
> 
> In order to reconnect safely you need to get out of your loop
> after the session has been closed AND after OnRequestDone 
> has been triggered RqType smtpQuit as well. You must assign event
> OnSessionClose to always get notified about connection close,
> this can happen before as well as after OnRequestDone triggered
> RqType smtpQuit, I'm not sure if you do something like that. 
> 
> In order to get out of your loop just post a custom message,
> something like: 
> 
> PostMessage(Form1.Handle, WM_MAILSENT, Integer(Something), 
> Integer(Something));
> 
> The message handler is declared like:
> 
> const
>   WM_MAILSENT = WM_USER + 1;
> ..
> protected
>   procedure WmMailSent(var Msg: TMessage); message WM_MAILSENT;
> ..   
> 
> procedure TForm1.WmMailSent(var Msg: TMessage);
> begin
>   Display(IntToStr(Msg.WParam) + ' ' + IntToStr(Msg.LParam); 
>   ..  
>   In the message handler you can connect safely again.
>   SmtpCli.Connect;
> end;
> 
> 
> ---
> Arno Garrels [TeamICS]
> http://www.overbyte.be/eng/overbyte/teamics.html
> 
> 
> 
> Michael Kochendoerfer wrote:
> > Arno and all,
> > 
> > I realized and appreciated your hint to perform it all event-driven
> > and I tried to accomplish it the way you suggested. However, I have
> > some problems building the correct logic, it seems. In short words,
> > the mail sending part of my application is as follows:
> > 
> > 1. Opening a SQL server query
> > 2. Fill the standard properties (like Host, Port etc.) which are
> > common between calls
> > 3. Invoking my OnGetNextMailParam notify procedure *directly*, as if
> > it had been called from the OnRequestDone handler
> > 3a. OnGetNextMailParam checks if the query has still records, read
> > some fields, sets HdrTo if the record contains an mail 
> address, calls
> > Connect() and Next() for the query
> > 3b. OnGetNextMailParam calls a message handler procedure if 
> there's no
> > target mail address, which invokes 3 again.
> > 4. OnRequestDone is built like the sample code in 
> MailSnd1.pas, except
> > for the smtpQuit part. In my handler, OnGetNextMailParam is called
> > again, and if it reports a valid target address, it calls Connect()
> > again (if not, it should have been handled by 3b)
> > 
> > This all should work from the beginning of the query to the 
> end, where
> > each record containing a target address should invoke the sending
> > process and each other record should not (records without an mail
> > address are handled otherwise). But it doesn't - it calls Connect()
> > for two records and then it leaves.
> > 
> > I don't like you all to analyze my procedures but I'm 
> looking for some
> > basic framework which would do it. I first thought of building the
> > whole procedd into the smtpConnect part of OnRequestDone, but this
> > isn't possible due to the lack of mail addresses in some of the
> > records. I'm really stuck here and I now realize my concept won't
> > work as needed. 
> > 
> > The whole thing is not more or less than walking through a 
> record set
> > and sending a mail to each receiver within that record set having a
> > mail address. Other records having no mail address are handled
> > otherwise, must be processed within the same loop but don't invoke
> > any mail sending process. And - of course - it should be async ;)
> > 
> > TIA,
> > Michael
> > 
> > 
> > Arno Garrels schrieb:
> > 
> >>> while not FlagDone do begin
> >>>  //Application.ProcessMessages;  // Don't know whether or 
> not to use
> >>> the message pump here   Sleep(50);
> >>> end;
> >>> 
> >>> 
> >> 
> >> This is bad design. Do not wait in a loop. While sleeping 
> the calling
> >> thread is blocked. Instead let your derived component do 
> the work in
> >> the background. In order to get notified when the job has finished
> >> add a custom event that fires when the work is done, or may be add
> >> another custom event that notifies the application when a single
> >> message has been sent/failed. In other words, control the
> >> application completely thru events while executing the mailing. So
> >> in the ButtonClick handler there the call to start the mailing
> >> should be the very last line. 
> >> 
> >> ---
> >> Arno Garrels [TeamICS]
> >> http://www.overbyte.be/eng/overbyte/teamics.html
> >> 
> >> 
> >> Kochendoerfer, Michael wrote:
> >> 
> >> 
> >>> You all are giving excellent information in this mailing list,
> >>> thanks a lot!
> >>> 
> >>> I guess my problem is - as you describe - that the component is
> >>> still active, even if smtpQuit has been reached within
> >>> OnRequestDone. I don't currently check if it's still 
> connected, but
> >>> I will change it. Errors will be checked and force to abort the
> >>> entire mail and write some log entries.
> >>> 
> >>> As Arno said earlier, I'd like to have async components because of
> >>> their benefits. But in fact, for me it is a sync call, at 
> least for
> >>> each single mail. IOW, I've to wait until each particular mail has
> >>> been finished before I'm advancing to the next one. So 
> I'm starting
> >>> with Connect(), let the OnRequestDone do the background stuff and
> >>> set a flag if either aborted or quit. Now I know I've to wait also
> >>> for not Connected. But what's the correct method to wait for
> >>> completion? Currently, I have a loop after calling Connect()
> >>> looking like this: 
> >>> 
> >>> while not FlagDone do begin
> >>>  //Application.ProcessMessages;  // Don't know whether or 
> not to use
> >>> the message pump here   Sleep(50);
> >>> end;
> >>> 
> >>> Any thoughts?
> >>> 
> >>> TIA,
> >>> Michael
> >>> 
> >>> 
> >>> 
> >>> 
> >>>> -----Original Message-----
> >>>> From: [EMAIL PROTECTED]
> >>>> [mailto:[EMAIL PROTECTED]
> >>>> Behalf Of DZ-Jay
> >>>> Sent: Tuesday, January 16, 2007 10:57 AM
> >>>> To: ICS support mailing
> >>>> Subject: Re: [twsocket] Still problems while sending SMTP
> >>>> 
> >>>> 
> >>>> 
> >>>> On Jan 16, 2007, at 02:49, Arno Garrels wrote:
> >>>> 
> >>>> 
> >>>> 
> >>>>> When the response to the Quit command is received the connection
> >>>>> (may) still be alive. So watch both, whether Quit response has
> >>>>> been received as well as the SessionClose event. Call 
> connect only
> >>>>> after the session has been closed.
> >>>>> Don't start a loop directly from an event handler but post a
> >>>>> custom message to some Window, in it's message handler start the
> >>>>> next loop. 
> >>>>> 
> >>>>> 
> >>>> You could, in fact, re-use the connection if the next message
> >>>> is to be
> >>>> sent through the same server.  All you have to do is, after the
> >>>> DATA command is completed and the server acknowledges receipt,
> >>>> check SmtpCli.Connected, if you are still connected then 
> reset your
> >>>> state-machine to start the cycle fromthe MAIL FROM command.  Some
> >>>> servers required a "reset" (RSET) command be sent to reset state,
> >>>> and it doesn't hurt to send it anyway.  The important thing is to
> >>>> check the
> >>>> connection, because something may have happened -- and 
> indeed, some
> >>>> servers have anti-spamming filters that will kick you out after
> >>>> receiving DATA that they determine is spam, and some won't
> >>>> allow you to
> >>>> re-send after one message.  So the algorithm would be something
> >>>> like: 
> >>>> 
> >>>> 1. Connect
> >>>> 2. HELO
> >>>> 3. MAIL FROM
> >>>> 4. RCPT TO
> >>>> 5. DATA
> >>>> 6. If connected:
> >>>> 6.a (yes) RSET then back to 3
> >>>> 7. QUIT
> >>>> 8. back to 1
> >>>> 
> >>>> Of course, you should check for errors after each step (in
> >>>> OnRequestDone, before changing states).  Keep in mind that
> >>>> some errors
> >>>> are recoverable (transient: 400+), some errors are not
> >>>> (non-transient:
> >>>> 500+), and some are somewhere in between (like RCPT 
> warnings, etc).
> >>>> Recoverable errors allow you to try again, or require a RSET
> >>>> and start
> >>>>> from step 3, while non-transient errors require closing the
> >>>> connection
> >>>> and starting from scratch.  If you are sending general 
> messages to
> >>>> strange servers "in the wild" it gets pretty 
> complicated, specially
> >>>> when you factor in all the non-RFC-compliant servers; but if your
> >>>> application is of limited purpose, sending using the same server
> >>>> all the time, the errors and issues that may occur are 
> predictable
> >>>> and substantially less.
> >>>> 
> >>>> Building this logic in a simple state-machine using
> >>>> OnRequestDone makes
> >>>> it fairly easy to make your application powerful and efficient --
> >>>> the reason we always push for the use of async methods.
> >>>> 
> >>>> dZ.
> >>>> 
> >>>> --
> >>>> DZ-Jay [TeamICS]
> >>>> http://www.overbyte.be/eng/overbyte/teamics.html
> >>>> 
> >>>> --
> >>>> To unsubscribe or change your settings for TWSocket mailing list
> >>>> please goto http://www.elists.org/mailman/listinfo/twsocket
> >>>> Visit our website at http://www.overbyte.be
> -- 
> To unsubscribe or change your settings for TWSocket mailing list
> please goto http://www.elists.org/mailman/listinfo/twsocket
> Visit our website at http://www.overbyte.be
> 
-- 
To unsubscribe or change your settings for TWSocket mailing list
please goto http://www.elists.org/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be

Reply via email to