PHP and Sendmail
#224 Henry, Sunday, 29 March 2015 11:55 AM (Category: Web Development)
(Tags: php web sendmail)

I write my websites in PHP. On several of them, I use the PHP mail function to send an email. This is mostly for contact purposes, or for giving temporary access to a user who has forgotten their password. The function is like this:

mail ($to, $subject, $body, $headers, $sendmail);

This function creates an email, and hands it over to sendmail. Ever since I started using this, I found it slow. It takes forever to process. The webpage just goes blank and the user waits for maybe 15 seconds before anything else happens. I never knew why this was.

I added new Contact pages to the ASG website recently. I did not like this delay. You can't have a delay while nothing is happening, your users don't know what is going on. So I researched it. StackOverflow had lots of suggestions, but I checked them all, and none of them was the problem.

Finally, I ran experiments. I watched the sendmail logs while I ran the webpage and called that mail function. And I found my problem. Sendmail on my Linode handles the mail for 12 domains and couple hundred users. The sendmail config has

FEATURE(`greet_pause', `15000')dnl

This is an anti-spam measure. When a remote mailer connects, there is a 15 second delay before sendmail comes back with the 220 response. If the remote mailer starts churning out mail commands between the connection and the 220, sendmail assumes it is a spammer and disconnects. All valid mailers will connect, wait for the 220, and then start sending the email. And that's what is happening when PHP connects to sendmail to send a message - there is the 15 second greet pause, and then the transaction takes place.

I'm not willing to remove that greeting pause. I looked in the sendmail logs and saw that there are plenty of occasions each day where SMTP is spewed out as soon as a connection is made, which means that old stupid spammer trick is still in use. I thought they had gotten smarter about it, but no, old techniques are still in use.

We have techniques for dealing with things like this at work. If it's possible to have delays that hold up the action, then put a queue in between. So for my PHP contact web page, I created a SQL table, and stored the email details in that table. That's lightning fast, the web page responds rapidly and the user is not inconvenienced. I have a cron job that checks that queue regularly, and if there are messages to send, it will connect to sendmail and send them.

So now I know, and now I have a neat way around it.