none
MailItem Save error because message has changed

    Question

  • Hi,

    I'have a vsto outlook addin, it was migrated from OLK 2003 to OLK 2010 (using VS 2010sp1), so all references to CDO was deleted.

    Now I'm using Redemption to work with MAPI fields (insted of CDO), in some situations I get an error when wants to save a new MAPI field in the mailitem, the error comes because the "message has changed", so the method Save fails:

    Public Shared Sub SetCampoMAPIcon_RED(ByVal xItem As Outlook.MailItem, ByVal xsCampo As String, ByVal xsValor As String) Try Dim sItem As New Redemption.SafeMailItem, PR_MY_PROP As Object 'sItem = CreateObject("Redemption.SafeMailItem") sItem.Item = xItem PR_MY_PROP = sItem.GetIDsFromNames("{00020329-0000-0000-C000-000000000046}", xsCampo) Or &H101E 'PT_UNICODE Dim PropValue(0) As String PropValue(0) = xsValor sItem.Fields(PR_MY_PROP) = PropValue 'to convince Outlook something has changed sItem.Item.Subject = sItem.Item.Subject sItem.Save()'FAIL

    xItem.Save() 'ReleaseCOMobject(sItem) Catch ex As System.Exception GeneroTrace("SetCampoMAPIconRedemption::", TraceLevel.Error, ex.Message & vbCrLf & ex.StackTrace & vbCrLf & xsCampo & " - " & xsValor) End Try End Sub

    I could reproduce this error if I have two sessions opens in two PCs, then I open a mail in PC1, then open the same mail in PC2 and close it, then in PC1 when I close the mail comes that error.

    This happen because my addin set mapi fields when mails open, so my question is why using CDO in 2003 it did not happened?

    thanks a lot,

    Mauricio.


    Mauricio

    Thursday, December 20, 2012 7:07 PM

Answers

  • Hmmm... You can force Redemption to overwrite the changes (note that when you call Safe*Item.Save, the call call goes to the original Outlook item since the Save method is not blocked)

    If you are using the latest version of Redemption, you can try something like the following script.

    The latest version of Redemption (since RDOMail.Save does not take any parameters) will allow to call SaveAs with an empty file name. In that case the second parameter is interpreted as a parameter to pass to IMessage::SaveChanges(); this way you can pass the FORCE_SAVE parameter.

    KEEP_OPEN_READWRITE = 00000002
    FORCE_SAVE = 00000004
    set Session = CreateObject("Redemption.RDOSession")
    Session.MAPIOBJECT = Application.Session.MAPIOBJECT
    rMail = Session.GetRDOObjectFromOutlookObject(xItem)
    rMail.SaveAs("", FORCE_SAVE | KEEP_OPEN_READWRITE)


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.4 is now available!


    Saturday, January 05, 2013 5:24 PM

