Ensure flag changes are persisted to imap after setFlags:forMesssage: is called #50

Merged
merged 1 commit into from Oct 8, 2012

Projects

None yet

4 participants

Contributor
NZKoz commented Oct 4, 2012

With libetpan mailmessage_check only updates the in memory store of the flags for a given message, it doesn't make any changes over the wire. You must ensure that imap_flags_store_process is called otherwise the data is lost.

There are a few options for ensuring this is called:

  • imapdriver_uninitialize
  • imapdriver_logout
  • imapdriver_check_folder
  • imapdriver_select_folder
  • imapdriver_expunge_folder
  • imapdriver_get_envelopes_list

Calling CHECK seemed the lowest cost alternative out there.

The current implementation of setFlags:forMessage only works if you either explicitly log out, expunge or select another folder, my particular application doesn't usually do any of those things as it only handles a single mailbox and is more likely to get suspended by a user than explicitly log out / dealloc the CTCoreFolder

@NZKoz NZKoz Do a folder check to ensure flags get stored immediately
Prevents loss of flags if the app terminates or otherwise doesn't call logout or expunge.
175b398
JanC commented Oct 5, 2012

Hi,
FYI: I was having the same issue. See this conversation in the mailing list
http://librelist.com/browser//mailcore/2012/9/14/setting-message-imap-flags/

Hold on, I've just had a look at the CTCoreFolder.m and the code you are submitting is already there
https://github.com/mronge/MailCore/blob/master/Source/CTCoreFolder.m

Contributor
NZKoz commented Oct 5, 2012

@JanC Yeah, @mronge's example code works because the CTCoreFolder is dealloced which causes the imapdrive_uninitialize to be called, which sets the flags.

The code isn't there already, this is calling folder check, not message check.

JanC commented Oct 5, 2012

ah I see. I misread the code

wzbozon commented Oct 8, 2012

Jan Chaloupecky, thank you, but your code didn't help. Expunge helped.

  • (BOOL)setFlags:(NSUInteger)flags forMessage:(CTCoreMessage *)msg {
    BOOL success = [self connect];
    if (!success) {
    return NO;
    }

    int err;
    [msg messageStruct]->msg_flags->fl_flags=flags;
    err = mailmessage_check([msg messageStruct]);
    if (err != MAIL_NO_ERROR) {
    self.lastError = MailCoreCreateErrorFromIMAPCode(err);
    return NO;
    }

    // Added by DK
    // Ensure that flags are updated
    err = mailfolder_expunge(myFolder);
    if (err != MAIL_NO_ERROR) {
    self.lastError = MailCoreCreateErrorFromIMAPCode(err);
    return NO;
    }

    return YES;
    }

05.10.2012, â 13:11, Jan Chaloupecky notifications@github.com íàïèñàë(à):

ah I see. I misread the code


Reply to this email directly or view it on GitHub.

wzbozon commented Oct 8, 2012

Ah, sorry. Your code must be working.
It just Apple Mail app syncs not always, when you tell it to sync. Looks like there is a time treshhold on server.

08.10.2012, â 21:42, Denis Kutlubaev kutlubaev.denis@gmail.com íàïèñàë(à):

Jan Chaloupecky, thank you, but your code didn't help. Expunge helped.

  • (BOOL)setFlags:(NSUInteger)flags forMessage:(CTCoreMessage *)msg {
    BOOL success = [self connect];
    if (!success) {
    return NO;
    }

    int err;
    [msg messageStruct]->msg_flags->fl_flags=flags;
    err = mailmessage_check([msg messageStruct]);
    if (err != MAIL_NO_ERROR) {
    self.lastError = MailCoreCreateErrorFromIMAPCode(err);
    return NO;
    }

    // Added by DK
    // Ensure that flags are updated
    err = mailfolder_expunge(myFolder);
    if (err != MAIL_NO_ERROR) {
    self.lastError = MailCoreCreateErrorFromIMAPCode(err);
    return NO;
    }

    return YES;
    }

05.10.2012, â 13:11, Jan Chaloupecky notifications@github.com íàïèñàë(à):

ah I see. I misread the code


Reply to this email directly or view it on GitHub.

@mronge mronge merged commit 5a033e9 into MailCore:master Oct 8, 2012
Owner
mronge commented Oct 8, 2012

Looks good, thanks!

JanC commented Oct 9, 2012

For me the flag is still not set when I call setFlags only. I have to refetch the folder and only then the imap command "UID STORE 148 FLAGS.SILENT (\Seen)" is actually sent to the server.

Contributor
NZKoz commented Oct 9, 2012

@JanC you can see that imap_flags_store_process is called when calling mailfolder_check. Are you sure you're running the right revisions?

JanC commented Oct 10, 2012

@NZKoz I tried setting a flag with MailCoreEnableLogging(). I have a breakpoint in the method you mentioned and the only output I see after this method is:

>>>>>>> send >>>>>>

3 CHECK
>>>>>>> end send >>>>>>

<<<<<<< read <<<<<<

3 OK CHECK completed
<<<<<<< end read <<<<<<

Contributor
NZKoz commented Oct 10, 2012

If you step through that method in the debugger, does it call imap_flags_store_process? It wouldn't be reasonable for MailCore to call expunge after every flag setting as that would destroy deleted messages instantly rather than letting the programmer call expunge at a suitable point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment