Page 1 of 1

Best way to loop through results array to send multiple mail

Posted: Wed Jan 11, 2006 6:31 am
by matthijs
I have some questions about a script I am making to send a newsletter to a list of people. I posted a similar question here, but as I've understood now it's better to start a new thread instead of hijacking an existing thread.

What I would like to know is:

1 - what is the best way to loop through the results I get from the db? In my first example I first build a multidimensional array and then split it using array_chunk(). I have a feeling that that is a bit laborious, compared to the second example.

2 - when should I implement a delay with sleep()? From what I know, using the phpmailer class I should be able to send quite a lot of emails before the script runs out of time. So, what are your guesses. Can I run the script for less then 1000 mails without a sleep() build in?

3- If needed, what is the best way to implement a delay? Assuming I try to do it in the script itself, and not use a cron job (which many would advice).

Version 1:

Code: Select all

<?php
set_time_limit(300); // 5 minutes

if(isset($_POST['submit']))
{
    //  validation of $_post values here....
    // Setup body here ...
    // instantiate the class here ...
        
    // Get the user's Email
    $sql = 'SELECT FirstName,LastName,EmailAddress,MailType FROM mymaillist_subscribers';
    $result = $db->query($sql); // create MySQLResult object. I use a MySQL class from the php anthology books
    
    $mails = array();
    while ($rows = $result->fetch()) {
       $mails[] = $rows;
    }
    $chunks = array_chunk($mails, 50);

    foreach($chunks as $value)
    {
        foreach($value as $row)
        {
         // Send the emails in this loop.
         $member_name = $row['FirstName'] .$row['LastName'];
         $member_address = $row['emailaddress'];
		  		  
         $mailer->AddAddress($member_address);
 
         $mailer->Body = str_replace('{MEMBER_NAME}', $member_name, $htmlBody);
         $mailer->IsHTML(true);
         $mailer->AltBody = str_replace('{MEMBER_NAME}', $member_name, $textBody);
	
         $mailer->Send();
         $mailer->ClearAddresses();
         $mailer->ClearAttachments();
         $mailer->IsHTML(false);
         echo "Mail sent to: $member_name<br />";
        }

        // Have the loop sleep a few secs
        sleep(3);
    }
}
?>
or

Code: Select all

<?php

...
    $x = 1;
    $hold = 50;

   while($row = $result->fetch())
    {
      // Send the emails in this loop.
      $member_name = $row['name'];
      $member_address = $row['emailaddress'];
		  		  
      $mailer->AddAddress($member_address);
        
      $mailer->Body = str_replace('{MEMBER_NAME}', $member_name, $htmlBody);
      $mailer->IsHTML(true);
      $mailer->AltBody = str_replace('{MEMBER_NAME}', $member_name, $textBody);
		  
      $mailer->Send();
      $mailer->ClearAddresses();
      $mailer->ClearAttachments();
      $mailer->IsHTML(false);
      echo "Mail sent to: $member_name<br />";
      
       // delay method:
      $x++;
      if($x == $hold)
      {  // When $x is equal to $hold, a 3 sec delay will occur avoiding php to timeout
          sleep(3);
          $x = 0;
      }
    }
...

?>
I hope my questions are clear enough.

Thanks, Matthijs

Posted: Wed Jan 11, 2006 6:51 am
by BDKR
I'd say the best way to loop through anything is the most direct method. I'm implying that that is the method with the least overhead.

As for the delay and all that jazz, I would strongly suggest you put it in a chron job. I don't see the point in doing it any other way. At least the time constraints become a non-issue. Just do a set_time_limit(0) and let it run as long as it takes. No need for a delay (it appears) so don't include one.

Cheers

Posted: Wed Jan 11, 2006 7:06 am
by matthijs
Ok, so what I thought already, that the loop in the second version is the most direct and better method because it has the least overhead. Thanks for your input.
As for the delay and all that jazz, I would strongly suggest you put it in a chron job
I've never worked with cron jobs before, so that's still all unknown territory for me unfortunately..

But I'll look into it.
No need for a delay (it appears) so don't include one.
I'll ditch the sleep then. It's just that I have found many solutions using this. Maybe it's used to lessen the burden on the mailserver a bit?

Posted: Wed Jan 11, 2006 7:37 am
by Weirdan
Sleep is used in bulk mail sending loops to prevent the MTA (mail transfer agent, your mail server) from getting overloaded. Sleep will not prevent php to timeout (though the time the process slept does not count when checking whether the process is timed out).

Memory usage of the first snippet is about three times higher comparing to the second one.

Posted: Wed Jan 11, 2006 7:42 am
by BDKR
matthijs wrote:
As for the delay and all that jazz, I would strongly suggest you put it in a chron job
I've never worked with cron jobs before, so that's still all unknown territory for me unfortunately..

But I'll look into it.
It's really not that difficult at all. If you can read and write code, you'll have no problems with cron jobs. :)

It appears that Weirdan has good intel on the sleep function usage in the bulk mailers. In that case, I'd put it back in.

Sorry... :oops:

Posted: Wed Jan 11, 2006 7:58 am
by Weirdan
'It appears that Weirdan has good intel on the sleep function usage in the bulk mailers.', wow, what a super-polite method to call me a spammer :)

j/k, no offence taken.

Posted: Wed Jan 11, 2006 8:41 am
by matthijs
'It appears that Weirdan has good intel on the sleep function usage in the bulk mailers.', wow, what a super-polite method to call me a spammer Smile
Ha! Advice directly from someone with loads of experience with mailing lots of people, great! ;)

I'll trust him on this one then and put in the sleep() for now. At least untill I've upped my knowledge on crons and use that.

And I'll certainly go with the second, simpler loop.

Thanks a lot guys!