• Fudging multiple recipient_delimiter statements with postfix

    by  • 2007/11/07 • Uncategorized

    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 (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/main.cf 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:

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

    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
    example.com – 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 @
    example.com – 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!