1

in php5 web app, getting email address from user and sticking it into database, but want to send the email without user waiting for the email to complete. using gmail, sometimes takes a few seconds.

thinking about fopen( "http://self.com/mailer.php", "r" ), where mailer.php would do the actual mailing. will this work?

PeeHaa
  • 71,436
  • 58
  • 190
  • 262
cc young
  • 18,939
  • 31
  • 90
  • 148
  • Sending the E-Mail should be a matter of milliseconds. Do you have actual performance problems because of this? – Pekka Dec 29 '11 at 12:46
  • What is your mean from without user waiting? – Mohammad Saberi Dec 29 '11 at 12:46
  • sending email through gmail sometimes takes a few seconds. want to show the next page to the user without her waiting for the email to have been sent. – cc young Dec 29 '11 at 12:49
  • Ah, fair enough, if you use an external server, that might happen. On the other hand, if you do it in a different process, you don't have a chance to tell the user if something goes wrong. – Pekka Dec 29 '11 at 12:51
  • @Pekka right - will report errors to database. – cc young Dec 29 '11 at 12:52
  • Fair enough. Here's one question dealing with the issue: [most simple way to start a new process/thread in PHP](http://stackoverflow.com/q/8548419) – Pekka Dec 29 '11 at 12:55
  • possible duplicate of [php execute a background process](http://stackoverflow.com/questions/45953/php-execute-a-background-process) – Pekka Dec 29 '11 at 12:55
  • @Pekka not really. using web page versus command line has many advantages: pconnect to the db (in postgresql connection is very expensive), all logic in one place, and _no security issues_. – cc young Dec 29 '11 at 12:59
  • 1
    @cc then do a `curl` from the command line that calls your web page. I think it's the only way - the way you show won't work, it will wait for the mailing process to take place. – Pekka Dec 29 '11 at 13:00

1 Answers1

1

There are two approaches that have worked well for me in the past.

Database Email Queue

Create an "email_queue" table in your database or whatever else you are using for persistent storage. Each entry contains everything you will need in order to send an email (e.g. Subject, recipient, sender, body, etc...) and a "sent" flag field. To send an email you add an entry to this table using a helper class.

Then you create a cli php script that reads from the queue table filtering for entries that have the sent flag set to 0, send the email and finally set the sent flag to 1. This script needs to run in a cron job, but since you probably want to run it more often than one minute, you can use something like Frequent-cron. The scheduled task should only run in one web server in case you have many (and assuming your persistent storage is shared).

Local email queue

I've also had some success configuring a local postfix server on each web server to deliver mail using an external smtp service. The goal here is to get postfix to accept the email as fast as possible (because it is local) and then deliver it via the external SMTP server in a different process. Postfix will act as an intermediary queue.

I personally like the first solution because it gives your app more information about email delivery for statistical analysis' record keeping, etc..

Hope that helps.

0x6A75616E
  • 4,696
  • 2
  • 33
  • 57
  • thanks. instead of cron, what do you think about a daemon that sleeps 60 seconds after checking the mail queue - this would save db re-connects – cc young Dec 29 '11 at 13:51
  • 1
    That'd work too but you'd have to build it custom in something other than php. Php leaks memory like a mad man :) so leaving it running all the time is likely not sustainable. Db reconnects are usually not a big problem though. – 0x6A75616E Dec 29 '11 at 13:59
  • good to know. think will use ajax from client to back to server to send the email. since that can be unreliable (client goes to new page), will use cron to curl same page to pick up any dropped emails. – cc young Dec 29 '11 at 14:05
  • I'd not make the script that sends emails publicly accessible. You can use ajax to make a call that queues the email with some type of user authentication, but the queue cron should be private to prevent attacks. – 0x6A75616E Dec 30 '11 at 04:14
  • the accessible script requires a session, is callable only through an ajax function, takes no args - it simply queries and sends emails unsent for some reason - so I think safe enough unless I'm missing something really stupid. – cc young Dec 31 '11 at 13:08