
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
- API C# .NET para Ler Arquivos PST do Outlook
- Agrupar mensagens em PST por tópico de conversa
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 propriedadeMessages
da correspondente instância da classeConversationThread
. - 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; | |
} | |
} |
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.