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.

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:

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:

:0
$ARG

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:

EXTENSION
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:

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

:0
* ARG ?? ^^cvs-all^^|^^procmail|^^postgresql-advocacy^^
$ARG

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

:0
* ARG ?? ^^^^
!dan@things.example.org

:0
!dan+$ARG@things.example.org

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

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

philip.domain.com

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.

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.