Ler arquivos PST do MS Outlook em C# .NET

Um Tópico de Conversa é uma sequência de respostas a uma mensagem com um tópico de conversa comum. As mensagens dentro da conversa podem ser exibidas de várias maneiras, como em ordem hierárquica ou cronológica. Para exibir um tópico de mensagem, os aplicativos de e-mail identificam as respostas das mensagens. Os formatos de arquivo de e-mail mais populares oferecem esse recurso.
Os tópicos de conversa permitem que os leitores compreendam rapidamente a estrutura geral de uma conversa, destaquem certos pontos das conversas e analisem informações importantes. Neste artigo, vamos nos concentrar em usar os recursos PST/MAPI da Aspose.Email para encontrar e agrupar mensagens por conversa. Para isso, implementaremos um código de exemplo que irá percorrer as mensagens em uma determinada pasta, agrupá-las por conversa e, em seguida, salvar cada conversa em um diretório separado no disco.

Propriedades MAPI que são usadas para Suportar o Tópico de Conversa

Como as mensagens em pst são armazenadas como um conjunto de propriedades MAPI, precisamos definir as propriedades MAPI que estão associadas à coleta de respostas de mensagens. Isso é descrito na seção Microsoft Docs. Como pode ser visto, a propriedade PidTagConversationIndex permite determinar com precisão se uma mensagem está associada a uma determinada conversa ou não. A propriedade também indica a posição relativa da mensagem dentro de um tópico de conversa. Visite a página para mais informações sobre a propriedade PidTagConversationIndex. O cabeçalho é os primeiros 22 bytes do valor da propriedade PidTagConversationIndex. É uma porção de dados para determinar se a mensagem pertence a um determinado tópico de conversa.

API C# .NET para Ler Arquivos PST do Outlook

Para ler arquivos PST, usaremos Aspose.Email para .NET. É uma biblioteca incrível para implementar aplicativos de processamento de e-mail usando .NET. Usando a biblioteca, você pode facilmente lidar com muitos formatos de arquivo de e-mail diferentes. Você pode instalar Aspose.Email para .NET via NuGet ou baixar seu DLL.

PM> Install-Package Aspose.Email

Agrupar mensagens em PST por tópico de conversa

Para agrupar as mensagens em PST por conversas, precisamos do seguinte:

  • Primeiro, criar uma classe ConversationThread. É um contêiner para agrupar as mensagens dentro de uma conversa.
  • Em seguida, criar um método para pesquisar e agrupar mensagens por conversa.
  • Por fim, criar um método para salvar o tópico de conversa em um diretório separado.

Criar uma classe ConversationThread

Ela terá as seguintes propriedades.

  • Id: representação em string do cabeçalho do índice da conversa (22 bytes).
  • Messages: lista de IDs de mensagens que estão no tópico de conversa.
/// <summary>
/// Represents messages within a conversation thread.
/// </summary>
public class ConversationThread
{
private string id;
private List<string> messages;
/// <summary>
/// Initializes a new instance of the <see cref="ConversationThread"/> class.
/// </summary>
/// <param name="id">The string representation of conversation index header.</param>
public MessageThread(string id)
{
this.id = id;
this.messages = new List<string>();
}
/// <summary>
/// Gets or sets the HEX string representation of conversation index header (22 bytes).
/// </summary>
public string Id { get => id; set => id = value; }
/// <summary>
/// Gets a list of message IDs that are within a conversation thread.
/// </summary>
public List<string> Messages { get => messages; }
}

Criar um método para pesquisar e agrupar mensagens por conversa

Após criar a classe ConversationThread, podemos nos concentrar em escrever um método que faça o seguinte:

  • Percorrer todas as mensagens na pasta. Por razões de desempenho, leremos apenas o identificador da mensagem usando o método EnumerateMessagesEntryId.
  • Para cada mensagem, extrairemos a propriedade PidTagConversationIndex usando o método ExtractProperty.
  • Mensagens que têm os mesmos primeiros 22 bytes do valor da propriedade PidTagConversationIndex pertencem à mesma conversa. Adicionaremos o Id da mensagem à lista representada pela propriedade Messages da correspondente instância da classe ConversationThread.
  • Retornar a lista de instâncias de ConversationThread.
using Aspose.Email.Mapi;
using Aspose.Email.Storage.Pst;
public List<ConversationThread> GroupMessagesByThread(PersonalStorage pst, FolderInfo folder)
{
// Result
var list = new List<ConversationThread>();
foreach (var entryId in folder.EnumerateMessagesEntryId())
{
// Extract PidTagConversationIndex property and its header value (22 bytes).
var convIndexTag = KnownPropertyList.ConversationIndex.Tag;
var convIndexProperty = pst.ExtractProperty(Convert.FromBase64String(entryId), convIndexTag);
var convIndexHeader = (convIndexProperty != null && convIndexProperty.Data != null) ? convIndexProperty.Data.Take(22).ToArray() : null;
var convIndexHeaderString = convIndexHeader != null ?
BitConverter.ToString(convIndexHeader).Replace('-', '') : null;
if (convIndexHeaderString != null)
{
var convThread = list.Find(x => x.Id == convIndexHeaderString);
if (convThread == null)
{
convThread = new ConversationThread(convIndexHeaderString);
convThread.Messages.Add(entryId);
list.Add(convThread);
}
else
{
convThread.Messages.Add(entryId);
}
}
}
return list.Where(x => x.Messages.Count > 1).ToList();
}

Criar um método para salvar o tópico de conversa em um diretório separado

Finalmente, vamos salvar as conversas nos diretórios.

Para cada instância de ConversationThread, faça o seguinte:

  • Crie um diretório separado com o nome do tópico da conversa.
  • Enumere os identificadores na propriedade ConversationThread.Messages, para cada identificador extraia uma mensagem usando o método ExtractMessage e salve a mensagem no diretório criado usando o método Save.
public void SaveThreads(List<ConversationThread> list, string outDirectory)
{
var invalidChars = Path.GetInvalidFileNameChars();
foreach (var item in list)
{
string? threadDirectory = null;
var i = item.Messages.Count - 1;
foreach (var entryId in item.Messages)
{
var msg = pst.ExtractMessage(entryId);
if (threadDirectory == null)
{
var threadName = new string(msg.ConversationTopic.Where(x => !invalidChars.Contains(x)).ToArray()).Trim();
threadDirectory = Path.Combine(outDirectory, threadName);
Directory.CreateDirectory(threadDirectory);
}
msg.Save(Path.Combine(threadDirectory, $"{i--}.msg"));
}
threadDirectory = null;
}
}
view raw SaveThreads.cs hosted with ❤ by GitHub

Obtenha uma Licença de API Gratuita

Você pode usar Aspose.Email para .NET sem limitações de avaliação usando uma licença temporária gratuita.

Conclusão

Este artigo mostra como usar Aspose.Email para pesquisar mensagens relacionadas a conversas em PST. Ao explorar mais a documentação do PidTagConversationIndex, você também pode complicar a implementação adicionando, por exemplo, a ordenação hierárquica das mensagens de conversa. Você pode aprender mais sobre Aspose.Email usando a documentação. Caso tenha alguma dúvida, você pode postar em nosso fórum.

Veja Também