All replies

  • It is all in the timing - if you are using a cached store, it is possible that the local cached store will not see the change made on another machine until after you save the item. Or it could be that CDO 1.21 simply ignored the error.

    There isn't much you can do - a conflict is a conflict: you can simply ignore the error or you can use Redemption to overwrite the changes anyway.


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.4 is now available!

    Thursday, December 20, 2012 8:20 PM
  • Hi Dmitry,

    we didn't use the OLK cache, that CDO just ignored the error....

    The problem is that after this error mailitem "saved" property change to "false", so when the mailitem is closed a pop up dialog appears asking to save the changes... there is anyway to avoid this?

    thanks,

    Mauricio.


    Mauricio

    Thursday, December 20, 2012 8:48 PM
  • Have you tried to call MailItem.Close(olDiscard)?

    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.4 is now available!

    Monday, December 24, 2012 3:13 PM
  • but I'm already attached to the mailItem close event, so when you suggests to use "MailItem.Close(olDiscard)" ?

    (when the user closes a mail, the close event fires and all events go on in the chain....)

    thanks.


    Mauricio

    Thursday, December 27, 2012 2:59 PM
  • Hmmm... You can force Redemption to overwrite the changes (note that when you call Safe*Item.Save, the call call goes to the original Outlook item since the Save method is not blocked)

    If you are using the latest version of Redemption, you can try something like the following script.

    The latest version of Redemption (since RDOMail.Save does not take any parameters) will allow to call SaveAs with an empty file name. In that case the second parameter is interpreted as a parameter to pass to IMessage::SaveChanges(); this way you can pass the FORCE_SAVE parameter.

    KEEP_OPEN_READWRITE = 00000002
    FORCE_SAVE = 00000004
    set Session = CreateObject("Redemption.RDOSession")
    Session.MAPIOBJECT = Application.Session.MAPIOBJECT
    rMail = Session.GetRDOObjectFromOutlookObject(xItem)
    rMail.SaveAs("", FORCE_SAVE | KEEP_OPEN_READWRITE)


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.4 is now available!


    Saturday, January 05, 2013 5:24 PM
  • Hi all,

    I received the error every time: MAPI_E_OBJECT_CHANGED

    ulong KEEP_OPEN_READWRITE = 0x00000002; ulong FORCE_SAVE = 0x00000004;

    var redemption = RedemptionLoader.new_RDOSession();
    redemption.Logon(Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value);

    var mail = redemption.GetMessageFromID(entryId, storeId); mail.MessageClass = newMessageClass; mail.SaveAs("", FORCE_SAVE & KEEP_OPEN_READWRITE);

    Whats wrong?  Is it correct values for flags?

    Please advise.



    Monday, February 20, 2017 9:35 PM
  • The constants are fine. What kind of message store is it? Is it Exchange?

    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Monday, February 20, 2017 11:23 PM
  • Thanks for your answer,

    For Exchange everything is OK. I received the error only for IMAP.

    My workflow:

    1. I changed (Save) an email via classic MailItem

    var item = _application.Session.GetItemFromID(entryId, storeId) as MailItem;
    item.Save();

    2. After ~10 sec seacrh by  _application.AdvancedSearch

    3. Take ltEntryId OnAdvancedSearchComplete

    var entries = new List<string>();
    var table = search.GetTable();
    table.Columns.Add(OItemProps.PR_LONGTERM_ENTRYID_FROM_TABLE);
    while (!table.EndOfTable) {
      var nextRow = table.GetNextRow();
      string ltEntryId = (string)nextRow.BinaryToString(OItemProps.PR_LONGTERM_ENTRYID_FROM_TABLE);
      entries.Add(ltEntryId);
    }

    4. Then I updated the item by Redemption

    var mail = redemption.GetMessageFromID(entryId, storeId);
    mail.SaveAs("", FORCE_SAVE & KEEP_OPEN_READWRITE);

    On the 2-3 repeat I got the error: MAPI_E_OBJECT_CHANGED

    Note: I didn't get any errors if I will update via UnwrapStore:

    var unwStore = stores.UnwrapStore(redemptionStore);
    var mail = unwStore.GetMessageFromID(entryId);
    mail.Save();

    Should I use GetRDOObjectFromOutlookObject or GetMessageFromID for save with FORCE_SAVE ?

    Tuesday, February 21, 2017 10:12 AM
  • It don't work if You call save after save for IMAP.

    ulong KEEP_OPEN_READWRITE = 2; ulong FORCE_SAVE = 4; var rdoMail = (RDOMail)redemption.GetRDOObjectFromOutlookObject(mail); rdoMail.UnRead = true;

    rdoMail.SaveAs("", FORCE_SAVE | KEEP_OPEN_READWRITE); var rdoMail2 = redemption.GetMessageFromID(item.EntryId, item.StoreId); rdoMail2.UnRead = !rdoMail.UnRead;

    rdoMail2.SaveAs("", FORCE_SAVE | KEEP_OPEN_READWRITE);

    Why?



    Tuesday, February 21, 2017 11:25 AM
  • The store provider is free to ignore the FORCE_SAVE flag (which the IMAP4 provider apparently does).

    I would strongly recommend that you reconsider the flow - it is a bad idea to keep an open item for any prolonged period of time: open it, modify, save. If you need to modify it again, reopen by the entry id rather than keep an open object.


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Tuesday, February 21, 2017 10:26 PM