markauk
asked on
Efficient way to delete old mails
I have a script which does a bunch of mail processing, including deleting old mails from certain IMAP folders. I currently use the following to do this:-
for ($msg = 1 ; $msg <= $numsg ; ++$msg) {
$header = imap_headerinfo($mbox, $msg);
$date = $header->udate;
if (($date + $age) < $now) imap_delete($mbox,$msg);
}
imap_expunge($mbox);
This is run for a number of different folders, many of which have rather a lot (>1000) messages, so going through and checking the date of every single message and deleting one by one strikes me as a rather inefficient way to do this.
Could someone supply me with a rather more efficient bit of code to replace the above code with?
thanks
mark.
for ($msg = 1 ; $msg <= $numsg ; ++$msg) {
$header = imap_headerinfo($mbox, $msg);
$date = $header->udate;
if (($date + $age) < $now) imap_delete($mbox,$msg);
}
imap_expunge($mbox);
This is run for a number of different folders, many of which have rather a lot (>1000) messages, so going through and checking the date of every single message and deleting one by one strikes me as a rather inefficient way to do this.
Could someone supply me with a rather more efficient bit of code to replace the above code with?
thanks
mark.
$thold = $now - $age;
for ($msg = 1 ; $msg <= $numsg ; ++$msg) {
$header = imap_headerinfo($mbox, $msg);
if ($header->udate < $thold) imap_delete($mbox,$msg);
}
imap_expunge($mbox);
----
Or use imap_sort, then imap_headerinfo with array_slice to get the sequence and after that imap_setflag_full to set \\Deleted flag
http://www.php.net/imap_setflag_full
http://www.php.net/array_slice
http://www.php.net/imap_headerinfo
http://www.php.net/imap_sort
for ($msg = 1 ; $msg <= $numsg ; ++$msg) {
$header = imap_headerinfo($mbox, $msg);
if ($header->udate < $thold) imap_delete($mbox,$msg);
}
imap_expunge($mbox);
----
Or use imap_sort, then imap_headerinfo with array_slice to get the sequence and after that imap_setflag_full to set \\Deleted flag
http://www.php.net/imap_setflag_full
http://www.php.net/array_slice
http://www.php.net/imap_headerinfo
http://www.php.net/imap_sort
ASKER
Not sure how that code is really any different from my own.
The suggestion of using sort, sounds better if someone can supply my with the required code. Or, is there a way to read dates of all messages in a folder into an array in one go, figure out which ones are old, and then delete all the relevant messages in one go?
The suggestion of using sort, sounds better if someone can supply my with the required code. Or, is there a way to read dates of all messages in a folder into an array in one go, figure out which ones are old, and then delete all the relevant messages in one go?
It is just a bit faster PHP code.
I don't have many email account with thousands of useless letters, so you will have to test this yourself on another mailbox. =)
// Let's start with
$msgnumbersbydate = imap_sort($mbox, SORTDATE, 1);
// now you've got message numbers, sorted by date in reverse order
// next find first element in array, from which queue has to be deleted
$thold = $now - $age;
reset($msgnumbersbydate);
while (list($key, $value) = each($msgnumbersbydate)) {
$header = imap_headerinfo($mbox, $msg);
if ($header->udate < $thold) {
$delfrom = $key;
break;
}
}
// if there's something to delete build mesage sequence and set \\Deleted flag
if (isset($delfrom)) {
// building sequence string
$seqarray = array_slice($msgnumbersbyd ate, $delfrom);
$seqstring = implode(',', $seqarray);
// flag messages as deleted
imap_set_flag_full ($mbox, $seqstring, "\\Deleted");
// call expunge to actually delete them
imap_expunge($mbox);
}
Should work. Please, let us know if something goes wrong or if you will make some modifications to this code to work.
I don't have many email account with thousands of useless letters, so you will have to test this yourself on another mailbox. =)
// Let's start with
$msgnumbersbydate = imap_sort($mbox, SORTDATE, 1);
// now you've got message numbers, sorted by date in reverse order
// next find first element in array, from which queue has to be deleted
$thold = $now - $age;
reset($msgnumbersbydate);
while (list($key, $value) = each($msgnumbersbydate)) {
$header = imap_headerinfo($mbox, $msg);
if ($header->udate < $thold) {
$delfrom = $key;
break;
}
}
// if there's something to delete build mesage sequence and set \\Deleted flag
if (isset($delfrom)) {
// building sequence string
$seqarray = array_slice($msgnumbersbyd
$seqstring = implode(',', $seqarray);
// flag messages as deleted
imap_set_flag_full ($mbox, $seqstring, "\\Deleted");
// call expunge to actually delete them
imap_expunge($mbox);
}
Should work. Please, let us know if something goes wrong or if you will make some modifications to this code to work.
ASKER
Looks like this should be an improvement, but doesn't reverse order sorting mean that the newest message comes first? Would probably be faster to start with oldest message... as long as I run the script regularly there will always be more messages not to delete than to delete.
Also, any reason you did the deletes the way you did rather than just imap_delete($mbox,'1:$key' ) (assuming we are sorted oldest first)?
Also, any reason you did the deletes the way you did rather than just imap_delete($mbox,'1:$key'
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
You are right, imap_sort doesn't actually sort the messages, so the simple imap_delete won't work. Here's what I've ended up going with:-
$msgnumbersbydate = imap_sort($mbox, SORTARRIVAL, 0);
reset($msgnumbersbydate);
$delete_msgs = "";
while (list($key, $msg) = each($msgnumbersbydate)) {
$header = imap_headerinfo($mbox, $msg);
if ($header->udate < $oldest) {
$delete_msgs .= "$msg,";
} else {
break;
}
}
if ($delete_msgs<>"") {
$delete_msgs = rtrim($delete_msgs,",");
imap_delete($mbox,$delete_ msgs);
imap_expunge($mbox);
}
imap_close($mbox);
It's not quite as super efficient as I was hoping, but certainly better than what I had.
Thanks for your help.
$msgnumbersbydate = imap_sort($mbox, SORTARRIVAL, 0);
reset($msgnumbersbydate);
$delete_msgs = "";
while (list($key, $msg) = each($msgnumbersbydate)) {
$header = imap_headerinfo($mbox, $msg);
if ($header->udate < $oldest) {
$delete_msgs .= "$msg,";
} else {
break;
}
}
if ($delete_msgs<>"") {
$delete_msgs = rtrim($delete_msgs,",");
imap_delete($mbox,$delete_
imap_expunge($mbox);
}
imap_close($mbox);
It's not quite as super efficient as I was hoping, but certainly better than what I had.
Thanks for your help.
In this way you will not need to check the newer files