« Smarty & GNU gettext System | Main | Amazon S3 PHP Class »

November 02, 2006

Postfix To PHP

I have been looking for a good way to setup special email addresses which will be handled by a php script so I can push them into a database.

I'm writing a service where certain members of a website can exchange messages and I want those members to be able to have an email address they can give people which sends messages right into their account on the website.

The problem also was that the domain I wanted the emails to use had other addresses on it also AND on top of all that they were virtual domains in Postfix. Postfix does not support pipes in targets to VIRTUAL aliases (it does so for normal ones of course) so I could not just setup an alias for each account and pipe it to some script...

But that was not even needed, I came up with a way nicer solution. Here is what I did:

I already had a mysql configured virtual email setup running with Postfix / dovecot so I was familiar with the mysql maps setup. So all I did was setup a 2nd config file for a 2nd mysql powered virtual alias map, lets call it mysql_virtual_alias_php.cf.

In that file, among with the login info of course, I setup this query:

SELECT concat(username, "@php.domain.tld") FROM accounts WHERE username='%u' AND type = 2 AND active = 1

I then added the mysql_virtual_alias_php.cf file to the end of my virtual_alias_maps directive in main.cf and thus this is checked at the end to see if there might still be any other aliases to be resolved.

%u expands to just the local part of the address, so emails going to foo@domain.tld would run this query with username='foo' unless of course they matched anything in a previous virtual alias map.

One thing to note of course is that this will the run for all mails going to any virtual domains you have setup and would not care about it, you could also add some additional checks in the where clause to limit that, for example foo@other.tld would also trigger that query, in case you do not want that the easiest way would be to add a simple AND '%d' = 'domain.tld' to the where clause which would make sure it would never return any valid info unless the domain is correct.

So, once it gets passed through that map and foo@domain.tld DOES result in a good lookup postfix will now send the mail on to foo@php.domain.tld.

The second thing I did was really easy, setup a transport_maps entry that points to a transport which causes postfix to use a new transport, for example viaphp. To do that, all you have to do is make a file with:

php.domain.tld viaphp:

In it, call it for example transport, run postmap transport and then point to it via transport_maps in main.cf. This will cause postfix to use a non-standard transport for any mail going to the php.domain.tld domain, and all you have to do now is tell postfix what that transport does. Simple 2 lines at the end of master.cf are enough:

viaphp unix - n n - - pipe
  flags= user=nobody argv=/usr/bin/php /path/to/script.php ${sender} ${mailbox}

This needs to be on 2 lines and there needs to be whitespace at the beginning of the 2nd one!

Once thats all done, restart postfix to make it reread its config files and you are done.

Each mail addressed to an addy causing the sql query to return anything good will be sent to php.domain.tld and on to /path/to/script.php via a pipe. So in that script you will have $argv[1] as the sender, $argv[2] as the username of the recipient and of course simply use php://stdin to read the whole mail and get everything you need.

Posted by Nathan on November 2, 2006 at 11:39 PM in Coding | Permalink

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00d83445413953ef00d8356cb41169e2

Listed below are links to weblogs that reference Postfix To PHP:

Comments

Post a comment