-2

My program needs to send about 600 emails out. As my ISP only allows 400 in each hour I need to send say 300 of them, wait for an hour and send another 300. I don't really want my program hung for an hour as the user might want to do something else with it while waiting. Better still, they might even want to shut it down.

Is there a way to delay for an hour whilst keeping the program responsive or even allowing it to be shut down and woken up to continue?

I found this which is helpful

[What is the best way to program a delay in Delphi?

but that declares a variable

var
  SE: TSimpleEvent;

which Delphi 2009 does not understand

BTW if the answer involves threads please could you explain carefully or even give code as I have never used threads before (not knowingly anyway!)

Community
  • 1
  • 1
user3209752
  • 619
  • 2
  • 17
  • 29
  • 1
    Schedule a task that will execute your application which will send the batch and terminates. – TLama Aug 25 '15 at 18:05
  • 1
    Windows Scheduled Tasks is the appropriate thing to use here. However, for your main purpose, I'd advise using a proper email service such as Mandrill to keep yourself from getting blacklisted.. – Jerry Dodge Aug 25 '15 at 18:10
  • I'm sure TSimpleEvent is present in D2009. Look into the SyncObjs unit or search in help. – LU RD Aug 25 '15 at 18:23
  • 1
    The most robust way to deal with this is to set up a rolling sampling interval of one hour, count the number of emails actually sent during the sampling interval and suspend sending emails until the number sent drops below 300 if it approaches that rate. I.e. comply with the constraint your ISP actually imposes. Requires keeping a rolling record of when each email was sent, but that's hardly difficult. – MartynA Aug 25 '15 at 19:31
  • 1
    @MartynA Adding to that, it also helps divide them out so you don't have 300 blasted all at once - which is perfect activity to get blacklisted. Not to mention the resources used in one burst of activity. Instead, it could send bursts of maybe up to 20 emails at once every 5 minutes. – Jerry Dodge Aug 25 '15 at 23:22
  • `TSimpleEvent` existed in Delphi 2007, so it certainly is present in D2009. Shame on you for not reading the documentation and just assuming that it isn't available. – Ken White Aug 26 '15 at 01:53
  • This is a task that should be handled by a central inhouse mail server or a special mail proxy server. Your application can run several times from several users sending all 600 mails (n x 600 mails). – Sir Rufo Aug 26 '15 at 05:37
  • It is better to send 50 emails every 10 minutes than sending 300 at once. This will reduce the risk of being blacklisted, not only by the receiving mail server, but also by your ISP smtp server. You might also be able to create two email accounts to double the limit, this means you can send all the emails without delay. – Hans Aug 26 '15 at 07:33
  • I did check with the ISP and they advised sending out either 300 emails all at once or send batches of 7 each with 40 bcc (its the same email going to different people, then waiting an hour and repeating. – user3209752 Aug 26 '15 at 07:39
  • @Ken White - maybe, but also shame on posters here that offer code requiring extra 'uses' clauses to the default ones without saying which ones are needed, or even which version of Delphi their code requires. I often try out snippets and eventually have to give up as they contain so many errors due to missing references. If a poster is offering something like TSimpleEvent as a solution to somebody who is obviously not already using it, then it doesn't take much thought just to say that TSimpleEvent requires SyncObjs. (or put it as a comment next to the declaration). – user3209752 Aug 26 '15 at 07:50
  • @ Jerry Dodge. Any hints on how I might use Windows Scheduled Tasks i.e. how to get Delphi to insert a new task and then remove it after it has run a few, but unknown, number of times? I guess that would also require a separate program to be launched that just send the emails. Currently I have some prototype emailing code within the much larger program I am developing that is a front end to a remote database and does all the processing. I'd also have to be sure it would work with whatever OS my eventual users will have. – user3209752 Aug 26 '15 at 07:55
  • @Hans Would having many email accounts really work? This is used to send out circulars to members of an association so I am going through an email account I created on the associations web account. I guess I could make loads of new email accounts but suspect the ISP limit of 400 max recipients per hour would apply the the whole account, not each individual email account – user3209752 Aug 26 '15 at 08:01
  • 2
    "also shame on posters here " I think that's a bit OTT and ungracious considering that they're giving their time and effort free of charge. Much more often, the "fault", if there is any, is questioners quoting code without identifying which non-standard components, etc, that they are using. – MartynA Aug 26 '15 at 09:35
  • @JerryDodge: Indeed. When I said "robust" I was thinking that keeping records would help in case of a falling-out with the ISP, so that one could quote them chapter and verse. Otoh, if you think in terms of a minimum interval between sends, and keep to it, then just recording the time of the last one would suffice for a minimalist implementation. – MartynA Aug 26 '15 at 09:41
  • @user3209752 That depends on your ISP. If you are using Google accounts to send emails, the limit is per email account. – Hans Aug 26 '15 at 11:57
  • 2
    Sorry. People are donating their time to help others for free, and your response is *shame on posters here for not saving me from having to open the help file*? Are you too lazy to do a search in the help contents or via Google to find out what something is? Seriously? Your immediate response is *well, it's not in a unit added by default, so it must not exist*? Good luck with getting anything done. Far more than half of Delphi's functionality is provided in units that don't get added by the IDE, so not everything can be done by dragging and dropping things. – Ken White Aug 26 '15 at 12:29
  • Shame on posters is OTT, my apologies. I do google anything the compiler objects to (Help in Delphi 2009 doesn't work in all installations). I didn't mean to imply that if D2009 didn't understand it then I assume it doesn't exist. I simply meant that if someone gives freely of their time to help others with a code snippet then it helps to also highlight anything extra that is needed - such as a unit or a specific version - that will assist them in understanding the code. I guess I was a bit taken aback by Ken's assumption that I hadn't checked as opposed to LU RD's helpful comment. – user3209752 Aug 26 '15 at 13:56

1 Answers1

1

A simple solution is often the best. You could use a standard TTimer with an interval of 1 second and the count down from 3600. When you counter is zero one hours has past.

This is a dummy implpementation showing my point :

procedure TForm1.FormCreate(Sender: TObject);
begin
  Timer1.Tag := 1;
end;

procedure Send300EMails;
begin
  // Dummy
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Timer1.Tag := Timer1.Tag - 1;

  if Timer1.Tag = 0 then
  begin
    Timer1.Enabled := false;
    Timer1.Tag := SecsPerHour;
    Send300EMails;
    Timer1.Enabled := True;
  end;
end;
Jens Borrisholt
  • 6,174
  • 1
  • 33
  • 67
  • 1
    Better than counting on your own is to check if an hour has passed. When the PC slows down for different reasons a timer will may not be triggered every second. – Wosi Aug 25 '15 at 18:16
  • Correct if accuracy is an issue – Jens Borrisholt Aug 25 '15 at 18:19
  • 1
    This assumes the first 300 were all sent out in the first hour, which might not actually be the case. – MartynA Aug 25 '15 at 19:20
  • This assumes that nothing else is being done on the PC, and that posting messages that are basically CPU-burning NOOPs for most of the running time is acceptable. – Ken White Aug 26 '15 at 01:18
  • 1
    @MartynA To overcome your object, start the timer disabled and enable it when you send your first batch, but better is to use it to trigger a time comparison. The CPU burning is minimal at once per second, but I would trigger once a minute anyway if accuracy is not an issue. Time comparison is better and, if you save the last sent time to a file and read it back when loading, it will survive even a shut down. However you will always need something to trigger a time check and a TTimer is as good as anything. – Dsm Aug 26 '15 at 08:37
  • I see people doesn't like my answer. My main objective was to show the use of a timer inorder for waiting an hour. I haven't thought about accuracy and stuff like that. The question lacks information about a lot of stuff. We'll have to wait for him who wrote the question to return. – Jens Borrisholt Aug 26 '15 at 08:52
  • @Dsm: I don't disagree, particularly. My problem was more with the formulation of the problem in the q than any rather pedestrian response. – MartynA Aug 26 '15 at 21:47