#!/usr/bin/perl
#-----------------------------------------------------------------------------
#
#  POPular -- A POP3 server and proxy for large mail systems
#
#  $Id: expire,v 1.3 2001/02/09 15:59:07 sqrt Exp $
#
#  http://www.remote.org/jochen/mail/popular/
#
#-----------------------------------------------------------------------------
#
#  Expire for mailboxes.
#
#-----------------------------------------------------------------------------
#
#  Copyright (C) 1999-2001  Jochen Topf <jochen@remote.org>
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
#
#-----------------------------------------------------------------------------

use strict;

my $POPDIR    = "/pop";		# Directory where all the mailboxes are
my $DEBUG     = 1;		# Debug output

# Expiretime (in days) for each namespace. There must be a special "namespace"
# called "OLD", which contains the expire time for deleted mailboxes.
my %expire = ("OLD", 30,	# 1 month
              "example", 190);	# 6 month + grace period

#-----------------------------------------------------------------------------

my $time = time();

# Depending on the directory layout, you have to change this. This calls
# scandir($dir) for every directory where there are mailboxes. This version
# uses a two-level directory hierarchy like this: 1/23/mailboxname=namespace/
foreach my $h (0x0 .. 0xf) {
  foreach my $d (0x00 .. 0xff) {
    my $dir = sprintf("%x/%02x", $h, $d);
    print STDERR "$dir\n" if ($DEBUG);
    scandir($dir);
  }
}

exit 0;


#-----------------------------------------------------------------------------
#
#  scandir($dir)
#
#  Changes current directory into $dir, scans it for mailbox dirs, and calls
#  expiremailbox() for each.
#
#-----------------------------------------------------------------------------
sub scandir {
  my ($dir) = @_;
  my ($name, $ns, $expire);

  chdir("$POPDIR/$dir") or die("Can't chdir to $POPDIR/$dir: $!\n");

  # read directory, skip dot-files
  opendir(DIR, ".") or die("Can't scan dir $dir: $!\n");
  my @files = grep(!/^\./, readdir(DIR));
  closedir(DIR);

  foreach my $file (@files) {
    if ($file =~ /_\d{8}\.\d{6}$/) {
      $ns = "OLD";
    } else {
      ($name, $ns) = split(/=/, $file);
    }
    if ($expire{$ns}) {
      $expire = $expire{$ns};
    } else {
      print STDERR "No expire for namespace of mailbox $file\n";
    }
    print "$dir/$file ($ns, $expire)\n" if ($DEBUG);
    expiremailbox($file, $ns, $expire * 60 * 60 * 24);
  }
}


#-----------------------------------------------------------------------------
#
#  expiremailbox($mailbox, $ns, $expire)
#
#  Expire all mails in mailbox $mailbox if they are older then $expire
#  seconds. $ns is the namespace or 'OLD' if the mailbox is deleted.
#
#-----------------------------------------------------------------------------
sub expiremailbox {
  my ($mailbox, $ns, $expire) = @_;

  opendir(DIR, "$mailbox/cur") or die("Can't opendir $mailbox/cur: $!\n");
  my @cur = grep(!/^\./, readdir(DIR));
  closedir(DIR);
   
  opendir(DIR, "$mailbox/new") or die("Can't opendir $mailbox/new: $!\n");
  my @new = grep(!/^\./, readdir(DIR));
  closedir(DIR);

  # Delete old mailboxes if they are empty
  if ($ns eq "OLD" && $#cur == -1 && $#new == -1) {
    rmdir("$mailbox/new") or print STDERR "Can't rmdir $mailbox/new: $!\n";
    rmdir("$mailbox/cur") or print STDERR "Can't rmdir $mailbox/cur: $!\n";
    rmdir("$mailbox/tmp") or print STDERR "Can't rmdir $mailbox/tmp: $!\n";
    rmdir("$mailbox")     or print STDERR "Can't rmdir $mailbox: $!\n";
    return;
  }

  # Now the old files are expired. All files with a name beginning with
  # "0QUOTA" are deleted, too. They are created by the "checksize" script
  # and contain a mail to warn the user, that his quota is exceeded or nearly
  # exceeded. A new "0QUOTA" mail is created each night, so we can just delete
  # it here.
  foreach my $file (@cur) {
    if ($file =~ /^0QUOTA/) {
      unlink("$mailbox/cur/$file")
    } else {
      expirefile("$mailbox/cur/$file", $expire);
    }
  }

  foreach my $file (@new) {
    if ($file =~ /^0QUOTA/) {
      unlink("$mailbox/new/$file")
    } else {
      expirefile("$mailbox/new/$file", $expire);
    }
  }
}


#-----------------------------------------------------------------------------
#
#  expirefile($file, $expire)
#
#  Unlink file $file if it is older then $expire seconds.
#
#-----------------------------------------------------------------------------
sub expirefile {
  my ($file, $expire) = @_;

  my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
	$blksize,$blocks) = stat($file);

  if ($time - $mtime > $expire) {
    unlink($file) or print STDERR "Can't unlink $file: $!\n";
    print " $file (", $time - $mtime, " $expire) EXPIRE\n" if ($DEBUG);
  }
}


#-- THE END ------------------------------------------------------------------


syntax highlighted by Code2HTML, v. 0.9.1