Stoffe has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I've been trying to use Mail-Qmail-Queue to introduce a simple filter on our Qmail server. The idea is to replace the qmail-queue program, check and potentially modify the message and then call the original qmail-queue. This is apprently the approach of qmail-scanner and other programs, but I've not found any that seemes easy to adapt for our own purposes, but the Mail-Qmail-Queue package seemed it would do exactly the right thing.

Below is a really minimal example, without die clauses and other stuff I do have. If I replace qmail-queue with this program, and have a copy of the original still there as qmail-queue.old, it will be able to read and parse the message, but when I try to send it on, changed or not, it just disappears somewhere - the send call doesn't return anything or even dies in a way I've been able to catch. The only clue I've got is that if I send from Squirrelmail, something on the way apparently complains about write errors. asking if disk may be full (it isn't, and sending with original program works fine).

#!/usr/bin/perl use warnings; use strict; use Mail::Qmail::Queue::Message; # This works, message available my $msg = Mail::Qmail::Queue::Message->receive(); # This never returns... at all $ret_val = $msg->send(QmailQueue => '/var/qmail/bin/qmail-queue.old')

The machine is running Debian Sarge, Qmail 1.03-31.01 and it all works fine otherwise.

Any ideas, can it be fixed? Any tips appreciated, including pointers to other possible solutions. Thanks!

Replies are listed 'Best First'.
Re: Mail-Qmail-Queue can't (re)send message
by almut (Canon) on Feb 13, 2007 at 21:35 UTC
    the send call doesn't return anything or even dies in a way I've been able to catch

    Hm, it's hard to image that your script just disappears without a trace. Actually, I'd expect qmail to somehow check and report the status of invoking qmail-queue. Also, when you look in the sources of Mail/Qmail/Queue/Send.pm, there's plenty of error handling that would cause the program to die/carp with some helpful messages. But the question probably is "where do they end up?" :)

    Have you checked the syslog and any qmail specific logfiles? (not exactly sure where they're kept (probably /var/log/qmail/* or /var/log/qmail.log) -- I'm not using qmail myself, and as qmail is in "non-free", there's no readily downloadable .deb package to check...)

    If you absolutely can't find where the error messages are ending up, it might be easier to just dump them another time to a place where you'll actually look, e.g. somewhere in /tmp/ . In Mail/Qmail/Queue/Error.pm there's a routine _fail which seems to be called eventually for every error. So, you could insert a bit of debugging code in there

    sub _fail(@) { ### DEBUG if (open my $log, ">>", "/tmp/qmail-queue.log") { print $log "@_\n"; # or something like this close $log; } else { # writing another error message to nowhere if # this fails would be mostly useless... } ### my $default_ec = shift; ... }

    Otherwise, if this also isn't going to lead you to enlightenment, you could try strace(1) as a last resort. Either write a wrapper for your script which runs it under strace (this is the easy way, but it would likely produce lots of unnecessary output), or fork/exec strace in the background from within your script (attaching it to the PID of the script), immediately before you call $msg->send(...). (If you want help with the latter approach, just report back...)

    Good luck!

      Thank you - you're right, of course, that it's very unlikely it actually disappears without a trace, even with forks and execs. :) I've been checking every logfile I could find and even been rgrepping through other possible locations without any result. I do find qmail logs, but nothing from this.

      However, the idea to insert debugging code into _fail did give a result:

      81 53 Error closing write pipe: Broken pipe

      Reading up further on the source in Send.pm, this message comes from after the body is written and the pipe is supposed to be closed to signal that it's time for the next pipe, the envelope, to be written. The closing is what fails, or at least triggers the fail in the script.

      Now this is sadly where I'm stumped again. I do not really know how to proceed from here, I don't really know anough about this kind of communication to see why this may be...