Apr 112003

Using foo+bar@ email addresses with Postfix and procmail

Mail addresses can be expressed as localpart@example.org. The key point of this article is that the localpart is indeed local. This provides a wide array of possibilities. I will explore just one of those possibilities.

Address extensions have been around for some time. They are a conceptual entity and are not actually defined in any RFC. Convention dictates what an address extension is and how it is used. Let us use foo+bar@example.org as our primary example. The user name in this example is foo. The extension part is bar and can be used for variety of purposes, but the most common usage is folder delivery. It is important to note that the delimiter can be anything you want. That is because delivery is a local matter. We can do whatever we want. Common delimiters include ‘+’ and ‘-‘. I have chosen to use ‘+’. Postfix allows you to set this value using the recipient_delimiter setting.

For reference, the following may be useful:

Yeah, well, why bother?

Why am I doing this? Why bother with address extensions? The answer is simple: because it makes life easier.

In this particular case, I am setting up a new development box for FreshPorts and FreshSource. This box is much faster than the existing environment. It will contain a development, a test, and a beta environment. I will want cvs-all messages going to each of those databases. I do this by sending the messages to dan+dev, dan+test, and dan+beta respectively[1]. I use procmail to process the incoming mail. This is very useful as it allows me to process the mail into the appropriate FreshPorts database. Without this ability, I would resort to different users for each database. Having just one user (me!) makes this all very easy and simple.

[1] – no, I don’t have three subscriptions to the cvs-all mailing list. I have one. I use local aliases to copy that single message to three local addresses.

What’s in it for me?

You might be asking that question now. Let me give you an example. Let’s guess that you are subscribed to three different mailing lists. It’s nice to keep all the messages for a particular list in a separate folder. There are many different ways to do this. I will not list them. Let’s assume all the mailing lists have nothing in common and therefore you need three different entries such as these:

* ^Sender: owner-cvs-all@FreeBSD.ORG

* ^Sender: Sender: procmail-bounces@lists.RWTH-Aachen.DE

* ^Sender: pgsql-advocacy-owner@postgresql.org
Worse still, there is nothing in the mailing list email messages which is easy to identify. Rather than check To:, From:, and possible CC:, you can avoid all this by adding your very own key; your subscription address. Let’s assume I subscribe to the above lists using the following email addresses:
  • dan+cvs-all@example.org
  • dan+procmail@example.org
  • dan+postgresql-advocacy@example.org
If you did that, then your procmail recipe becomes:
where ARG is the address extension.

But how do you get that extension? Postfix to the rescue!

Address extensions with Postfix

The Postfix MTA supplies many environment variables when local delivery is being performed. man 8 local contains the information you need. Specifically, this extract from the EXTERNAL COMMAND DELIVERY section:

       The optional recipient address extension.
This variable is available to you within your ~/.forward script, which is the normal method for invoking procmail. Here is what I’m using:
"|exec /usr/local/bin/procmail -t -a ${EXTENSION}"

Read man procmail for more information. on these options.

  • -t instructs procmail to fail softly.
  • -a specifies an argument (in this case, the address extension).
In case anyone is wondering, I looked at using Procmail for system-wide local delivery but decided against it. Although I am the only user on this system, I didn’t want to invoke procmail for every single email delivery.

See also the man page section titled ADDRESS EXTENSION where it documents that ~name/.forward+foo is tried first, by default. This setting can be changed via the forward_path setting (see sample-local.cf for an example).

The new procmail recipe

Here is how to use the address extension (as supplied by Postfix) within procmail. I found this gem in the procmail tips.

ARG = $1

* ARG ?? ^^cvs-all^^|^^procmail|^^postgresql-advocacy^^
The address extension is passed in as $1 by the .forward script. You can add more parameters to .forward as needed. The first is always $1, the second will be $2, etc. You cannot access this variable directly and you must assign it to a variable.

Passing the extension along

Sometimes you need to forward an email and include the extension you were given. This recipe does that:

ARG = $1

* ARG ?? ^^^^


^^^^ represents an empty string. In this case, we do not include an extension.

Other references

I found Procmail Quick Reference Guide useful when devising my recipes.

The last word

My thanks to those on the procmail and Postfix mailing lists for pointing me in the right direction.

  2 Responses to “Using foo+bar@ email addresses with Postfix and procmail”

  1. Hi –
    I use this a lot when signing up on online forms, but sometimes their validation process won’t allow a "+" in the email address. If you have your own domain you can setup say "philip.domain.com" and make it so that *anything* sent to that domain actually goes to philip@domain.com.

    Once you’ve setup the domain and the mx records in DNS, under sendmail you’d add the following line to /etc/mail/local-host-names


    and to /etc/mail/virtusertable:

    @philip.domain.com philip

    Then run make in that directory and you can now send to literally any address @philip.comain.com.

    Just another way to do the same thing really.

  2. I have used mailagent as long as I can remember, and wanted to support this type of addressing method. I came up with this rule which handles these types of addresses in a general case:

    To Cc:
    /jlp\+([^@]+)\@/i { TR 1 /A-Z/a-z/; SAVE +plus/%1 }

    (Note that I save directly to MH folders… mailagent supports saving to MH folders directly and updates the "unseen" sequence without having to resort to calling rcvstore.)

    I, too, use this primarily for sites that want an e-mail address. Since I want to find out who sells my e-mail address, I try to use a descriptive key after the "+". Then, when spam shows up in a particular folder, I know what company is to blame.

    Unfortunately, I have also found several web-based forms that prohibit the "+" character in the local part (in violation of the RFC). On occasion, when I really want the information the site has, I’ve had to resort to disabling javascript while filling out and submitting the form. I also usually send a "feedback" via some mechanism provided on the site. I’ve never had any luck getting them to change it, though, or even respond to me.