Microsoft Graph to Manage Mailboxes in C#

Microsoft Graph API 與 Aspose.Email for .NET 庫的集成使開發人員能夠輕鬆訪問和操作郵箱數據,執行如提取郵件、檢索文件夾層次結構和以不同格式保存電子郵件等操作。在本文中,我們將探討如何利用這一強大組合來處理和管理郵箱。

Microsoft Graph 簡介

Microsoft Graph 是微軟提供的一個綜合 API 平台,提供統一的端點以訪問廣泛的 Microsoft 服務和數據。它是訪問 Microsoft 365 中可用的海量數據的入口,包括 Outlook 郵箱、日曆、聯繫人、OneDrive、Teams 等。

使用 Microsoft Graph,開發人員可以構建與 Microsoft 雲生態系統中用戶數據和見解無縫交互的應用程序。這是通過提供輕鬆的身份驗證、授權和查詢數據的 RESTful APIs 和 SDK 實現的。

關於 Aspose.Email for .NET 庫

Aspose.Email for .NET 是一個功能豐富的庫,使開發人員能夠在其 .NET 應用程序中處理電子郵件文件和協議。它提供了一組強大的 API,用於以各種格式(如 MSG、EML 和 MBOX)創建、操作和轉換電子郵件消息。此外,該庫支持 SMTP、POP3 和 IMAP 等電子郵件協議,允許多樣化的郵件管理。

在本指南中,我們將使用 Aspose.Email 與 Microsoft Graph 進行交互,以編程方式處理郵箱數據。通過 Aspose.Email 的 GraphClient,我們可以通過與 Microsoft Graph 進行身份驗證來高效地執行郵箱操作。

要開始使用該庫,您需要將其集成到您的項目中。獲取 Aspose.Email for .NET 的最簡單方法是通過 NuGet 包管理器:

  • 在 Visual Studio 中打開您的項目。
  • 轉到工具 > NuGet 包管理器 > 管理解決方案的 NuGet 包。
  • 搜索 Aspose.Email
  • 選擇該包並單擊安裝。

或者,您可以使用包管理器控制台:

Install-Package Aspose.Email

您也可以直接從 Aspose 網站 下載最新版本的 API。

在 Azure 入口網站上配置您的應用程序

在我們深入代碼之前,至關重要的是在 Azure 入口網站中配置您的應用程序以啟用 Microsoft Graph 訪問。只需按照以下步驟操作:

  1. 創建 Azure Active Directory (AAD) 應用程序:

    • 轉到 Azure 入口網站
    • 轉到 Azure Active Directory > 應用程序註冊
    • 單擊 新註冊 創建新應用程序。
    • 提供名稱並根據需要設置重定向 URI。
    • 單擊 註冊 完成過程。
  2. 設置 API 權限:

    • 在您的註冊應用中,轉到 API 權限
    • 單擊 添加權限 > Microsoft Graph
    • 選擇 應用程序權限 以進行服務之間的調用。
    • 選擇必要的權限,如 Mail.ReadMail.ReadWriteUser.Read 等。
    • 單擊 添加權限 以應用。
  3. 創建客戶端密鑰:

    • 前往應用中的 證書和密鑰
    • 單擊 新客戶端密鑰 並提供描述。
    • 設置過期時間,然後單擊 添加
    • 記下生成的客戶端密鑰值,因為您稍後將需要它。
  4. 收集配置值:

    • 從應用的概覽頁面和密鑰部分獲取 租戶 ID客戶端 ID客戶端密鑰
    • 您將使用這些值進行身份驗證並與 Microsoft Graph 交互。

一旦您的應用程序配置完成,您就可以進行開發任務。

獲取訪問令牌並初始化 GraphClient

在深入郵箱操作之前,我們需要打開通往 Microsoft Graph 廣闊數據和服務生態系統的大門。這種訪問是通過 OAuth 2.0 訪問令牌授予的——一把數字鑰匙,授權您的應用程序代表用戶或服務與 Microsoft Graph 進行交互。想像一下,它是一個安全通行證,讓您進入一整個可能性的宇宙,從提取電子郵件到管理聯繫人等等。

步驟 1:設置配置文件

獲取令牌的第一步是設置一個配置文件,用於存儲基本詳細信息,如您的應用程序的 租戶 ID客戶端 ID客戶端密鑰。這些值是您的應用程序的憑據,並在與 Microsoft 服務器通信時充當標識符。

這是您的 JSON 配置的樣子:

{
    "Instance": "https://login.microsoftonline.com/{0}",
    "ApiUrl": "https://graph.microsoft.com/.default",
    "TenantId": "YOUR_TENANT_ID_HERE",
    "ClientId": "YOUR_APP_ID_HERE",
    "ClientSecret": "YOUR_CLIENT_SECRET_HERE",
    "UserId": "YOUR_ID_HERE"
}

步驟 2:將 JSON 配置映射到 C# 對象

