UpdateMessage command removes embedded messages

We are testing with aspose.email 24.9 (Files attached)
TestPSTandEML.zip (23.2 KB)

using Aspose.Email;

using Aspose.Email.Mapi;

using Aspose.Email.Storage.Pst;

var asposeLicense = new License();

var pstFilePath = args[0];

var emlFilePath = args[1];

var asposeLicensePath = args[2];

SetAsposeLicense();

using var pst = PersonalStorage.FromFile(pstFilePath);

var inbox = pst.RootFolder.EnumerateFolders(FolderKind.Normal).ToArray();

var msg = MapiMessage.FromMailMessage(MailMessage.Load(emlFilePath));

var ids = inbox[1].EnumerateMessagesEntryId().ToArray();

inbox[1].DeleteChildItems([ids[0]]);

// inbox[1].UpdateMessage(ids[0], msg); <— Produces weird results.

inbox[1].AddMessage(msg);

void SetAsposeLicense()

{

asposeLicense.SetLicense(new MemoryStream(File.ReadAllBytes(asposeLicensePath)));

}

@bahakh

Why UpdateMessage Removes Embedded Items

Folder.UpdateMessage(entryId, message) replaces the existing message in the PST folder with the MapiMessage you pass in.
It does not merge the new message with the old one – everything that is not present in the supplied MapiMessage (including embedded messages, inline images, custom properties, etc.) will be lost.

In your sample you:

inbox[1].DeleteChildItems([ids[0]]);   // ❌ removes the original message
// inbox[1].UpdateMessage(ids[0], msg); // now you try to update a non‑existent entry
inbox[1].AddMessage(msg);              // adds a brand‑new message
  • The call to DeleteChildItems deletes the original message before you try to update it.
  • UpdateMessage then works on a stale entryId, which produces the “weird results” you see.

What you need to do

  1. Do not delete the message if you intend to update it.
  2. If you need to keep the original embedded messages (or any other attachments), copy them from the existing message into the new one before calling UpdateMessage.

Below is a typical pattern for updating a message while preserving its embedded items.


Step‑by‑Step Solution

using Aspose.Email;
using Aspose.Email.Mapi;
using Aspose.Email.Storage.Pst;

// ---------- 1. Load PST ----------
PersonalStorage pst = PersonalStorage.FromFile(pstFilePath);
MapiFolder inbox = pst.RootFolder.GetSubFolder("Inbox");

// ---------- 2. Locate the message ----------
string entryId = inbox.EnumerateMessagesEntryId().First();   // example: first message

// ---------- 3. Load the *existing* message ----------
MapiMessage originalMsg = inbox.GetMessage(entryId);

// ---------- 4. Create / modify the new message ----------
MapiMessage newMsg = MapiMessage.FromMailMessage(MailMessage.Load(emlFilePath));

// ---- 4a. Preserve embedded messages / attachments ----
foreach (MapiAttachment att in originalMsg.Attachments)
{
    // Keep only the embedded messages (type = MapiAttachmentType.EmbeddedMessage)
    // or any other attachment you want to retain.
    if (att.Type == MapiAttachmentType.EmbeddedMessage ||
        att.IsInline ||
        att.IsEmbeddedMessage)
    {
        newMsg.Attachments.Add(att);
    }
}

// You can also copy custom properties, conversation index, etc.
newMsg.ConversationIndex = originalMsg.ConversationIndex;
newMsg.Subject = newMsg.Subject;   // or modify as required

// ---------- 5. Update the message ----------
inbox.UpdateMessage(entryId, newMsg);

Key Points

What you want How to achieve it
Update an existing item Use UpdateMessage(entryId, newMsg). Do not delete the item first.
Keep embedded messages/attachments Load the existing MapiMessage, copy the needed MapiAttachments into the new one, then call UpdateMessage.
Preserve custom MAPI properties After creating newMsg, copy any required properties:
newMsg.SetProperty(propertyTag, originalMsg.GetProperty(propertyTag));
Change only body or subject Load the original message, modify newMsg.Body / newMsg.Subject, then UpdateMessage. No need to touch attachments.

Common Pitfalls & How to Avoid Them

Pitfall Why it happens Fix
Calling DeleteChildItems before UpdateMessage The entry ID no longer refers to a valid message, so ASPose replaces it with a minimal placeholder. Remove the delete call; let UpdateMessage overwrite the message in place.
Using MapiMessage.FromMailMessage on an EML that contains embedded messages The conversion strips out message/rfc822 attachments because they are treated as regular attachments. Load the original PST message, copy its Attachments collection, then add any new content.
Losing custom properties (PR_ tags)* FromMailMessage creates a fresh MapiMessage without the custom tags. After creating newMsg, copy the needed properties from originalMsg as shown above.
Expecting UpdateMessage to merge bodies UpdateMessage replaces the entire message object. Build the final MapiMessage exactly as you want it (merge bodies manually if needed).

References


Next Steps

  1. Replace the DeleteChildItems line with the pattern shown above.
  2. If you need to add new attachments while preserving old ones, add them to newMsg.Attachments after copying the existing collection.
  3. Run the code and verify that the embedded message (or any other attachment) remains intact.

If you still encounter unexpected behaviour, please share:

  • The exact PST hierarchy (folder names) you are working with.
  • A minimal EML file that contains the embedded message you wish to preserve.

With that information we can reproduce the scenario and fine‑tune the solution.

Happy coding! :rocket:

We are sorry if we confused you with our code snippet, we were trying multiple things and just realized we provided you with an incorrect code snippet. Please find the correct code snippet below.

using Aspose.Email;

using Aspose.Email.Mapi;

using Aspose.Email.Storage.Pst;

var asposeLicense = new License();

var pstFilePath = args[0];

var emlFilePath = args[1];

var asposeLicensePath = args[2];

SetAsposeLicense();

using var pst = PersonalStorage.FromFile(pstFilePath);

var inbox = pst.RootFolder.EnumerateFolders(FolderKind.Normal).ToArray();

var msg = MapiMessage.FromMailMessage(MailMessage.Load(emlFilePath));

var ids = inbox[1].EnumerateMessagesEntryId().ToArray();

inbox[1].UpdateMessage(ids[0], msg); <— Produces weird results.

void SetAsposeLicense()

{

asposeLicense.SetLicense(new MemoryStream(File.ReadAllBytes(asposeLicensePath)));

}

Hello @bahakh,

Thank you for reaching out.
We’ll review the issue and follow up with you soon.

1 Like

Any update on this?

Hello @bahakh,

I’ve checked with our developers, and they were able to reproduce the problem where UpdateMessage removes embedded messages.
A ticket has been created for further investigation and resolution.

Issue ID(s): EMAILNET-41631

Thank you.

Thank you. Do you have any estimates when we can have a fix for this? this is a high priority and it is a customer requirement that we will need a fix asap as we will loose the customer if this is not fixed.

@bahakh,

We will make every effort to provide a fix by the end of the current month.