Clarification on Aspose.Email support for system folders like IPM_SUBTREE, Common Views, etc

I am using Aspose.Email for .NET to convert OST to PST and enumerate folders/messages.

During folder traversal, I notice that the following folders are detected:

“Common Views”, “Drizzle”, “Finder”, “RSS Feeds”, “Suggested Contacts”,
“Sync Issues”, “Conflicts”, “Local Failures”, “Server Failures”,
“EFORMS REGISTRY”, “Organization Forms”, “Non_IPM_SUBTREE”, “IPM_SUBTREE”,
“Root - Public”, “Root - Mailbox”

Could you please clarify the following:

  1. Does Aspose.Email officially support accessing and reading data from these folders?
  2. Which of these are considered system/internal folders that are recommended to be skipped?
  3. Is there a documented list or API indicator to help distinguish user folders (Inbox, Sent, etc.) from internal/system folders?
    I want to make sure my tool avoids processing unnecessary or non-user folders during migration.
    Environment:
  • Aspose. Email for .NET version: [Insert version]
  • Input file: OST (Outlook 2016)

@Anjali12

Cause

Aspose.Email for .NET supports accessing and reading data from various folders, including system folders. However, certain folders are designated as internal or system folders and are not intended for user interaction.

Solution

  1. Accessing Folders: You can access folders like “IPM_SUBTREE” and “Non_IPM_SUBTREE” using Aspose.Email, but it is crucial to exercise caution with system folders.

  2. Recommended Folders to Skip: The following folders are generally considered system/internal folders and should be skipped during processing:

    • Common Views
    • Drizzle
    • Finder
    • RSS Feeds
    • Suggested Contacts
    • Sync Issues
    • Conflicts
    • Local Failures
    • Server Failures
    • EFORMS REGISTRY
    • Organization Forms
  3. Distinguishing User Folders: There isn’t a specific documented list or API indicator that clearly distinguishes user folders (like Inbox, Sent Items) from internal/system folders. A common practice is to check the folder names and skip those that match known system folder names.

Code

Here’s a simple example of how you might enumerate folders and skip the system folders:

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

// Load the PST file
using (PersonalStorage pst = PersonalStorage.FromFile("path_to_your_file.pst"))
{
    foreach (var folder in pst.RootFolder.GetSubFolders())
    {
        // Check if the folder is a system folder
        if (!IsSystemFolder(folder.Name))
        {
            Console.WriteLine($"User Folder: {folder.Name}");
        }
    }
}

bool IsSystemFolder(string folderName)
{
    // List of known system folders
    var systemFolders = new List<string>
    {
        "Common Views", "Drizzle", "Finder", "RSS Feeds", "Suggested Contacts",
        "Sync Issues", "Conflicts", "Local Failures", "Server Failures",
        "EFORMS REGISTRY", "Organization Forms"
    };
    return systemFolders.Contains(folderName);
}

Next Steps

  • Implement the above code to filter out system folders during your folder traversal.
  • Test with your specific OST file to ensure that only user folders are processed.
  • If you encounter any issues or need further clarification, please reach out for assistance.

I hope this information helps you successfully manage your folders!

How should I handle folder names that appear in different languages, such as ‘Root-Mailbox’ and ‘Radice-cassetta postale’?

Hello @Anjali12,

Aspose.Email can access all folders present in an OST file. However, some folders are used by Outlook/Exchange internally and do not usually contain user content that is relevant for migration.

We recommend skipping root-level system OST folders: “Non_IPM_SUBTREE”, “IPM_SUBTREE”, “Root - Mailbox”, “Root - Public”.
You can only migrate content from “IPM_SUBTREE” under “Root - Mailbox” to avoid unnecessary data.

Next, you can use the MapiFolder.GetPredefinedType(true) method to identify standard folders like:

  • Inbox
  • SentItems
  • Drafts
  • DeletedItems
  • Contacts, Calendar, Tasks, etc.

Folder names can appear in different languages, so you should rely on GetPredefinedType instead of comparing names directly.

If the method returns StandardIpmFolder.Unspecified, the folder is likely a custom.

For example:

using Aspose.Email.Storage.Pst;

var ostFilePath = "input.ost";
var pstFilePath = "output.pst";

// Load OST
using var ost = PersonalStorage.FromFile(ostFilePath);

// Create new PST
using var pst = PersonalStorage.Create(pstFilePath, FileFormatVersion.Unicode);

// Locate Root - Mailbox > IPM_SUBTREE
FolderInfo rootMailbox = ost.RootFolder.GetSubFolder("Root - Mailbox");
FolderInfo ipmSubtree = rootMailbox?.GetSubFolder("IPM_SUBTREE");

if (ipmSubtree == null)
    throw new InvalidDataException("IPM_SUBTREE not found under 'Root - Mailbox'.");

// Start copying from IPM_SUBTREE
foreach (var folder in ipmSubtree.GetSubFolders())
{
    CopyFolder(folder, pst.RootFolder, pst);
}

// Recursive copy method
void CopyFolder(FolderInfo sourceFolder, FolderInfo targetParent, PersonalStorage destination)
{
    // Determine the predefined type of the folder (e.g., Inbox, Sent Items, etc.)
    var predefined = sourceFolder.GetPredefinedType(true);
    FolderInfo destFolder;

    if (predefined == StandardIpmFolder.DeletedItems)
    {
        // Deleted Items folder already exists in the PST, so reuse it
        destFolder = destination.RootFolder.GetSubFolder("Deleted Items");
    }
    else if (predefined != StandardIpmFolder.Unspecified)
    {
        // For standard folders (Inbox, Sent Items, etc.), create them using CreatePredefinedFolder
        destFolder = destination.CreatePredefinedFolder(sourceFolder.DisplayName, predefined);
    }
    else
    {
        // For custom user-defined folders, use AddSubFolder
        destFolder = targetParent.AddSubFolder(sourceFolder.DisplayName);
    }

    // Copy all messages from the source folder to the destination
    foreach (var msg in sourceFolder.EnumerateMapiMessages())
        destFolder.AddMessage(msg);

    // Recursively process all subfolders
    foreach (var sub in sourceFolder.GetSubFolders())
        CopyFolder(sub, destFolder, destination);
}