I have been using a perl script to archive mail found here

The script uses ctime to process and decide which month sub folder to place mail. In most cases this is fine since the ctime = mtime and therefore the mails are archived by the month that they were sent or received.

But I have found occasions when it is not good to run the script.

Say for example a user moves mail back into the inbox or mail has been recovered from a backup into the inbox. If the script processes the touched mail it will move mail into a month it was touched not the time it was sent/received.

Is it not better to process mails by mtime ?

In other words what is the better POSIX qw I should use ?


I work with procmail and Dovecot, but the maildir structure is fairly standardized.

If you are trying to archive by date you may want to verify the Date from the headers. Reading from the top of the headers the first date you find should be very accurate. My messages have three fields which can be used Delivery-Date:, the Received: headers, and the Date: header. For received messages, the Delivery-Date: or first Received: header will have the appropriate date. For sent messages, you are likely to have only the Date: header, which may reflect the time of the system that created it, not your mail server. You may want to flag messages which don't have a usable date in the headers.

ctime should usually be the date of the message, but there are cases where a new copy of the message is created when it is moved or copied. Normally these actions take place by relinking the file to the correct directory. EDIT: This script will print a list of messages with the first date in the file. It matches on the RFC date format. The regex may not be the best.


%months = ( 'Jan'=>'01', 'Feb'=>'02', 'Mar'=>'03', 'Apr'=>'04',
            'May'=>'05', 'Jun'=>'06', 'Jul'=>'07', 'Aug'=>'08',
            'Sep'=>'09', 'Oct'=>'10', 'Nov'=>'11', 'Dec'=>'12' );

foreach $filename (@ARGV) {
    open( MESSAGE, $filename);

    while (<MESSAGE>) {
        if ( m/[A-Z][a-z][a-z], ([1230][0-9]) ([A-Z][a-z][a-z]) ([12][0-9][0-9][0-9])/ ) {
            print "$3-$months{$2}-$1 $filename\n";

        if ( m/^$/ ) {                     # End of header
            print "-No--Date- $filename\n";
    close MESSAGE;

  • Hello BillThor. Do you have a script example of how you process the dates in the headers ?
    – timoto
    Nov 25 '12 at 14:14
  • @timoto Added a date verifier I use to check my archive directories. Matches date format rather than specific headers.
    – BillThor
    Nov 25 '12 at 21:35
  • Thank you for your example. I will try to figure out how to incorporate this in the script I have. You mentioned "messages which don't have a usable date in the headers", does that happen often for you and what do you do about those, use mtime ?
    – timoto
    Nov 26 '12 at 14:58

As I read from here,the difference between ctime and mtime is explained here http://cerebro.freeshell.org/log/unix-mtime-vs-ctime/ . I can tell you small idea, just attach timestamp to every mail you store so that when you retrieve back you have the exact date it was sent or received, this we use to do for our backups.

  • Hello harish.venkat. Do you have an example of how to attach a timestamp ? How would you attach a timestamp to historical mail ?
    – timoto
    Nov 25 '12 at 14:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.