Auto-Archiving, and Unread Threshold Alert

Marco Colombo marco at
Wed May 11 08:38:24 EDT 2005

On Tue, 2005-05-10 at 22:41 +0800, Senandung Mendonan wrote:
> Hi,
> I need to do the following in Cyrus IMAP 2.2.12:-
> 1. Daily auto-archiving
> - On 12am each day, an IMAP/Cyrus agent runs through each user's
> mailbox, and sort out all existing mails into today, yesterday, last
> week, and last month folders.

The best way to achieve this, by far, is client-side. See VFolders in
evolution (those are not real IMAP folders, and the server is totally
unaware of them; it's only a matter client interface). But I understand
sometimes you can't choose the client and you have to band-aid on the
server side.

> 2. Unread threshold alerts
> - Every 5 minutes, an IMAP/Cyrus agent runs through each user's
> mailbox (or any other alternative ways), and upon finding new mails
> that are unread since last poll, alert the sysadmin.

5 mins? Wow. Are you sure you need this? The implications are:
- time to read and process a single message is << 5 mins
- rate of message arrivals is predictable, and is < the rate at which
messages are processed - ever;
- _all_ messages are to be processed (or deleted), no matter if they are
not relevant with the activity (based on the subject) - no one can say
"ok, this one i'll read later".

It the above conditions are not strictly met, all you have is a nice
entropy generator (the sysadmin will receive almost random and useless

Anyway, the quickest way to implement your agent is a Perl or Python
script. Here's one (quick and dirty) that prints the number of messages
in each user's INBOX that are both unread and older than 5 minutes. It
assumes you can do PLAIN authentication over SSL to imapd running on

#!/usr/bin/env python

import sys
import re
import imaplib
import time
import email.Utils

# authentication credentials for the admin user
auth = "admin"
password = "*******"

def check_one(user, threshold = 300):
    conn = imaplib.IMAP4_SSL()
    rc, data = conn.authenticate("PLAIN",
                            lambda x: "\0".join((user, auth, password)))
    if rc != "OK":

    rc, data = = 1)    # INBOX
    if rc != "OK":

    rc, data = conn.uid("SEARCH", "UNSEEN")
    if rc != "OK":

    uids = ",".join(data[0].split())

    if not uids:

    rs, data = conn.uid("FETCH", uids, "INTERNALDATE")
    if rc != "OK":

    patt = re.compile(r'\(UID ([0-9]+) INTERNALDATE "([^"]*)"\)')
    unread_messages = []
    for line in data:
        m =
        if not m:
        uid =
        internaldate_mk = email.Utils.parsedate(
        if not internaldate_mk:

        internaldate_ts = time.mktime(internaldate_mk)
        now_ts = time.time()
        if internaldate_ts < now_ts - threshold:

    return unread_messages

# the list of users to check
users = ("user1", "user2", "user3")

for user in users:
    mesgs = check_one(user)
    if mesgs:
        print "user %s has %d messages." % (user, len(check_one(user)))

You can do the same in Perl of course. And moving messages around should
be possible too, for your "daily auto-archiving".

      ____/  ____/   /
     /      /       /                   Marco Colombo
    ___/  ___  /   /                  Technical Manager
   /          /   /                      ESI s.r.l.
 _____/ _____/  _/                      Colombo at

Cyrus Home Page:
Cyrus Wiki/FAQ:
List Archives/Info:

More information about the Info-cyrus mailing list