eLore has asked for the wisdom of the Perl Monks concerning the following question:

Fellow monks: I've been hammering away on a script to parse HTML formatted messages retreived from email via Net::IMAP::Simple and throws them at syslog via Sys::Syslog. As part of maintaining some sense of state, i copy processed messages to a "processed" folder for later review, and delete them from the INBOX. As i understand it, either an explicit $server->expunge_mailbox('INBOX') or a $server->quit() should clear the messages from the Inbox. My issue is that they stick around, and are processed on the next execution of the script.

Since $server->quit is also supposed to expunge (according to the docs), I'm pretty sure it's either an issue with the module or with MS-Exchange server. Have any of you experienced anything similar and/or fixed the issue?

UPDATE #1: Added code

UPDATE #2: broken module

UPDATE #3: Converted to Mail::IMAPClient and all is well!!

It appears that the module neither works completely as advertised, nor does it properly check it's own return codes. $server->quit calls $server->expunge_mailbox before disconnect, so $server->quit should never complete successfully without $server->expunge_mailbox also completing successfully...

I guess i get to go re-code, based (hopefully) on Mail::IMAPClient


#!/usr/bin/perl use Env; ## This allows the script to read environment variables use lib $MY_PERL; ## my custom site_perl directory use Net::IMAP::Simple; use Email::Simple; use Sys::Syslog; my $user = $IMAP_USER; my $password = $IMAP_PASS; my $mailhost = $IMAP_HOST; ########################### # subroutine log_msg ########################### sub log_msg { my $error_msg = shift; openlog $0,'nowait,pid','local7'; $rc=syslog('notice', "[ID xxx local7.alert] $error_msg"); closelog(); ## Close the syslog handle return; } my $server = Net::IMAP::Simple->new($mailhost); $server->login($user, $password); my $before_msgs = $server->select('INBOX'); my $heartbeat_msg = "BEFORE EXPUNGE: $before_msgs message(s) in the in +box"; log_msg($heartbeat_msg); my @boxes = $server->mailboxes; #foreach my $box ( @boxes ) { # print "BOX: $box\n"; #}##double check the names of the mailboxes foreach my $msg (1 .. $before_msgs){ my $delete_rc = $server->delete($msg); print "DELETE RC for msg $msg: $delete_rc\n"; } my $expunge_rc = $server->expunge_mailbox('INBOX'); print "EXPUNGE RC: $expunge_rc\n"; print "\$?: $? \$! $!\n"; my $after_msgs = $server->select('INBOX'); my $heartbeat_msg = "AFTER EXPUNGE: $after_msgs message(s) in the inbo +x"; log_msg($heartbeat_msg); $server->quit(); exit();

Printed results: $ test.pl DELETE RC for msg 1: 1 DELETE RC for msg 2: 1 EXPUNGE RC: $?: 0 $! Illegal seek
Based on the blank after "EXPUNGE RC:" it would appear expunge_mailbox is returning undef, which isn't one of the two choices for success or failure...
syslog contents: Sep 15 10:34:08 somebox test.pl[17786]: [ID xxx local7.alert] BEFORE E +XPUNGE: 2 message(s) in the inbox Sep 15 10:34:08 somebox test.pl[17786]: [ID xxx local7.alert] AFTER EX +PUNGE: 2 message(s) in the inbox

Replies are listed 'Best First'.
Re: EXPUNGE not working in Net::IMAP::Simple?
by idsfa (Vicar) on Sep 15, 2004 at 15:14 UTC

    Without seeing your code, it's difficult to make meaningful comment. Are you checking the return status of $server->delete($message_number) to confirm that your delete action succeeds? What does your expunge_mailbox return?

    Updated:

    Well, it looks like the module does not work as documented. The loop which generates the return code is:

    while ( $res = $sock->getline ) { my $ok = $self->_cmd_ok($res); if ( $ok == 1 ) { return $args{final}->($res); } elsif ( defined($ok) && ! $ok ) { return; } else { $args{process}->($res); } }

    Which plainly can return undef (counter to the docs). You could probably stick some code in there to print out the actual result. So the answer to your original question is, "Broken module"


    If anyone needs me I'll be in the Angry Dome.
Re: EXPUNGE not working in Net::IMAP::Simple?
by kappa (Chaplain) on Sep 15, 2004 at 16:06 UTC

    IMAP EXPUNGE actually expunges \Deleted messages from the mailbox which is currently selected. Try to call ->expunge_mailbox() without arguments.

    This could be an omission in Net::IMAP::Simple interface or something. There's no way to expunge non-selected mailbox in the IMAP protocol.