=== lib/Qpsmtpd/Plugin.pm
==================================================================
--- lib/Qpsmtpd/Plugin.pm  (revision 485)
+++ 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 485)
+++ 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 485)
+++ lib/Qpsmtpd.pm  (local)
@@ -255,4 +255,51 @@
   }
 }
 
+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];
+      die "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 $dirname = $self->temp_file();
+  -d $dirname or mkdir($dirname, 0700)
+    or die "Could not create temporary directory $dirname: $!";
+  return $dirname;
+}
+
 1;
