Finding Dormant E-Mail Accounts In Courier

    I recently needed to determine if there were inactive/dormant e-mail accounts on my Postfix/Courier mail server. We use virtual accounts in a database, and it does not keep track of last login time for the users, but through a bit of creativity I came up with a way to determine how long it has been since the last login.

    Courier uses several files in the "Maildir" folder for the user, and some of these files are purely used internally to Courier. When users check their mail via POP3, there is a file in their Maildir called courierpop3dsizelist which is updated on every POP3 login. For IMAP users, there is a file called courierimapuiddb which gets updated on every login. Using a bit of PHP code and that bit of knowledge, I was able to create a script which checks for inactive accounts, disables them in the database, and moves their e-mail into an archive folder for later processing.

Here's the basic code:


$domainName = "mydomain.tld" ; // The mail domain you are working with
$baseDirectory = "/home/vmail/$domainName/" ; // The base directory where all user e-mail folders are stored
$archiveDirectory = "/tmp/Archive" ; // The directory where dormant account's messages will be moved to
$archiveBase = "/tmp/MailArchive" ; // The base name of the archive file which will be created
$popFile = "courierpop3dsizelist" ; // The name of the file to check for POP3 activity
$imapFile = "courierimapuiddb" ; // The name of the file to check for IMAP activity
$dormantTime = 1 ; // How long, in months, the account has been dormant

// Instantiate a new dir() object using the $baseDirectory
$d = dir($baseDirectory) ;

// Determine the current month, year, and day
list($year,$month,$day) = explode("-",date("Y-m-d",time())) ;

// Generate a cut-off date for $dormantTime month(s) ago (PHP automatically handles roll-overs from year to year)
$cutOffTime = mktime(0,0,0,($month-$dormantTime),$day,$year) ;

// Open a database connection to the e-mail database
$dbPtr = mysql_connect("localhost","<db user>","<db password>") ;
mysql_select_db("postfix") ;

// Loop through all of the user folders and check their time stamps.
while ($current = $d->read()) {
// Ignore the current and parent directory symbols ("." and "..") and hidden files.
if ($current[0]!='.') {
$popTime = mktime(0,0,0,1,1,1970) ; // Initialize the variable to January 1st, 1970
$imapTime = mktime(0,0,0,1,1,1970) ; // Initialize the variable to January 1st, 1970

// Does the POP3 file exist? If so, store it's modification time in the $popTime variable
if (file_exists($baseDirectory.$current."/Maildir/".$popFile)) {
$popTime = filemtime($baseDirectory.$current."/Maildir/".$popFile) ;

// Does the IMAP file exist? If so, store it's modification time in the $imapTime variable
if (file_exists($baseDirectory.$current."/Maildir/".$imapFile)) {
$imapTime = filemtime($baseDirectory.$current."/Maildir/".$imapFile) ;

// Determine which timestamp is more recent and set $mtime equal to that value
$mtime = $popTime ;
if ($mtime<$imapTime) {
$mtime = $imapTime ;

// If the most recent timestamp is less than the cut-off timestamp, archive the user's account
if ($mtime<$cutOffTime) {
// Set the user's account to "inactive" inside of the database
$query = "UPDATE mailbox SET active='0' WHERE username='$current@$domainName'" ;
$result = mysql_query($query) ;

// Move the user's e-mail to the $archiveDirectory
system("mv ".$baseDirectory.$current." $archiveDirectory");

// Close the database connection
mysql_close($dbPtr) ;

// Generate a data-stamped archive file name
$tarFile = $archiveBase."-".date("Y-m-d").".tgz" ;

// Generate a tar command which will archive the contents of the $archiveDirectory
$tarCmd = "tar -czvf $tarFile $archiveDirectory" ;

// Run the tar command and place the resultant file in the $archiveBase directory
passthru($tarCmd,&$retVal) ;

// If the tar command completes successfully, delete the contents of the $archiveDirectory
if ($retVal==0) {
passthru("rm -rf $archiveDirectory/*") ;
} else {
echo "Error creating archive file.\n" ;


Popular Posts