Simulating multiple recipient delimiters ($recipient_delimiter) with postfix and mysql/postfixadmin virtual domains

As clearly exposed by Bill McGonigle :

Postfix supports the configuration item recipient_delimiter, like:

recipient_delimiter = +

so that one can do ‘plus-expansion’ style e-mail addresses, like: mike+amazon@bfccomputing.com for myriad reasons, like tracking, spam filtering, auto-sorting, etc. Unfortunately, while + has long been the standard character for this purpose, half of the websites out there have been written by noodle-heads who figure that any incoming + character in a parameter is a faux-encoded space character

Or at least do they simply reject any e-mail address containing the + character.

It would be fairly straightforward to just change the parameter in postfix, but as I'm using this scheme for few years now, I'm kind of reluctant to change all previous subscriptions and I also use DSPAM which recipient delimiter character can't be changed !

In his post Bill McGonigle explains how to use a regexp virtual alias map to rewrite any character into the + character and so simulating the acceptance by Postfix of multiple recipient delimiters. The problem with this solution is that for each virtual domain hosted there has to be a line in the said virtual alias map ; kind of boring when the virtual domains are stored in a SQL database via a Postfixadmin portal.

The solution I found lies in the following MySQL query which will replace (in this case) the _ character by a + character in the recipient part of the address

select concat(replace(left('%s', length('%s') - instr(reverse('%s'), '@')), '_', '+'), '@', reverse(substring_index(reverse('%s'), '@', 1))) "goto" from domain where domain = reverse(substring_index(reverse('%s'), '@', 1)) and active = 1 and instr(left('%s', length('%s') - instr(reverse('%s'), '@')), '_') > 0

This query might neither be very elegant nor quite optimal but it works.

In context, create a file named mysql_multi_recipient_delimiter.cf in your postfix config folder containing :

user = <mysql_user>
password = <mysql_password>
hosts = <mysql_host_or_localhost>
dbname = <mysql_database_name>
query = select concat(replace(left('%s', length('%s') - instr(reverse('%s'), '@')), '_', '+'), '@', reverse(substring_index(reverse('%s'), '@', 1))) "goto" from domain where domain = reverse(substring_index(reverse('%s'), '@', 1)) and active = 1 and instr(left('%s', length('%s') - instr(reverse('%s'), '@')), '_') > 0

And in main.cf, modify the line :

virtual_alias_maps = proxy:mysql:$config_directory/mysql_virtual_alias_maps.cf

to :

virtual_alias_maps = proxy:mysql:$config_directory/mysql_virtual_alias_maps.cf proxy:mysql:$config_directory/mysql_multi_recipient_delimiter.cf

Reload postfix :

postfix reload

et voilà !

La discussion continue ailleurs

URL de rétrolien : http://www.ploup.net/nazgullien/trackback/30

Fil des commentaires de ce billet