Timeout

devongovett

New Member
Messages
33
Reaction score
0
Points
0
Hello,

I am using PHP to send out a large number of emails (almost 300) with a loop. After about 30 seconds, my browser times out. Does this mean that the PHP script was stopped? If so, is there a way to find out where it left off so I don't have to send duplicate emails to people?

Also, I need to fix the timeout problem, so how can I make it run for longer than 30 seconds - i.e. until it finishes?

Thanks!
 

Scoochi2

New Member
Messages
185
Reaction score
0
Points
0
You can't. There is a limit on the processing time.
However, you can refresh. wink wink.

If you use JavaScript or metatags to refresh the page after just a few seconds, you could pass on the remaining workload using normal http means (ie, GET POST or COOKIE), or you can store the workload in a database (or text file) so PHP knows what's left to do.

I would recommend having the email addresses in an array, then email them one at a time. Use array_shift to get each address in turn. You'll want to do that a certain number of times. Go for 50.
Once that 50th email is sent out, you should start outputting the HTML headers and metatags. This will ensure that the 50 emails are already sent before you tell the page to refresh! In your metatags or JS, reload the page, but ensure that you serialize the array and pass that on as a GET.

Back to where you started now :)
Use GET to obtain the relevant data. unserialize it and you have the remains of that array back.


Not the best or most elegant solution, but it will get the job done.


EDIT: in fact, here's a [modified] small snippet of code I just found in one of my old projects. Modify and use it as you wish :)
PHP:
<?php
if (isset($_POST['emails']))
  $emails_array = unserialize($_POST['emails']);
else
  $emails_array =  array('emailaddress1');  // GET LIST OF EMAIL ADDRESSES FROM ELSEWHERE

/*

SEND OUT 50 EMAILS, SHIFTING OUT ARRAY VALUES

if you still get timeouts for 50 emails, go for less than 50.
if you have to keep lowering the number, why is it taking so long?
look into your existing code if that's the case.

*/

echo '<html><head></head><body>
<form action="index.php" method="post" name="complete">
<input type="hidden" name="emails" value="'.serialize($emails_array).'"></form>';
?>
<script type="text/javascript">
document.complete.submit();
</script></body></html>
 
Last edited:

devongovett

New Member
Messages
33
Reaction score
0
Points
0
I honestly don't care if the browser times out or not, I just need it to send the emails :). When the browser times out, does that affect the php script?
 

Scoochi2

New Member
Messages
185
Reaction score
0
Points
0
The browser doesn't time out. The server times out...
Either the PHP takes too long to finish executing (ie, it can't send out all the emails and so you'll need to do something like I mentioned) or your browser doesn't get a reply from the server, and gives up waiting. In this second case, not a single email will be sent out. There is typically nothing you can do here other than trying again later or using a different host if you have to do it there and then.
 

xPlozion

New Member
Messages
868
Reaction score
1
Points
0
You've got a few options, if you want to go for a db backend, you can add the field, sent and make it 1 when the email is sent (pref after), and when you initially start sending emails out, set all of them to 0.
PHP:
<?php
$limit = 15;
// assuming you've already got a db connection running

// reset the sent list
mysql_query('UPDATE newsletter SET sent=\'0\'');

$emailsQ = mysql_query('SELECT email FROM newsletter WHERE sent=\'0\'');
while ($result = mysql_fetch_assoc($emailsQ))
{
  //place all emails into an array
  $email[] = $result['email'];
}

$total_emails = count($email);

$start=0;
if ($total_emails > $limit)
{
  while ($start < $total_emails)
  {
    for ($i=0;$i>$limit;$i++)
    {
      if ($start == $total_emails)
        break 2; //break out of the for and while loop

      //your email command goes here
      echo $email[$start];

      //update db to know this member was sent an email
      mysql_query('UPDATE newsletter SET sent=\'1\' WHERE email=\''.$email[$start].'\' LIMIT 1');

      $start++;
    }
  }
}

echo 'All ',$total_emails,' emails sent';
?>
another way to do it, is by splitting them up, as schoochie has said. make an array. maybe since the for loop is taking so long, it thinks it's a never-ending loop, thus terminates the script. try breaking up your array into increments of 30 or something, then start a new loop at 31 ;) the code above should work, just replace the db with what you are using it with.

off topic, but may help you. I have a cron script in php that makes i think about 200 calls to different pages (don't worry, it's in the wee hours in the morning, one day a week, just to synchronise data). Maybe cronjobs are not affected by server timeouts, or i'm using it a different way... idk tbh...
 
Last edited:

mephis

New Member
Messages
39
Reaction score
0
Points
0
off topic, but may help you. I have a cron script in php that makes i think about 200 calls to different pages (don't worry, it's in the wee hours in the morning, one day a week, just to synchronise data). Maybe cronjobs are not affected by server timeouts, or i'm using it a different way... idk tbh...

CRON jobs are definitely not affected by server timeouts, it's only when PHP scripts are parsed through the Apache server that they have a timeout (set in php.ini, default is 30 seconds).
Therefore, you can set up a CRON job to run your PHP script outside of Apache (i.e. in the command-line). Alternatively, you can implode an array of email addresses and send it all at once (here's a snippet of some of my old code):

PHP:
$emails = implode (", ", $email_array);

$headers = "MIME-Version: 1.0"."\r\n".
   "Content-type: text/html; charset=iso-8859-1"."\r\n".
   "From: email@youserver.com"."\r\n".
   "Reply-To: email@youserver.com"."\r\n".
   "X-Mailer: PHP/".phpversion();
$subject = "Testing email";

$body = "whatever you want to put here (even HTML, as specified in Content-type)";

mail($emails, $subject, $body, $headers);

the only problem is that this might be filtered as SPAM, but if you tell your users to add "email@youserver.com" to the "safe senders" (or whatever their email clients call it) you should be OK
 
Last edited:
Top