Deleting emails

Oct 28, 2009 at 4:16 PM

Hi,

I wrote a function to delete mails.

My mailbox contains 88 messages. I have 40 of them with the subject "reply ".

When i mark all message which has a match as read then this goes ok. When i delete the messages after the first succesfully delete message a error is raised (unique message id could not be found). It seems that the messageid (after removal of 1 message) changes so that the next match goes wrong. What can i do to resolve this, (except starting over after 1 deleted message, till i dont have a match anylonger?)

I connect to gmail mailbox

Dim connection As New Koolwired.Imap.ImapConnect("imap.gmail.com", 993, True)

Dim command As New Koolwired.Imap.ImapCommand(connection)
        Dim authenticate As New Koolwired.Imap.ImapAuthenticate(connection, "", "")
        connection.Open()
        authenticate.Login()

Dim mailbox As Koolwired.Imap.ImapMailbox = command.Select("INBOX")
        Dim irecords As Integer = mailbox.Exist
        mailbox = command.Fetch(mailbox)
        For Each imessage As Koolwired.Imap.ImapMailboxMessage In mailbox.Messages
            Dim strFrom As String = imessage.From.Address
            Dim strSubject As String = imessage.Subject

            If strSubject.ToLower().Contains("reply") Or _
            strSubject.ToLower().Contains("office") Then

                command.SetDeleted(imessage.ID, True)

                command.Expunge()


            End If

        Next

authenticate.Logout()
        connection.Close()

Jul 12, 2010 at 4:32 PM
Edited Jul 12, 2010 at 7:24 PM
Having the same problem. Any example or fix?
EDIT:
found a "solution":


1) Created a new method on ImapCommand object

Code on: http://pastebin.com/RMArACHm


2) Create a list of messages which contains only the subjects

List<string> toDeleteMails = new List<string>;
// Populate the list with the subjects of the e-mails that will be deleted


3) Finally delete that damn mails >:^/

foreach (string subject in toDeleteMails)
{
ImapMailboxMessage msg = cmd.SearchMailBySubject(subject);
cmd.SetDeleted(msg.ID, True);
cmd.Expunge();
}
Aug 25, 2010 at 3:35 PM

I just learned a lesson the hard way: do not call cmd.Expunge() immediately after calling cmd.SetDeleted()! Set the messages as deleted whenever you want, but only call Expunge when you're finished with your session (right before you call authenticate.Logout() and connection.Close()).

The problem is that as soon as you call Expunge() to delete the messages, all of your message IDs may change. The IDs are not the Message-ID headers from the messages themselves - Koolwired's message ID starts at 1 (for the first message in the mailbox).

Consider this code:

foreach (ImapMailboxMessage message in mailbox.Messages)
{
    cmd.SetDeleted(message.ID, true);
    cmd.Expunge();
}

Imagine you have two messages in your inbox. The first time through this loop, message.ID is 1 and it'll delete/expunge the first message in the mailbox. The second time through, message.ID is 2 and it'll delete the second message ... except that there is no second message, there's only one message remaining, so that message has ID 1, and this code will fail.

 

Coordinator
Sep 2, 2010 at 4:45 PM
bkendig wrote:

I just learned a lesson the hard way: do not call cmd.Expunge() immediately after calling cmd.SetDeleted()! Set the messages as deleted whenever you want, but only call Expunge when you're finished with your session (right before you call authenticate.Logout() and connection.Close()).

The problem is that as soon as you call Expunge() to delete the messages, all of your message IDs may change. The IDs are not the Message-ID headers from the messages themselves - Koolwired's message ID starts at 1 (for the first message in the mailbox).

Consider this code:

foreach (ImapMailboxMessage message in mailbox.Messages)
{
    cmd.SetDeleted(message.ID, true);
    cmd.Expunge();
}

Imagine you have two messages in your inbox. The first time through this loop, message.ID is 1 and it'll delete/expunge the first message in the mailbox. The second time through, message.ID is 2 and it'll delete the second message ... except that there is no second message, there's only one message remaining, so that message has ID 1, and this code will fail.

Its best if you only call expunge after all messages have been flagged. Change the code to something like this.

foreach (ImapMailboxMessage message in mailbox.Messages)
{
cmd.SetDeleted(message.ID, true);
}
cmd.Expunge();

There may be a way to do something about that. I believe the MessageID (UID) on the server is tracked but I guess when expunge is called it would have to know what mailbox object is selected so it can remove the messages from the collection eliminating the need to get a new list from the server and allowing the user to expunge more frequently (although I think most IMAP servers would frown on that)