Reputation:
I have recently implemented the Swiftmailer library, but the first time I used it, I got a php timeout error even though it only had to send out mails to around 300 people.. (I should mention that using the set_time_limit(0);
workaround is not an option due to restrictions on the server)
The way I use it is like this:
$transport = Swift_SmtpTransport::newInstance('smtp.mydomain.com',25);
$mailer = Swift_Mailer::newInstance($transport);
$message = Swift_Message::newInstance();
$message->setSubject($_POST['subj']);
$message->setFrom(array('email' => 'Mysite'));
$message->setTo($recipients);
$message->setBody(strip_tags($messagebody));
$message->addPart($messagebody, 'text/html');
$numSent = $mailer->batchSend($message);
printf("Sent %d messages\n", $numSent);
where $recipients
is a commaseparated array of emails (built with explode()
from a mySQL query)..
I have no idea which part of the above code that generates the script-timeout, and since I use it for a newsletter function, it is rather difficult for me to test or debug it, so I would be really thankful for anyone coming up with a (near) bulletproof solution to this problem :)
Thanks in advance !
Lars
Upvotes: 1
Views: 4996
Reputation: 597123
If you have access to cron, fill up a data base with what you need to send the newsletter, then pop the queue using a cron job that runs a script processing a low number of mails.
If you don't, write a system() statement at the end of the script so it call it self, passing the next newsletter as parameters, then dying. So you will execute the script as many time as you need to send a mail.
Upvotes: 4
Reputation: 314
[Update] well the data below is for me calling the smtp server from my dev box. So from Eastern Europe decent home ADSL to a US SMTP server (my project Staging server). When it all runs on the Staging - so localhost php+mysql+Postfix this baby barely takes 1 second to send 5 individual emails and a BCC to 30 recipients. Quite a sight...
Swiftmaieler actually behaves synchronously and waits for the SMTP server to send each email so that it gets the array with failed mail addys. So if u BCC to 100 recipients the total time is: time taken to talk to the server + time for the server to send 100 emails. Sending 100 individual emails would be 100*(talk time + send time). My Postfix takes 1 second per email and talk time is also 1 sec so it takes 2.5 sec to send an individual email. With the standard 30 sec timeout it would be 12 individual emails or 20 recipients in the BCC. It's all a guessing game actually :P
All these mailer seem to hve been designed with set_time_limit(0) as a must. For someone who has 30 sec timeout the smartest way would be to have a "batch sending" page that stays open and has an ifrme+refresh or Ajax mechanism that calls a "send mail packet" (a small one - 10) method every x seconds. With Ajax you could call again on script response.
Upvotes: 1
Reputation: 2576
Limit recipients number per sending mail. Call script "n" times with offset value via curl or cron and it will not throw timeout. For example set $limit = 20. Then call script n times:
send.php?offset=0
send.php?offset=20
and so on... If your root script (which calls send.php script) will timeout, then you can continue sending mails from your last offset.
Upvotes: 2
Reputation: 154603
set_time_limit(0);
before the code
EDIT: Okay, since you cannot use the set_time_limit
() function, why not put the code that sends the emails inside a function and use register_shutdown_function
()? That way, when the script times out it call the function again.
Upvotes: -1