Skip to content

Fudging multiple recipient_delimiter statements with postfix

Postfix supports the configuration item recipient_delimiter, like:

recipient_delimiter = +

so that one can do ‘plus-expansion’ style e-mail addresses, like: 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 (somebody thwap the guy who came up with that idea with a fish, please). There are lots of good well-done address verifiers which honor RFC 2822, specifically section 3.2.4, the Atom definition. E-mail addresses are very complex in structure, and you are not going to do a better job or save time by writing your own, so please use one of the canned libraries.

Anyway, long-story short, on those sites you often have to use a different character, a -, for example. However, postfix doesn’t let you use multiple recipient_delimiter statements, so what is one to do?

The answer is simply to break out postfix’s regexp support. If you have a virtual users table already in place (most do) you’ll have a statement like this:

virtual_alias_maps = hash:/etc/postfix/virtual

in your /etc/postfix/ file. Add an extra parameter to it, like so:

virtual_alias_maps = hash:/etc/postfix/virtual, regexp:/etc/postfix/virtual-regexp

Now, create a new file called /etc/postfix/virtual-regexp, and put a line in it like this:

/(.*)-(.*)                       ${1}+${2}

Piece by piece:
/ – start a regex match
(.*) – capture the first block of text up to
- – a - character, slash-escaped
(.*) – and now capture the rest of the text up to the
@ – the @ in the e-mail address – and then capture the rest of the address, which will be the domain
/ – and close the match.

The column on the right hand is the replacement which looks like:

${1} – insert the first capture
+ – and a + (we don’t need to escape now, we’re not in a regex)
${2} – and then the second capture
@ – and a @ – and then the domain name.

You get the idea. Save, and issue:

sudo postmap /etc/postfix/virtual-regexp
sudo postfix reload

and all incoming mails with a ‘-’ expansion will be re-written to a ‘+’ expansion. From there, postfix knows what to do.

You might be temped to use the expression:

/(.*)-(.*)@(.*)/     ${1}+${2}@${3}

but this will also be applied to outbound mail, so be careful. If anybody knows how to only apply the rule to domains listed in the virtual tables, please leave a comment!