Reputation: 486
I have built an emailing script with PHPmailer after inserting into a table, however, I'm getting a bad gateway 502 coz the script times out. and sending 300+ emails in response to a web request doesn't sound like a good idea to me. So my question is how can I build a queue that will send the emails in the background?
as far as I understand I will need new table lets say email_queue_table
insert the email addresses, content and then have a field called status
sent or queued create a while loop something like if($status == "queued"){ //then send the email here} else{ // nothing to be sent.}
If you know of a more efficient/better way of doing this I'm all ears. Thanks for any help.
Upvotes: 2
Views: 5874
Reputation: 5395
The logic of how it would work - with a bit of code to help you along the way - is something like this:
Add the following fields to your email_queue_table
table:
email_address
, Email address (to:)content
, Message content. If it's the same message that's to be sent to every user, you'd be better storing this once somewhere else. If it's just a few things that need changing in the content such as the users name then use PHP's str_replace()
to do things like str_replace('%name%', 'Andy')
where %name%
is in your template and will be replaced as appropriate on each loop. Ideally you would not have this column or be repeating the same data here - if your message was 50 Kb and you had 3000 users, for example, you'd be storing 150 Mb of data in a table un-necessarily.sent_status
, Sent status (default = "not sent", or 0
)retry_attempts
Retry attempts (default = 0
)Create a PHP script which does the following:
SELECT email_address, content FROM email_queue_table LIMIT 0, 50
. This gets you 50 people per loop. Repeat until the end of the list - to do this you will need to know the total number of records in the table which you can do with COUNT()
content
to email_address
return
status from PHPMailer. If it's successfully sent flag sent_status
as "sent" (1
). If not, flag it as "not sent" (0
).sleep(60)
between each batch of 50. This pauses execution of the script for 1 min (60 seconds) and may help mitigate your server as being flagged for sending out large quantities of email in one attempt.When all the messages have been sent, you could optionally go back through the table to try and resend any that didn't send. Still keep the LIMIT
logic because there may be a large number where it didn't send, e.g.
SELECT email_address, content FROM email_queue_table WHERE sent_status = 0 AND retry_attempts < 5 LIMIT 0, 50
Increment the retry_attempts
field. Stop if it goes beyond, say, 5 attempts.
You cannot execute the above script through a browser because it will time out.
Instead, you can manually trigger it from a command line, e.g.
php send_email.php
Or set the above up on Cron, to run every night, or at whatever frequency are needed.
Or you can trigger it from an ajax call and update the progress in the browser. See: creating background processes in php for long running process
Upvotes: 1