Subject: | [PATCH] mail lost when pipe() command fails |
After porting a Mail::Audit script to Email::Filter, it failed like this:
#####
@400000003f1acdde3a806314 delivery 40512: success:
file_not_found:_preline_/usr/local/bin/tmda-filter_at_/usr/local/lib/perl5/site_perl/5.8.0/Email/Filter.pm_line_317/did_0+0+1
#####
What was happening was that Email::Filter was dying at point where
pipe() was called, returning something that looked like an success code.
Although the syntax for calling "pipe" appears not to have changed from
Mail::Audit, it quit working. From the documentation of IPC::Run, it
looks like multiple commands need to be given as an array. I tested, and
that works in my case:
$m->pipe(qw!preline /usr/local/bin/tmda-filter!);
Perhaps if a single string is given, you want to split on white space to
preserve backwards compatibility with Mail::Audit-style syntax. I do
find it more natural to give a single string as I would on the command
line.
At least, the documentation should be updated with an example of the
correct syntax to use with pipe().
The attached patch fixes the pipe bug by wrapping it in an eval. It
also fixes a bug in fail_badly()-- A "warn" was emitted after the call
to exit() and was thus never seen.
A patch to the test script to test the pipe() fix will also be attached.
Perhaps there are other cases where external modules are depended on
that should also be "eval'ed" to catch this kind of failure.
--- /usr/local/lib/perl5/site_perl/5.8.0/Email/Filter.pm Sun Jul 20 11:53:57 2003
+++ Email-Filter-1.0/lib/Email/Filter.pm Sun Jul 20 13:44:41 2003
@@ -78,9 +78,8 @@
sub fail_badly {
my $self = shift;
$self->{giveup} = 1; # Don't get caught by DESTROY
+ warn "Message ".$self->simple->header("Message-ID"). "was never handled properly\n";
exit TEMPFAIL unless $self->{noexit};
- warn "Message ".$self->simple->header("Message-ID").
- "was never handled properly\n";
}
sub fail_gracefully {
@@ -314,12 +313,18 @@
my $stdout;
my $string = $self->simple->as_string;
$self->call_trigger("pipe");
- if (run(\@program, \$string, \$stdout)) {
+
+ my $rv;
+ eval{$rv = run(\@program, \$string, \$stdout)};
+
+ if (!$@ and $rv) {
$self->done_ok;
return $stdout;
}
- $self->fail_gracefully() unless $self->{noexit};
- return;
+ else {
+ $self->fail_gracefully() unless $self->{noexit};
+ return;
+ }
}
=head1 COPYRIGHT