Czytaj pliki PST programu MS Outlook w języku C# .NET

Wątek rozmowy to sekwencja odpowiedzi na wiadomość o wspólnym temacie wątku. Wiadomości w konwersacji mogą być wyświetlane na różne sposoby, na przykład w porządku hierarchicznym lub chronologicznym. Aby wyświetlić wątek wiadomości, aplikacje pocztowe identyfikują odpowiedzi na wiadomości. Najpopularniejsze formaty plików e-mail udostępniają tę funkcję. Wątki konwersacji pozwalają czytelnikom szybko zrozumieć ogólną strukturę konwersacji, wyróżnić określone punkty konwersacji i przeanalizować ważne informacje. W tym artykule skupimy się na wykorzystaniu funkcji PST/MAPI Aspose.Email do znajdowania i grupowania wiadomości według konwersacji. W tym celu zaimplementujemy przykładowy kod, który przejrzy wiadomości w danym folderze, pogrupuje je według konwersacji, a następnie zapisze każdą konwersację w osobnym katalogu na dysku.

Właściwości MAPI używane do obsługi wątku konwersacji

Ponieważ wiadomości w pst są przechowywane jako zestaw właściwości MAPI, musimy zdefiniować właściwości MAPI, które są powiązane ze zbieraniem odpowiedzi na wiadomości. Jest to opisane w sekcji Microsoft Docs. Jak widać, właściwość PidTagConversationIndex pozwala dokładnie określić, czy wiadomość jest powiązana z daną konwersacją, czy też nie. Właściwość wskazuje również względną pozycję wiadomości w wątku konwersacji. Odwiedź stronę, aby uzyskać więcej informacji o właściwości PidTagConversationIndex. Nagłówek to pierwsze 22 bajty wartości właściwości PidTagConversationIndex. Jest to część danych służąca do określenia, czy wiadomość należy do określonego wątku konwersacji.

C# .NET API do odczytu plików PST programu Outlook

Do czytania plików PST użyjemy Aspose.Email for .NET. To niesamowita biblioteka do implementacji aplikacji do przetwarzania poczty e-mail przy użyciu platformy .NET. Korzystając z biblioteki, możesz łatwo obsługiwać wiele różnych formatów plików e-mail. Możesz zainstalować Aspose.Email for .NET przez NuGet lub pobierz jego bibliotekę DLL.

PM> Install-Package Aspose.Email

Grupuj wiadomości w pliku PST według wątku konwersacji

Aby pogrupować wiadomości w PST według konwersacji, potrzebujemy:

  • Najpierw utwórz klasę ConversationThread. Jest to kontener do grupowania wiadomości w ramach konwersacji.
  • Następnie utwórz metodę wyszukiwania i grupowania wiadomości według konwersacji.
  • Na koniec utwórz metodę zapisywania wątku konwersacji w oddzielnym katalogu.

Utwórz klasę ConversationThread

Będzie miał następujące właściwości.

  • Id: ciąg reprezentujący nagłówek indeksu konwersacji (22 bajty).
  • Wiadomości: lista identyfikatorów wiadomości znajdujących się w wątku konwersacji.
///<summary>
/// Reprezentuje wiadomości w wątku konwersacji.
///</summary>
public class ConversationThread
{
    private string id;
    private List<string> messages;
    
    ///<summary>
    /// Inicjuje nową instancję<see cref="ConversationThread"/> klasa.
    ///</summary>
    ///<param name="id"> Ciąg reprezentujący nagłówek indeksu konwersacji.</param>
    public MessageThread(string id)
    {
        this.id = id;
        this.messages = new List<string>();
    }
    
    ///<summary>
    /// Pobiera lub ustawia ciąg szesnastkowy reprezentujący nagłówek indeksu konwersacji (22 bajty).
    ///</summary>
    public string Id { get => id; set => id = value; }
    
    ///<summary>
    /// Pobiera listę identyfikatorów wiadomości, które znajdują się w wątku konwersacji.
    ///</summary>
    public List<string> Messages { get => messages; }
}

Utwórz metodę wyszukiwania i grupowania wiadomości według konwersacji

Po utworzeniu klasy ConversationThread możemy skupić się na napisaniu metody, która wykona następujące czynności:

  • Przejrzyj wszystkie wiadomości w folderze. Ze względów wydajnościowych identyfikator wiadomości odczytamy tylko metodą EnumerateMessagesEntryId.
  • Dla każdej wiadomości wyodrębnimy właściwość PidTagConversationIndex za pomocą metody ExtractProperty.
  • Wiadomości, które mają takie same pierwsze 22 bajty wartości właściwości PidTagConversationIndex, należą do tej samej konwersacji. Dodamy identyfikator wiadomości do listy reprezentowanej przez właściwość Messages odpowiedniej instancji klasy ConversationThread.
  • Zwróć listę instancji ConversationThread.
using Aspose.Email.Mapi;
using Aspose.Email.Storage.Pst;

public List<ConversationThread> GroupMessagesByThread(PersonalStorage pst, FolderInfo folder)
{
    // Wynik
    var list = new List<ConversationThread>();
        
    foreach (var entryId in folder.EnumerateMessagesEntryId())
    {
        // Wyodrębnij właściwość PidTagConversationIndex i jej wartość nagłówka (22 bajty).
        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();
}

Utwórz metodę zapisywania wątku konwersacji w oddzielnym katalogu

Na koniec zapiszmy rozmowy w katalogach.

Dla każdej instancji ConversationThread wykonaj następujące czynności:

  • Utwórz osobny katalog z nazwą tematu wątku.
  • Wylicz identyfikatory we właściwości ConversationThread.Messages, dla każdego identyfikatora wyodrębnij wiadomość metodą ExtractMessage i zapisz wiadomość w utworzonym katalogu metodą 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;
    }
}

Uzyskaj bezpłatną licencję API

Możesz używać Aspose.Email for .NET bez ograniczeń ewaluacyjnych, korzystając z darmowej licencji tymczasowej.

Wniosek

W tym artykule pokazano, jak używać Aspose.Email do wyszukiwania wiadomości związanych z konwersacją w pliku PST. Dalsze eksplorowanie dokumentacji PidTagConversationIndex może również skomplikować implementację, dodając na przykład hierarchiczne sortowanie wiadomości konwersacji. Możesz dowiedzieć się więcej o Aspose.Email korzystając z dokumentacji. Jeśli masz jakieś pytania, możesz pisać na naszym forum.

Zobacz też