Microsoft Graph для управления почтовыми ящиками на C#

Интеграция Microsoft Graph API и библиотеки Aspose.Email для .NET с приложением электронной почты позволяет разработчикам легко получать и манипулировать данными почтового ящика, выполнять такие операции, как получение сообщений, извлечение иерархий папок и сохранение электронных писем в различных форматах. В этой статье мы исследуем, как использовать это мощное сочетание для обработки и управления почтовыми ящиками.

Презентация Microsoft Graph

Microsoft Graph — это комплексная платформа API, предоставляемая Microsoft, которая предлагает унифицированную конечную точку для доступа к широкому спектру сервисов и данных Microsoft. Она служит шлюзом к обширным данным, доступным в Microsoft 365, включая почтовые ящики Outlook, календари, контакты, OneDrive, Teams и многое другое.

С помощью Microsoft Graph разработчики могут создавать приложения, которые бесшовно взаимодействуют с пользовательскими данными и аналитикой в экосистеме облака Microsoft. Это достигается с помощью RESTful API и SDK, которые обеспечивают средства для аутентификации, авторизации и запроса данных с легкостью.

Об библиотеке Aspose.Email для .NET

Aspose.Email для .NET — это богатая функциональностью библиотека, которая позволяет разработчикам работать с электронными файлами и протоколами в своих .NET-приложениях. Она предоставляет надежный набор API для создания, манипуляции и конвертации электронных сообщений в различных форматах, таких как MSG, EML и MBOX. Кроме того, библиотека поддерживает электронные протоколы, такие как SMTP, POP3 и IMAP, что позволяет универсально управлять электронной почтой.

В этом руководстве мы будем использовать Aspose.Email для взаимодействия с Microsoft Graph, программно обрабатывая данные почтового ящика. С помощью GraphClient из Aspose.Email мы можем эффективно выполнять операции с почтовым ящиком, аутентифицируясь с помощью Microsoft Graph.

Чтобы начать использовать библиотеку, вам нужно интегрировать ее в ваш проект. Самый простой способ получить Aspose.Email для .NET — это через Менеджер пакетов NuGet:

  • Откройте свой проект в Visual Studio.
  • Перейдите в раздел Инструменты > Менеджер пакетов NuGet > Управление пакетами NuGet для решения.
  • Найдите Aspose.Email.
  • Выберите пакет и нажмите Установить.

В качестве альтернативы вы можете использовать Консоль менеджера пакетов:

Install-Package Aspose.Email

Вы также можете скачать последнюю версию API напрямую с сайта Aspose website.

Настройте ваше приложение на портале Azure

Прежде чем мы углубимся в код, важно настроить ваше приложение на портале Azure для включения доступа к Microsoft Graph. Просто выполните следующие шаги:

  1. Создайте приложение Azure Active Directory (AAD):

    • Перейдите на портал Azure.
    • Перейдите в Azure Active Directory > Регистрация приложений.
    • Нажмите Новая регистрация, чтобы создать новое приложение.
    • Укажите имя и установите URI перенаправления, если это необходимо.
    • Нажмите Зарегистрировать, чтобы завершить процесс.
  2. Установите разрешения API:

    • В вашем зарегистрированном приложении перейдите в Разрешения API.
    • Нажмите Добавить разрешение > Microsoft Graph.
    • Выберите Разрешения приложения для серверных вызовов.
    • Выберите необходимые разрешения, такие как Mail.Read, Mail.ReadWrite, User.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 Authentication Library (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();

        // Кэши токенов в памяти (кэши приложений и пользователей)
        _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($"Токен получен из {result.AuthenticationResultMetadata.TokenSource} {Environment.NewLine}");
        }
        catch (MsalServiceException ex)
        {
            Console.WriteLine($"Ошибка при получении токена:{Environment.NewLine}{ex}{Environment.NewLine}");
            result = null;
        }

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

Шаг 4: Инициализация GraphClient

Наконец, мы инициализируем GraphClient, используя полученный токен. GraphClient действует как наш мост к 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, чтобы представить каждую папку в иерархии:

// Представляет узел в иерархии папок,
// расширяя свойства FolderInfo и храня набор подпапок.
class FolderNode
{
    // Получает объект FolderInfo, представляющий информацию о папке.
    public FolderInfo Folder { get; }
    
    // Получает коллекцию подпапок, содержащихся в текущей папке.
    public List<FolderNode?> SubFolders { get; }

    // Инициализирует новый экземпляр класса FolderNode с указанным объектом FolderInfo.
    public FolderNode(FolderInfo folder)
    {
        Folder = folder;
        SubFolders = new List<FolderNode?>();
    }
    
    // Печатает все папки в иерархическом порядке, начиная с текущего узла.
    public void PrintHierarchy()
    {
        PrintFolderNode(this, 0);
    }

