On Wed, 14 Nov 2007, Matt wrote:
[...]
For what it's worth, I'd look at the newest message in the ./cur folder,
rather than the oldest in the ./new. (You want the last time the user
But most of my user POP3 and do not leave messages on server. I just
check if there is a message over 6 months old in new.
Even in POP3, dovecot moves RETR'ieved messages into ./cur as soon as
they're read, thus changing its timestamp.
[...]
But, the benefit is that you can get the timestamp for the last time the
user read/deleted a message in ./cur simply by checking the change time of
the ./cur directory. (rather than going through all its files)
Light bulb. Wish I had thought of that.
:-)
[...]
Should make it fast enough to run in cron.hourly, depending on your number
of users/mailboxes.
I am going to have to try this. I used find with -mtime to find all
messages over 6 months old in all the ./new directorys. If this way
works it would be far more efficient.
A flaw though. If the account is checked daily but never receives any
new mail (such as the email account that goes to my fax machine and I
am sure there are a few others) the ctime on the cur will not be
updated. It would not automagically start working again either since
it cannot receive new messages when suspended and thus cannot update
./cur. Someone just might email my fax machine some day rather then
call.
This might be a good preliminary check then only then double check
that there are messages in ./new. Of course it makes my simple perl
script a little more involved. Is there a low overhead way to check
that ./new is not empty?
Yes, that's definitely a case I didn't consider. Here's how I'd implement
an empty-directory check in Perl:
sub empty {
# Use 'while' instead of 'for' to avoid reading all the filenames.
# basic idea:
# return 1 unless directory contains something other than '.' or '..'
# In a cron script, I think I'd treat un-openable dirs as empty ***
my $dirname = shift;
opendir my $d, $dirname or return 1; # *** hence the '1'
local $_;
!/^\.\.?$/ and return 0 while $_ = readdir $d;
1;
}
sub oldest_msg {
# finds oldest file in a dir and returns its ctime
# un-openable dirs return 'now'
my $dirname = shift;
opendir my $d, $dirname or return time;
my $min = time;
for (readdir $d) { # here we need to read them all to find the oldest
my $ctime = (stat)[10];
next if $ctime > $min;
$min = $ctime;
}
$min;
}
Then you have roughly the following logic:
my $longago = time - 86_400 * 180; # $longago = 180 days ago
if (
(stat 'cur')[10] > $longago) # cur's ctime isn't long ago
or empty('new') # or there are no new messages
or oldest_msg('new') > $longago # or the oldest isn't long ago
) {
# then don't disable it
# or switch the 'if' to 'unless', and this is where you disable it
}
# ...Perl's definitely my favorite language, if it's not obvious...
[...]
Thanks.
No prob.
Best,
Ben