@liangyongwen
Overview
MailMessage::EnumerateMessages
iterates through the items in a folder (PST/OST, IMAP, POP3, etc.).
When the parser meets a message that cannot be parsed, an exception is thrown and the enumeration stops.
At present this is the designed behaviour of the API – the enumeration stops as soon as a parsing error occurs.
There are no announced changes in upcoming releases that will automatically skip the offending item and continue the enumeration.
What can be done today
Even though the enumeration itself cannot be forced to “ignore” a bad message, you can still achieve the three goals you mentioned by using one of the following approaches:
Goal |
How to achieve it today |
Continue processing after a corrupted item |
Enumerate the message IDs / MessageInfo objects first (these do not require full parsing). Then load each message individually inside a try / catch block. If a particular message throws, log the error and move on to the next ID. |
Retain already‑processed messages |
Keep the successfully loaded MailMessage objects in a collection before you try to load the next one. When an exception occurs, the collection still holds all the messages that were loaded earlier. |
Identify the problematic item |
The MessageInfo (or the MessageId returned by EnumerateMessages ) gives you a stable identifier (subject, entry‑id, etc.). When loading fails, you can log that identifier together with the exception details. |
Step‑by‑step example (C++)
#include <Aspose.Email.Cpp/Mapi/PersonalStorage.h>
#include <Aspose.Email.Cpp/Mapi/MessageInfoCollection.h>
#include <Aspose.Email.Cpp/MailMessage.h>
#include <Aspose.Email.Cpp/MailMessageLoadOptions.h>
#include <iostream>
#include <vector>
using namespace Aspose::Email::Mapi;
using namespace Aspose::Email;
using namespace System;
int main()
{
// Open the PST/OST file
auto pst = PersonalStorage::FromFile(u"myArchive.pst");
// Get the folder you want to process
auto folder = pst->RootFolder->GetSubFolder(u"Inbox");
// 1️⃣ Enumerate *MessageInfo* objects – no parsing is performed yet
MessageInfoCollectionPtr infos = folder->EnumerateMessages();
// Store successfully loaded messages
std::vector<SharedPtr<MailMessage>> goodMessages;
// Load options – enabling relaxed parsing can help with partially broken items
auto loadOptions = MakeObject<MailMessageLoadOptions>();
loadOptions->set_RelaxedParserEnabled(true); // <‑‑ optional, see note below
for (auto&& info : infos)
{
try
{
// 2️⃣ Load the full message using its entry ID
auto msg = MailMessage::Load(info->get_EntryId(), loadOptions);
goodMessages.push_back(msg);
// Your normal processing goes here
std::wcout << L"Processed: " << msg->get_Subject() << std::endl;
}
catch (const System::Exception& ex)
{
// 3️⃣ Log the problematic message and continue
std::wcerr << L"Failed to load message with EntryId = "
<< info->get_EntryId() << L". Reason: " << ex->get_Message()
<< std::endl;
// continue with next message
}
}
// At this point `goodMessages` contains all successfully parsed items
// and you already have a log of the failures.
}
Key points in the code
EnumerateMessages()
returns a MessageInfoCollection
. These objects contain metadata (Subject, EntryId, Sender, ReceivedDate, …) and can be retrieved without parsing the whole MIME content.
MailMessageLoadOptions::set_RelaxedParserEnabled(true)
tells the parser to be more tolerant (it will try to recover from many malformed parts). It does not guarantee that every broken message will be loaded, but it reduces the number of hard failures.
- The
try / catch
around each MailMessage::Load
guarantees that a single corrupted message does not abort the whole loop.
Alternative: IMAP / POP3 scenario
If you are enumerating a remote mailbox (IMAP/POP3), the same pattern applies:
auto client = MakeObject<ImapClient>(u"imap.example.com", 993, u"user", u"pwd");
client->SelectFolder(u"INBOX");
// Get only the message UIDs (no body download)
ArrayPtr<int32_t> uids = client->ListMessages();
for (int32_t uid : uids)
{
try
{
auto msg = client->FetchMessage(uid, loadOptions); // loads full message
// process msg …
}
catch (const System::Exception& ex)
{
std::wcerr << L"UID " << uid << L" could not be parsed: " << ex->get_Message() << std::endl;
}
}
The principle is identical: first obtain identifiers, then load each message individually with proper exception handling.
Road‑map note
We have logged the request for a “skip‑on‑error” enumeration mode internally. At the moment there is no concrete release target for such a feature. In the meantime, the pattern described above is the recommended way to achieve robust processing of large mail stores that may contain corrupted items.
Helpful links
If you need further assistance—e.g., adapting the pattern to a specific mailbox type (Exchange, MBOX, .eml directory) or troubleshooting a particular corrupt file—please let us know the exact source (PST, IMAP, POP3, etc.) and any sample message identifiers you have. We’ll be happy to provide a more tailored code snippet.