    private void PrintFolderNode(FolderNode node, int indentLevel)
    {
        // Печатает текущий узел папки с отступом
        Console.WriteLine($"{new string(' ', indentLevel * 2)}{node}");

        // Рекурсивно печатает подпапки
        foreach (var subFolder in node.SubFolders)
        {
            PrintFolderNode(subFolder, indentLevel + 1);
        }
    }

    // Получает имя отображения папки.
    public override string ToString()
    {
        return $"{Folder.DisplayName} ({Folder.ContentCount})";
    }
}

Чтобы получить полную иерархию папок, мы создадим класс FolderHierarchy, который использует GraphClient, чтобы рекурсивно перечислить все папки. Вот как это работает:

static class FolderHierarchy
{
    // Извлекает все папки в почтовом ящике рекурсивно и возвращает иерархическую коллекцию объектов FolderNode.
    public static List<FolderNode> Retrieve(IGraphClient client)
    {
        // Извлекаем корневые папки
        var rootFolders = client.ListFolders();
        var allFolders = new List<FolderNode>();

        // Извлекаем подпапки рекурсивно
        foreach (var folder in rootFolders)
        {
            var folderNode = new FolderNode(folder);
            RetrieveSubFolders(client, folderNode);
            allFolders.Add(folderNode);
        }

        return allFolders;
    }

    // Извлекает подпапки рекурсивно и добавляет их в свойство SubFolders родительского узла FolderNode.
    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, вы можете без особых усилий пройти через почтовый ящик, чтобы узнать его структуру папок. Вот как это можно сделать:

// Извлекаем иерархию папок из почтового ящика
var folderNodes = FolderHierarchy.Retrieve(client);

// Печатаем иерархию папок в структурированном формате
foreach (var folderNode in folderNodes)
{
    folderNode.PrintHierarchy();
}

Шаг 3: Извлечение папок по имени

После того как иерархия папок была извлечена, вы можете быстро найти конкретные папки по имени. Независимо от того, хотите ли вы получить доступ к папке Входящие или любой другой пользовательской папке, этот метод гарантирует, что вы сможете легко их найти:

// Укажите имя папки, которую вы ищете
string targetFolderName = "Входящие";

// Найдите целевую папку по имени
var targetFolder = folderNodes.FirstOrDefault(
    folderNode => folderNode.Folder.DisplayName.Equals(targetFolderName, StringComparison.OrdinalIgnoreCase))
    ?.Folder;

Список сообщений в указанной папке

С успешно извлеченной иерархией папок следующим шагом будет погружение в содержимое конкретных папок. Представьте, что вы навигировали в свою папку Входящие; теперь вы хотите просмотреть все сообщения, которые она содержит.

В этом разделе мы рассмотрим, как перечислить сообщения внутри конкретной папки, используя GraphClient и Aspose.Email для .NET.

Как только у вас есть папка, перечисление сообщений в ней является простым делом. GraphClient предоставляет метод ListMessages для извлечения всех сообщений в папке, которые вы затем можете обработать или отобразить.

Вот код для перечисления сообщений из указанной папки:

Console.WriteLine("Перечисление сообщений в указанной папке...");

// Вызовите метод клиента, чтобы перечислить сообщения в выбранной папке
var messageInfoCollection = client.ListMessages(targetFolder.ItemId);

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

// Печатаем темы электронных писем
foreach (var messageInfo in messageInfoCollection)
{
    Console.WriteLine($"     - {messageInfo.Subject}");
}

messageInfoCollection содержит основную информацию о каждом электронном письме. Эта информация может быть использована для отображения резюме, генерации отчетов или даже триггеров оповещений на основе определенных критериев.

Заключение

В этой статье мы рассмотрели, как использовать возможности Microsoft Graph и библиотеки Aspose.Email для .NET для эффективной обработки почтовых ящиков, навигации по иерархиям папок и перечисления сообщений в конкретных папках. Следуя этим шагам, вы можете создавать надежные приложения, которые бесшовно взаимодействуют с данными электронной почты, предоставляя расширенные возможности и пользовательский опыт.

Концепции в действии

Если вы хотите увидеть эти концепции в действии, вы можете скачать полностью функциональный пример работающего приложения. Это приложение включает исходный код, описанный в этой статье, и демонстрирует, как пошагово реализовать эти функции.

Посетите наш репозиторий на GitHub, чтобы получить доступ к образцу приложения: Aspose.Email для .NET - Пример GraphApp.

Обработка почтовых ящиков через Microsoft Graph предлагает беспрецедентный доступ к данным электронной почты и возможностям управления. С правильными инструментами и техниками вы можете создавать сложные приложения, которые предоставляют значимую информацию и автоматизируют сложные задачи, тем самым повышая продуктивность и удовлетворенность пользователей.

Попробуйте бесплатно

Кроме того, Aspose.Email предоставляет всестороннюю документацию, обширную API-справку и разнообразные бесплатные онлайн-инструменты и приложения, чтобы улучшить ваш процесс разработки. Разработчики также могут получить доступ к бесплатному форуму поддержки для получения помощи и идей от сообщества и оставаться в курсе последних советов и учебников через блог Aspose.

Смотрите также