Based on Hanno's feedback, I made the spool_dir code only warn() if the directory is other than 0700. I also made the base temp_dir() sub take a permission octal, but the Qpsmtpd::Plugin version remains unchanged. My reasoning is that most people won't care, and the existing version is safer (and it cleans up for you). However, if you really need more control, you can do what you want...
John
=== lib/Qpsmtpd/Plugin.pm
==================================================================
--- lib/Qpsmtpd/Plugin.pm (revision 488)
+++ lib/Qpsmtpd/Plugin.pm (local)
@@ -53,6 +53,20 @@
shift->qp->connection;
}
+sub temp_file {
+ my $self = shift;
+ my $tempfile = $self->qp->temp_file;
+ push @{$self->transaction->{_temp_files}}, $tempfile;
+ return $tempfile;
+}
+
+sub temp_dir {
+ my $self = shift;
+ my $tempdir = $self->qp->temp_dir();
+ push @{$self->transaction->{_temp_dirs}}, $tempdir;
+ return $tempdir;
+}
+
# plugin inheritance:
# usage:
# sub register {
=== lib/Qpsmtpd/Transaction.pm
==================================================================
--- lib/Qpsmtpd/Transaction.pm (revision 488)
+++ lib/Qpsmtpd/Transaction.pm (local)
@@ -7,10 +7,6 @@
use IO::File qw(O_RDWR O_CREAT);
-# For unique filenames. We write to a local tmp dir so we don't need
-# to make them unpredictable.
-my $transaction_counter = 0;
-
sub new { start(@_) }
sub start {
@@ -71,23 +67,7 @@
my $self = shift;
my $data = shift;
unless ($self->{_body_file}) {
- my $spool_dir = $self->config('spool_dir') ? $self->config('spool_dir')
- :
Qpsmtpd::Utils::tildeexp('~/tmp/');
-
- $spool_dir .= "/" unless ($spool_dir =~ m!/$!);
-
- $spool_dir =~ /^(.+)$/ or die "spool_dir not configured properly";
- $spool_dir = $1;
- $self->{_spool_dir} = $spool_dir;
-
- if (-e $spool_dir) {
- my $mode = (stat($spool_dir))[2];
- die "Permissions on spool_dir $spool_dir are not 0700" if $mode & 07077;
- }
-
- -d $spool_dir or mkdir($spool_dir, 0700) or die "Could not create
spool_dir $spool_dir: $!";
- $self->{_filename} = $spool_dir . join(":", time, $$,
$transaction_counter++);
- $self->{_filename} =~ tr!A-Za-z0-9:/_-!!cd;
+ $self->{_filename} = $self->temp_file();
$self->{_body_file} = IO::File->new($self->{_filename}, O_RDWR|O_CREAT,
0600)
or die "Could not open file $self->{_filename} - $! "; # .
$self->{_body_file}->error;
}
@@ -130,6 +110,25 @@
if ($self->{_filename} and -e $self->{_filename}) {
unlink $self->{_filename} or $self->log(LOGERROR, "Could not unlink ",
$self->{_filename}, ": $!");
}
+
+ # These may not exist
+ if ( $self->{_temp_files} ) {
+ $self->log(LOGDEBUG, "Cleaning up temporary transaction files");
+ foreach my $file ( @{$self->{_temp_files}} ) {
+ next unless -e $file;
+ unlink $file or $self->log(LOGERROR,
+ "Could not unlink temporary file", $file, ": $!");
+ }
+ }
+ # Ditto
+ if ( $self->{_temp_dirs} ) {
+ eval {use File::Path};
+ $self->log(LOGDEBUG, "Cleaning up temporary directories");
+ foreach my $dir ( @{$self->{_temp_dirs}} ) {
+ rmtree($dir) or $self->log(LOGERROR,
+ "Could not unlink temporary dir", $dir, ": $!");
+ }
+ }
}
=== lib/Qpsmtpd.pm
==================================================================
--- lib/Qpsmtpd.pm (revision 488)
+++ lib/Qpsmtpd.pm (local)
@@ -255,4 +255,52 @@
}
}
+sub spool_dir {
+ my $self = shift;
+
+ unless ( $self->{_spool_dir} ) { # first time through
+ my $spool_dir = $self->config('spool_dir')
+ || Qpsmtpd::Utils::tildeexp('~/tmp/');
+
+ $spool_dir .= "/" unless ($spool_dir =~ m!/$!);
+
+ $spool_dir =~ /^(.+)$/ or die "spool_dir not configured properly";
+ $spool_dir = $1; # cleanse the taint
+ $self->{_spool_dir} = $spool_dir;
+
+ # Make sure the spool dir has appropriate rights
+ if (-e $spool_dir) {
+ my $mode = (stat($spool_dir))[2];
+ warn "Permissions on spool_dir $spool_dir are not 0700" if $mode & 07077;
+ }
+
+ # And finally, create it if it doesn't already exist
+ -d $spool_dir or mkdir($spool_dir, 0700)
+ or die "Could not create spool_dir $spool_dir: $!";
+ }
+
+ return $self->{_spool_dir};
+}
+
+# For unique filenames. We write to a local tmp dir so we don't need
+# to make them unpredictable.
+my $transaction_counter = 0;
+
+sub temp_file {
+ my $self = shift;
+ my $filename = $self->spool_dir()
+ . join(":", time, $$, $transaction_counter++);
+ $filename =~ tr!A-Za-z0-9:/_-!!cd;
+ return $filename;
+}
+
+sub temp_dir {
+ my $self = shift;
+ my $mask = shift || 0700;
+ my $dirname = $self->temp_file();
+ -d $dirname or mkdir($dirname, $mask)
+ or die "Could not create temporary directory $dirname: $!";
+ return $dirname;
+}
+
1;