現在,讓我們將這個配置轉換為我們的應用程序可以使用的 C# 對象。我們將讀取 JSON 文件並將其內容映射到 AuthenticationConfig 類,確保我們的應用程序知道在哪裡找到所需的關鍵信息。

class AuthenticationConfig
{
    public string Instance { get; set; }
    public string ApiUrl { get; set; }
    public string TenantId { get; set; }
    public string ClientId { get; set; }
    public string UserId { get; set; }
    public string Authority => string.Format(CultureInfo.InvariantCulture, Instance, TenantId);
    public string ClientSecret { get; set; }
    
    public static AuthenticationConfig ReadFromJsonFile(string path)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile(path);

        var configuration = builder.Build();
        return configuration.Get<AuthenticationConfig>();
    }
}

步驟 3:獲取訪問令牌

配置就位後,是時候獲取訪問令牌了。我們將實現一個 GraphTokenProvider 類,該類使用 Microsoft 身份驗證庫 (MSAL) 處理身份驗證過程。這個類處理了繁重的工作——與 Microsoft Graph 通信以獲取授權我們的應用程序的令牌。

class GraphTokenProvider : ITokenProvider
{
    private readonly IConfidentialClientApplication _app;
    private readonly string[] _scopes;
    private string? _token;
    
    public GraphTokenProvider(AuthenticationConfig config)
    {
        _app = ConfidentialClientApplicationBuilder.Create(config.ClientId)
            .WithClientSecret(config.ClientSecret)
            .WithAuthority(config.Authority)
            .Build();

        // In memory token caches (App and User caches)
        _app.AddInMemoryTokenCache();
        
        _scopes = new[] { config.ApiUrl }; 
    }

    public void Dispose()
    {
        throw new NotImplementedException();
    }

    public OAuthToken GetAccessToken()
    {
        return GetAccessToken(false);
    }

    public OAuthToken GetAccessToken(bool ignoreExistingToken)
    {
        if (!ignoreExistingToken && _token != null)
        {
            return new OAuthToken(_token);
        }

        _token = GetAccessTokenAsync().GetAwaiter().GetResult();
        return new OAuthToken(_token);
    }
    
    private async Task<string?> GetAccessTokenAsync()
    {
        AuthenticationResult? result;
        
        try
        {
            result = await _app.AcquireTokenForClient(_scopes)
                .ExecuteAsync();
            
            Console.WriteLine($"The token acquired from {result.AuthenticationResultMetadata.TokenSource} {Environment.NewLine}");
        }
        catch (MsalServiceException ex)
        {
            Console.WriteLine($"Error Acquiring Token:{Environment.NewLine}{ex}{Environment.NewLine}");
            result = null;
        }

        if (result == null) return null;
        _token = result.AccessToken;
        return result.AccessToken;
    }
}

步驟 4:初始化 GraphClient

最後,我們使用已獲取的令牌初始化 GraphClientGraphClient 作為我們與 Microsoft Graph 交互的橋樑,使我們能夠無縫地與用戶郵箱進行交互。

var config = AuthenticationConfig.ReadFromJsonFile("appsettings.json");
var tokenProvider = new GraphTokenProvider(config);

using var client = GraphClient.GetClient(tokenProvider, config.TenantId);
client.Resource = ResourceType.Users;
client.ResourceId = config.UserId;

獲取文件夾層次結構並按名稱檢索文件夾

一旦您獲得了對 Microsoft Graph 的訪問權限,就可以開始探索郵箱。在本節中,我們將深入檢索郵箱的文件夾層次結構,使您能夠按名稱訪問特定文件夾。

步驟 1:理解文件夾層次結構

導航文件夾結構

郵箱的結構是分層的,就像一棵樹。根文件夾分支成幾個子文件夾,每個子文件夾都包含自己的一組電子郵件,並且可能還有更多的子文件夾。這種嵌套結構使得電子郵件的有序管理和輕鬆導航成為可能。

讓我們定義並使用 FolderNode 類來表示層次結構中的每個文件夾:

// Represents a node in a folder hierarchy,
// extending the properties of FolderInfo and storing a collection of subfolders.
class FolderNode
{
    // Gets the FolderInfo object representing the folder information.
    public FolderInfo Folder { get; }
    
    // Gets the collection of subfolders contained within the current folder.
    public List<FolderNode?> SubFolders { get; }

    // Initializes a new instance of the FolderNode class with the specified FolderInfo object.
    public FolderNode(FolderInfo folder)
    {
        Folder = folder;
        SubFolders = new List<FolderNode?>();
    }
    
    // Prints all folders in a hierarchical manner starting from the current node.
    public void PrintHierarchy()
    {
        PrintFolderNode(this, 0);
    }

    private void PrintFolderNode(FolderNode node, int indentLevel)
    {
        // Print current folder node with indentation
        Console.WriteLine($"{new string(' ', indentLevel * 2)}{node}");

        // Recursively print subfolders
        foreach (var subFolder in node.SubFolders)
        {
            PrintFolderNode(subFolder, indentLevel + 1);
        }
    }

