Dan Smith wrote (his commenting octothorpes can double as citations),
# This file is designed to be used from the /etc/aliases file to
# filter mail destined for some other address. Typical usages would
# be as follows
# user: "| /path/to/procmail FILE=user FLAG=subject /this/file.rc"
# fwd: "| /path/to/procmail MAIL=fwd(_at_)host FLAG=discard /this/file.rc"
# prog: "| /path/to/procmail PIPE=/some/prog FLAG=header /this/file.rc"
One complication there is that the pipes will run as user "nobody" and the
original envelope recipient will be lost (that may not be a problem in the
"fwd" case, except that the downstream recipient may get
nobody(_at_)your(_dot_)site
as the From_ address). If you keep the original user with procmail's -d
option, procmail will disregard any command-line variable assignments.
Of course, I don't know whether the original recipient is significant to
/some/prog; perhaps that can run as "nobody" as well. After all, it is
handling mail for prog(_at_)your(_dot_)site, which is not a username.
And I may be totally wrong about that if /path/to/procmail is setuid
root, in which case the pipes may run with ruid=nobody and euid=owner of
/this/file.rc? I guess that's OS-dependent. Oh bother. Well, anyway,
back to Dan:
# The first option is [FILE|MAIL|PIPE], this determines what should be
# done with messages that aren't spam (or flaged as SPAM). The FLAG
# variable determines what would be done with detected SPAM
# subject - modify the Subject line to indicate SPAM was found
# discard - send the message to /dev/null
# header - add an X-This-Is-Spam: header to the message
You could use the -a option to pass "subject", "discard", or "header"
rather than the FLAG variable; that will survive the -d option.
This looks better to me as a way to set variables in the aliases file. Note
that the possibility that /some/prog will have options or arguments means we
have to reverse the order of the parameters from Dan's original plan:
user: "| /path/to/procmail -m /this/file.rc subject logname"
fwd: "| /path/to/procmail -m /this/file.rc discard fwd(_at_)host"
prog: "| /path/to/procmail -m /this/file.rc header /some/prog args"
Then /this/file.rc could have code like this:
IF_SPAM=$1 # subject, discard, or header
IF_KOSHER=$2 # local logname, remote address, or program without args
:0 # if it's a program, lose $1 so that "$@" will be what we need
* IF_KOSHER ?? ^^/
{ SHIFT=1 }
... and later, if spam detected
MATCH # unset it to start
:0h
* IF_SPAM ?? discard
/dev/null
:0Efwh
* IF_SPAM ?? header
| formail -A "X-This-Is-Spam: yessiree, Bob!"
:0Efwh # if set to "subject" make it work if there is a subject or not
* IF_SPAM ?? subject
* 1^0 ^Subject\/:.*
* 1^0
| formail -I"Subject: SPAM!$MATCH"
:0Efwh # otherwise
| formail -A "X-Spam-Handling: undefined"
... but if not detected as spam, we rely on $IF_KOSHER
:0 # remote address
* IF_KOSHER ?? [(_at_)!]
! $IF_KOSHER
:0E # local logname
* IF_KOSHER ?? ^^[^/]+^^
| /path/to/setuid_procmail -d $IF_KOSHER
# Conditions on the above may be made more stringent to be sure of matching
# acceptable patterns for local lognames. For example,
# * IF_KOSHER ?? ^^[a-z]\
# [0-9a-z][0-9a-z]?[0-9a-z]?[0-9a-z]?[0-9a-z]?[0-9a-z]?[0-9a-z]?^^
# or if you don't mind the fork,
# * ? grep ^$IF_KOSHER: /etc/passwd
# In such a case, you could even put the local logname test first, before
# the handling of remote addresses.
:0E # W perhaps? # to a program
* IF_KOSHER ?? ^^/
| "$@"
:0Efwh # IF_KOSHER is null or unset or improper.
| formail -A"X-Diagnostic: no handling specified for legitimate mail"
:0A # local lockfile if saved for, rather than forwarded to, the postmaster
! postmaster # or a folder for the postmaster writable by this process