Hi Michael, I've had similar problems here.
It sounds like you might be missing a "QUIT". This closes the mail server. else if (RqType = smtpMail) and (ErrorCode = 0) then begin sgProgress.Value := 90; // -- Write every entry for xc :=1 to SmtpEmail.EmailFiles.Count do Report('SENT','Successfully sent ' + SmtpEmail.EmailFiles.Strings[xc-1]); SmtpEmail.Quit; end else if (RqType = smtpQuit) and (ErrorCode = 0) then Quoting Michael Kochendoerfer <[EMAIL PROTECTED]>: > 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