    // Get the folder Display Name.
    public override string ToString()
    {
        return $"{Folder.DisplayName} ({Folder.ContentCount})";
    }
}

要檢索完整的文件夾層次結構,我們將創建 FolderHierarchy 類,該類利用 GraphClient 來遞歸列出所有文件夾。以下是其工作原理:

static class FolderHierarchy
{
    // Retrieves all folders in the mailbox recursively and returns a hierarchical collection of FolderNode objects.
    public static List<FolderNode> Retrieve(IGraphClient client)
    {
        // Retrieve root folders
        var rootFolders = client.ListFolders();
        var allFolders = new List<FolderNode>();

        // Retrieve subfolders recursively
        foreach (var folder in rootFolders)
        {
            var folderNode = new FolderNode(folder);
            RetrieveSubFolders(client, folderNode);
            allFolders.Add(folderNode);
        }

        return allFolders;
    }

    // Retrieves subfolders recursively and adds them to the parent FolderNode's SubFolders property.
    private static void RetrieveSubFolders(IGraphClient client, FolderNode parentFolderNode)
    {
        if (parentFolderNode.Folder.HasSubFolders)
        {
            var subFolders = client.ListFolders(parentFolderNode.Folder.ItemId);
            
            foreach (var subFolder in subFolders)
            {
                var subFolderNode = new FolderNode(subFolder);
                RetrieveSubFolders(client, subFolderNode);
                parentFolderNode.SubFolders.Add(subFolderNode);
            }
        }
    }
}

步驟 2:檢索文件夾層次結構

使用 FolderHierarchy.Retrieve 方法,您可以輕鬆遍歷郵箱以揭示其文件夾結構。以下是如何實現這一點:

// Retrieve the folder hierarchy from the mailbox
var folderNodes = FolderHierarchy.Retrieve(client);

// Print the folder hierarchy in a structured format
foreach (var folderNode in folderNodes)
{
    folderNode.PrintHierarchy();
}

步驟 3:按名稱檢索文件夾

一旦檢索到文件夾層次結構,您可以按名稱定位特定的文件夾。無論您是否對訪問收件箱或任何自定義文件夾感興趣,此方法確保您可以快速找到它們:

// Specify the folder name you're looking for
string targetFolderName = "Inbox";

// Locate the target folder by name
var targetFolder = folderNodes.FirstOrDefault(
    folderNode => folderNode.Folder.DisplayName.Equals(targetFolderName, StringComparison.OrdinalIgnoreCase))
    ?.Folder;

列出指定文件夾中的郵件

一旦成功檢索文件夾層次結構,下一步是深入特定文件夾的內容。想像一下,您已經導航到收件箱;現在,您想查看它所包含的所有郵件。

在本節中,我們將探討如何使用 GraphClient 和 Aspose.Email for .NET 列出特定文件夾中的郵件。

一旦您擁有了文件夾,列出該文件夾中的郵件就變得簡單。GraphClient 提供了 ListMessages 方法來檢索文件夾中的所有郵件,然後您可以進行處理或顯示。

以下是列出指定文件夾郵件的代碼:

Console.WriteLine("Listing messages in the specified folder...");

// Call the client method to list messages in the selected folder
var messageInfoCollection = client.ListMessages(targetFolder.ItemId);

Console.WriteLine($"{targetFolderName}:");

// Print out the subject lines of the messages
foreach (var messageInfo in messageInfoCollection)
{
    Console.WriteLine($"     - {messageInfo.Subject}");
}

messageInfoCollection 包含每封電子郵件的基本詳細信息。這些信息可以用來顯示摘要、生成報告,甚至根據特定標準觸發警報。

結論

在本文中,我們探討了如何利用 Microsoft Graph 和 Aspose.Email for .NET 庫有效處理郵箱、導航文件夾層次結構以及列出特定文件夾中的郵件。通過遵循這些步驟,您可以構建強大的應用程序,無縫地與電子郵件數據互動,提供增強的功能和用戶體驗。

概念實踐

如果您渴望看到這些概念的實踐,可以下載一個功能完整的示例應用程序。該應用程序包括本文所描述的源代碼,並演示如何逐步實現這些功能。

訪問我們的 GitHub 倉庫以獲取示例應用程序:Aspose.Email for .NET - GraphApp 範例

通過 Microsoft Graph 處理郵箱提供了對電子郵件數據和管理能力的無與倫比的訪問。利用正確的工具和技術,您可以構建複雜的應用程序,提供有意義的見解並自動化複雜的任務,最終提高生產力和用戶滿意度。

免費試用

此外,Aspose.Email 提供全面的 文檔、廣泛的 API 參考 和各種免費的在線工具和 應用程序 來增強您的開發過程。開發人員還可以訪問免費的 支持論壇 以獲得社區幫助和見解,並通過 Aspose 博客 獲取最新的提示和教程。

參見