PHP based mail server; Release Day

So the day has come, I’m a modern web developer come sysadmin. One thing that I have learn’t over time, is rely upon others for critical systems! as a result, I outsource Mail to Google Apps and DNS to Point HQ , they’re experts at both, they keep my email up 99.9% (or something) and my DNS systems running smoothly..

But being a web developer, I like tinkering with my web server configuration! As a result, I run a VPS for my http serving which combines a special blend of Nginx, Apache, PHP-fpm, mod_php and MySQL.. For the last 2 years this setup has been running awesome, but I’ve found one thing that was lacking.. being able to receive and act upon emails to my vps. With all mail being handled by Google Apps, I couldn’t just watch the local mailboxes.

The obvious way forward was to install a mail server onto my VPS to process incoming email. Long story short, email servers suck. While researching, I came up against the fact that every mail server out there was designed for being a proper mail server.. Not what I wanted, a server to process emails..

I could ramble, but skip to here if you don’t care about the back story above.


Today I give you: A PHP based Mail server, It’s written in pure PHP, it receives SMTP data on STDIN, and responds on STDOUT, perfect for use with xinetd.

I originally started out with code from:  http://perplexed.co.uk/545_php_smtp_server_for_receiving_emails.htm however, fast replaced it with a home grown version, and have now expanded further to today’s class based approach.

This isn’t, and hasn’t been, designed for high load that being said, It’s received over 5,000 spam emails last month with little impact upon the VPS.  (who knew that spam bots just connect to port 25 on random IP’s??)

This is designed for a single-user situation, since PHP is a scripting language running as a single user, this can’t switch to the correct users account for processing or anything.. Doesnt suit everyone.. but works

This relies upon an external application to handle the TCP -> Stream conversion, a future release might daemon itself and use sockets to accept connections, do some pcntl_fork()’ing for individual connections, and even posix_setuid() to set the effective user.. but that’s filed into the Future Release bucket.

There is no support at all. although, if you throw a comment on this post, I might respond if I’ve got time. hopefully it should be reasonably straight forward to understand.

Licensing is also left sketchy for now, See the mail-server.php header for a initial custom license, tl;dr: You may use it for commercial and personal use, you must however credit, don’t fork/rename/charge for it, but give it to your friends.. always refer to the license in the header however, as that’s the only valid source of licensing details.

No External libraries required, Aside from the previous mentioned PHP and XInetd (or similar) to handle the connections. Oddly enough, It doesn’t even require WordPress (what a shock huh? – Stay tuned, I’m sure you’ll see WordPress as a Email Client soon enough with the integration of this ;))

This is NOT a relay mail server, It’s been designed to process incoming mail, and discard mail for addresses which it doesnt know. It will not forward mail on for you. Please check that you don’t conflict with sendmail on your own system, I think I have mine set for sendmail on loopback, and this on the external interface or something like that.

You can get the code from my SVN: http://svn.dd32.id.au/php-mail-server/ – Please note, this is a READ ONLY repository, if you find a bug and would like to submit it, for now, just sent it over to me at contact [at] dd32.id.au

 Integrating with Xinetd:

How I have it running is as follows: /etc/xinetd.d/d-mail

service smtp {
        port                    = 25
        bind                    = YOUR IP ADDRESS
        socket_type             = stream
        protocol                = tcp
        wait                    = no
        user                    = USERID TO RUN IT AS
        server                  = /path/to/mail-server/mail-server.php
        instances               = 10
        nice                    = 10
        disable                 = no
}

That limits connections to 10 active at a time (instances) which works well for me, that should hopefully prevent overloading.

What emails am I processing? Well, the examples should suggest that to you! SVNSync to automatically sync up a local repository with a remote repository which I don’t have admin access on for one, SVN update on a local WordPress installation (This site! It’s running on the latest WordPress trunk release within a few seconds of each commit) and there’s a few domino effect processing I’d like to do as well (ie. Alter mailing list posts to selectivly ignore certain things, Remove partial content from svn emails (I don’t want to see a 100kb minified css file in a commit email!). I’ll publish those details later when I get to it!

Magic 8 Ball Example! 

Included in the SVN repo, is a single Example plugin. A Magic 8ball extension, send an email to it with a question in the subject, and it’ll reply with an answer.

You can test this out by emailing 8ball [at] php-mail.dd32.id.au and seeing if it replies (It better!)

FIN.

So go forth and download/run/test out the PHP Mail Server!  Download from  http://svn.dd32.id.au/php-mail-server/ Send patches to contact[at] dd32.id.au, oh, and test it out by sending an email to 8ball  [at]  php-mail.dd32.id.au with a question in the subject!  

7 thoughts on “PHP based mail server; Release Day”

  1. Interesting approach. The traditional method for supplying emails to a PHP process would be to just create an alias that pipes to the PHP script. Though that does require running a regular email server, like Postfix.

    1. That was my initial approach – given that’s what I’ve used in the past.

      Ultimately I haven’t used a mail server such as Postfix/qmail/the other popular one in a long time, and in all honesty, the Configuration files for them were still based on the 10-year-old originals, after a few failed attempts, I went looking for a simplistic server with minimal functionality that I could read its configuration file in 10 minutes, understand what it would, and wouldn’t do, and wouldn’t have to worry about security issues burried in 100,000 lines of code.. there wasn’t anything that fit the bill.

      Moved on, looked for PHP based items.. Didn’t find anything that worked, immediately wanted to hack something together – And I did, a 50 line PHP script which accepted mail, and dumped it to a file.. problem solved in an hour, less than half the time I’d been trying to install and configure properly, postfix.

      Since there wasn’t a good PHP example out there, and I couldn’t handle the thought of releasing the original dodgy script, This was put together in a few hours.. and has been trudging away for about 2 weeks now (although I keep fixing small bugs here and there).

      So far it’s managed to receive about 1,000 spam messages in that time (to @dd32.id.au – the MX entries point to GoogleApps! – received ~50 legit emails) hasn’t caused me grief, can be extended in a matter of minutes, and lets me get on with other work :)

  2. Dion, this looks awesome, but I’m not able to connect to your SVN server. Keep getting ‘502 bad gateway.’

    Maybe it’s my building/work’s ISP, but I can’t imagine they’d filter an HTTP connection. Is there any chance you have a blacklist that I got onto somehow?

    Tks, -Mike

    1. Thanks, the SVN is working again & checkout worked. Too many services contending for ports I’m sure.

      Haven’t run a simple mail server since my Perl days. But recently I’ve been thinking that my old way of saving emails to a task file was simpler than all the new tools. Looking forward to playing with this.

      1. I believe I replied to you via email on this.. But just so others gain some knowledge: I like tinkering, I forgot to restart the svn server (apache) after doing some debugging..

        If anyone else has a similar problem.. just shoot me an email via my contact form..

Leave a Reply

Your email address will not be published. Required fields are marked *