[Dovecot] dovecot.index mtime
Benjamin R. Haskell
dovecot at benizi.com
Thu Nov 15 07:43:32 EET 2007
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
More information about the dovecot
mailing list