This is a documentation bug that has bugged me for a long time, until
eventually I have tried to read very carefully the man pages and
documentation, examples and network faqs, and have decided to write
this.
Please note that not only would I like to find an answer to my
questions, to some but not all of which I know the response, but mainly
I would like to stimulate the maintainers to complete and clarify the
manual, by writing or clarifying the necessary information, and by
adding ad hoc examples.
The problem is that I cannot determine whether a given recipe is
delivering or not. From the procmailrc man page:
----------------
There are two kinds of recipes: delivering and non-delivering recipes.
[...]
Delivering recipes are those that cause header and/or body of the mail
to be: written into a file, absorbed by a program or forwarded to a
mailaddress.
Non-delivering recipes are: those that cause the output of a program or
filter to be captured back by procmail or those that start a nesting
block.
----------------
Once one understands what "delivering recipe" means, the two definitions
above are not sufficient. That is, they are definitions of the meaning
of the word, but they say little about whether a given action is
delivering. For example, it is clear that a file action is a delivery
one, and that a mail action is a delivery one. The big problem is that
IT IS NOT CLEAR WHETHER A PIPE ACTION IS A DELIVERING ONE.
For example, in the following recipe, taken from the procmailex man
page:
:0 h # alternate method
KEYWORDS=| formail -xKeywords:
it is not clear whether the pipe action is delivering or not. Is the
header of the mail "absorbed" into the program or "captured back" by
procmail? How can I tell?
Same doubt for the following, again from procmailex:
:0 Bb
* ^^%!
| lpr
From this in procmailex I deduce that pipe actions are delivering:
to weed out duplicate mails. Simply put the following recipe at the
top of your rcfile, and no duplicate mail will get past it.
:0 Wh: msgid.lock
| formail -D 8192 msgid.cache
But then, again in procmailex, I read that the two following are
equivalent:
FROM=`formail -rt -xTo:`
:0 h
FROM=| formail -rt -xTo:
Since the first one is obviously non delivering, I understand that the
second one is non-delivering too. So pipes are non delivering. Or not?
Does it make a difference if their output is captured in a variable?
On the same line, it is not clear what the "f" flag means. The manual
says:
f Consider the pipe as a filter.
I suppose that this means: make the following pipe action into a
non-delivering action, and continue processing using the output of the
program. This is consistent with my experience using procmail, but it
is not written anywhere.
If this interpretation was correct, it would also imply that pipe
actions are normally delivering, and you must use "f" to make them non
delivering and capture their output.
Nor it is clear what the "w" flag means. The manual says:
w Wait for the filter or program to finish and check its exitcode
(normally ignored); if the filter is unsuccessful, then the text
will not have been filtered.
First, it makes a distinction between a filter and a program in the
first half of the sentence. What is a filter? Is a program where the
"f" flag is used? Is it something else?
Second, it only speaks about a filter (no program any more) in the
second part of the sentence.
Third, it says that procmail understands that the text is not filtered
with a bad exit code. What then? What does procmail do when the text
has not been filtered?
Next, if I put a "wc" flag on a pipe action captured into a variable,
procmail says that it ignores the extraneous "c". Does this mean that
"w" implies "c" in this case? If yes, it is not written anywhere. And
moreover, why ever is the "w" tolerated? Shouldn't it be redundant?
The "i" flag is even more obscure:
i Ignore any write errors on this recipe (i.e., usually due to an
early closed pipe).
What means that procmail ignores the error? What then? Is the output
so far ignored or not? Is the recipe delivering or not? What if the
errorr is not ignored?
About the variable=| construct, is it delivering or not?
Hello.
I've received the following report from the debian bug system:
Package: procmail
Version: 3.22-4
Severity: wishlist
This is a documentation bug that has bugged me for a long time, until
eventually I have tried to read very carefully the man pages and
documentation, examples and network faqs, and have decided to write
this.
Please note that not only would I like to find an answer to my
questions, to some but not all of which I know the response, but mainly
I would like to stimulate the maintainers to complete and clarify the
manual, by writing or clarifying the necessary information, and by
adding ad hoc examples.
The problem is that I cannot determine whether a given recipe is
delivering or not. From the procmailrc man page:
----------------
There are two kinds of recipes: delivering and non-delivering recipes.
[...]
Delivering recipes are those that cause header and/or body of the mail
to be: written into a file, absorbed by a program or forwarded to a
mailaddress.
Non-delivering recipes are: those that cause the output of a program or
filter to be captured back by procmail or those that start a nesting
block.
----------------
Once one understands what "delivering recipe" means, the two definitions
above are not sufficient. That is, they are definitions of the meaning
of the word, but they say little about whether a given action is
delivering. For example, it is clear that a file action is a delivery
one, and that a mail action is a delivery one. The big problem is that
IT IS NOT CLEAR WHETHER A PIPE ACTION IS A DELIVERING ONE.
For example, in the following recipe, taken from the procmailex man
page:
:0 h # alternate method
KEYWORDS=| formail -xKeywords:
it is not clear whether the pipe action is delivering or not. Is the
header of the mail "absorbed" into the program or "captured back" by
procmail? How can I tell?
Same doubt for the following, again from procmailex:
:0 Bb
* ^^%!
| lpr
top of your rcfile, and no duplicate mail will get past it.
:0 Wh: msgid.lock
| formail -D 8192 msgid.cache
But then, again in procmailex, I read that the two following are
equivalent:
FROM=`formail -rt -xTo:`
:0 h
FROM=| formail -rt -xTo:
Since the first one is obviously non delivering, I understand that the
second one is non-delivering too. So pipes are non delivering. Or not?
Does it make a difference if their output is captured in a variable?
On the same line, it is not clear what the "f" flag means. The manual
says:
f Consider the pipe as a filter.
I suppose that this means: make the following pipe action into a
non-delivering action, and continue processing using the output of the
program. This is consistent with my experience using procmail, but it
is not written anywhere.
If this interpretation was correct, it would also imply that pipe
actions are normally delivering, and you must use "f" to make them non
delivering and capture their output.
Nor it is clear what the "w" flag means. The manual says:
w Wait for the filter or program to finish and check its exitcode
(normally ignored); if the filter is unsuccessful, then the text
will not have been filtered.
First, it makes a distinction between a filter and a program in the
first half of the sentence. What is a filter? Is a program where the
"f" flag is used? Is it something else?
Second, it only speaks about a filter (no program any more) in the
second part of the sentence.
Third, it says that procmail understands that the text is not filtered
with a bad exit code. What then? What does procmail do when the text
has not been filtered?
Next, if I put a "wc" flag on a pipe action captured into a variable,
procmail says that it ignores the extraneous "c". Does this mean that
"w" implies "c" in this case? If yes, it is not written anywhere. And
moreover, why ever is the "w" tolerated? Shouldn't it be redundant?
The "i" flag is even more obscure:
i Ignore any write errors on this recipe (i.e., usually due to an
early closed pipe).
What means that procmail ignores the error? What then? Is the output
so far ignored or not? Is the recipe delivering or not? What if the
errorr is not ignored?
About the variable=| construct, is it delivering or not?
Santiago Vila <sanvila@unex.es> forwarded:
...
Part of the problem is that what is clear and complete to us is not
the same as what is clear and complete to someone who hasn't used it
for years. Your comments are helpful in pinpointing the areas that are
particularly unclear. Feel free to suggest particular textual changes
once you feel you have a grasp on the semantics of procmail.
It depends on whether the program's output is being captured by procmail.
If yes, then the non-delivering description applies. If not, then the
delivering description applies.
procmailrc(5) says:
Recipe action line
The action line can start with the following characters:
...
| Starts the specified program, possibly in $SHELL if
any of the characters $SHELLMETAS are spotted. You
can optionally prepend this pipe symbol with vari-
able=, which will cause stdout of the program to be
captured in the environment variable (procmail will
not terminate processing the rcfile at this point).
That action has prepended the '|' with KEYWORDS=, so procmail is
capturing the output and the recipe is not delivering. Indeed, that
paragraph explictly mentions that procmail will not terminate, so the
recipe cannot be delivering.
Is the output being captured? No, so it's a delivering recipe.
...
Yes. That's part of what the "captured back by procmail" part of the
definition of a non-delivering recipe is referring to. The other part
is of course filtering recipes.
I agree that sentence needs to say more.
That seems to confuse the purpose of the 'f' flag. If you want to use a
program to modify a message header, body, or both, continuing processing
with the modified results, you use the 'f' flag. If you just want to
feed a message to a program without terminating processing, you use the
'c' flag to effectively feed a copy of the message to the program.
Using the 'f' flag where you wanted the effect of the 'c' flag will
generally result in the rest of the rcfile seeing a message that consists
of just a newline.
a filter.
That's because in a non-filtering program action, the message isn't
being modified. That clause just tells you that if the filter fails,
procmail will retain the original version of the message instead of
using the (presumably incomplete) output of the filter.
No, the 'c' is extraneous because it's a variable capture recipe.
The description of the 'c' flag explictly says that it only makes sense
on delivering recipes and on a nesting block recipe. You should have
gotten that warning whether or not you included a 'w' flag on it.
By default, if a program in a '|' action fails to read all its input
such that procmail gets an error writing to the pipe, procmail will
consider the action to have failed. Procmail will not terminate but
go on to the next recipe. Whether an action has suceeded or failed is
testable using the 'a' or 'e' flag on the succeeding recipe.
The 'i' flag simply tells procmail to ignore whether it got any write
errors when determining whether the action succeeded or failed. It has
no effect on whether the recipe is delivering.
Philip Guenther
Procmail Maintainer
This clarifies the definition a little. But it is still part of the
definition. What I need is, for each possible action, knowing whether
that is a delivering action or not. In the listing of actions in
procmailrc, the first thing to be written should be: "Name: a delivering
action" or "Name: a not-delivering action".
Yes, I came to understand what you are explaining, after reading many
times the documentation and examples, and after some experiments. And
after all that, I also understood that's logic and well though out. The
fact is, this is a central point, and should always be clearly stated.
The implications you mention are not obvious at all. That paragraph
should read like this:
| Pipe: a program delivering action. Starts the specified
program, possibly in $SHELL if any of the characters
$SHELLMETAS are spotted. The standard input of the program is
fed with the body or the headers of the mail message being
processed, depending on the flags used for the recipe. If
procmail detects an error while writing on the pipe (usually a
broken pipe), the action is ignored and procmail continues
with the next recipe.
VAR=| Var-pipe: a program non-delivering action. The behaviour is
the same as with the previous action, but the standard output
of the program is captured in the environment variable, and
procmail continues processing a copy of the message.
In the procmailex example sited above, there should be a line saying:
Since this is a non-delivering action, procmail continues processing a
copy of the message.
Yes, but this is not written explicitely anywhere, it must be deducted
as a consequence of many different sparse observations. Instead, a line
should be added right after the example (this is true of all examples)
saying:
This is a delivering recipe. Procmail feeds the message to the
program, then stopsprocessing, without waiting for it to complete.
Something like that:
f Filter: applies exclusively to pipe actions. It turns a pipe
action into a filter action, a program non-delivering action
after which procmail continues processing a modified copy of
the message, instead of the original copy as usual. The
modified part is the header or body, depending on other flags
used in the action.
Okay, I'll try to rewrite this:
w Wait: applies exclusively to filter actions (see filter flag).
Do not process the output of the filter program as soon as it
is produced. Rather, wait for the filter program to finish,
and use its output only if the exit code is successful. If it
is not, discard the output, write an error message on standard
error and continue processing a copy of the original message.
i Ignore: applies only to program actions. Errors detected by
procmail while writing on the pipe (usually a broken pipe) are
completely ignored.