使用 Microsoft Graph 进行 Microsoft 365 数据访问和管理
使用 Aspose.Email Graph Client 优化 Microsoft 365 数据访问和管理
Microsoft Graph 是一个用于访问 Microsoft 365 数据的 REST API。Aspose.Email for .NET 中的 Graph Client 实现允许通过我们的 API 访问 Microsoft Graph。在下面的示例中,我们将创建一个 MS Graph Client 实例,提供令牌。然后,我们将审查管理文件夹、更新、复制和删除它们的主要方法。消息、其内容和附件也可以使用我们的 MS Graph Client 进行访问或更改。管理类别、规则、笔记本和覆盖是 Aspose.Email 提供的 Microsoft Graph Client 的扩展功能。
使用 MSAL 在 .NET 中通过 IGraphClient 进行身份验证和请求
要与 Microsoft Graph 服务交互,您需要创建一个 IGraphClient 对象。认证后,此客户端允许您进行各种服务请求。该 GetClient 方法,用于创建 IGraphClient,需要一个 ITokenProvider 实现作为其第一个参数。此 ITokenProvider 负责提供必要的身份验证令牌。要获取令牌,我们将使用 Microsoft 身份验证库 (MSAL) 适用于 .NET。
以下是设置身份验证流程的方法:
步骤 1:设置身份验证
以下步骤将指导您如何获取授权令牌:
-
创建 AccessParameters 类。
定义一个 AccessParameters 类来存储您的凭据。
public class AccessParameters
{
public string TenantId { get; init; }
public string ClientId { get; init; }
public string ClientSecret { get; init; }
public string UserId { get; init; }
public Uri Authority => new ($"https://login.microsoftonline.com/{TenantId}");
public string ApiUrl => "https://graph.microsoft.com/.default";
}
-
添加 MSAL.NET 包**.
安装
Microsoft.Identity.ClientNuGet 包,其中包含进行身份验证所需的 MSAL.NET 二进制文件。 -
实现 ITokenProvider 接口。
创建一个
GraphTokenProvider实现该接口的类 ITokenProvider 接口。此类将使用 MSAL.NET 库来获取访问令牌。
using Microsoft.Identity.Client;
using Microsoft.Identity.Web;
using Aspose.Email.Clients;
public class GraphTokenProvider : ITokenProvider
{
private readonly IConfidentialClientApplication _app;
private readonly string[] _scopes;
private string? _token;
public GraphTokenProvider(AccessParameters accessParams)
{
_app = ConfidentialClientApplicationBuilder.Create(accessParams.ClientId)
.WithClientSecret(accessParams.ClientSecret)
.WithAuthority(accessParams.Authority)
.Build();
_app.AddInMemoryTokenCache();
_scopes = new[] { accessParams.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("Token acquired");
}
catch (MsalServiceException ex) when (ex.Message.Contains("AADSTS70011"))
{
Console.WriteLine("Scope provided is not supported");
result = null;
}
if (result == null) return null;
_token = result.AccessToken;
return result.AccessToken;
}
步骤 2:创建 ITokenProvider 实例
在定义了 GraphTokenProvider 类,您可以创建一个实例 AccessParameters 并使用它实例化 GraphTokenProvider.
var accessParams = new AccessParameters()
{
TenantId = "Your Tenant ID",
ClientId = "Your Client ID",
ClientSecret = "Your Client Secret",
UserId = "User's Object ID"
};
var tokenProvider = new GraphTokenProvider(accessParams);
步骤 3:使用 IGraphClient 发起请求
最后,使用 GraphTokenProvider 以创建已身份验证的 IGraphClient 并开始发起服务请求。
using var client = GraphClient.GetClient(tokenProvider, accessParams.TenantId);
client.Resource = ResourceType.Users;
client.ResourceId = accessParams.UserId;
完成这些步骤后,您的 IGraphClient 现已准备好使用身份验证请求与 Microsoft Graph 服务交互。
连接到 GCC High 端点
该 GraphClient 支持使用以下方式连接到 GCC High 端点 EndPoint 属性。以下代码示例演示如何配置 GraphClient 以连接到 GCC High 端点,以列出文件夹并检索邮件。
client.EndPoint = "https://graph.microsoft.us";
var folders = client.ListFolders();
string folderId = folders.Find(x => x.DisplayName == "Inbox").ItemId;
var msgs = client.ListMessages(folderId);
使用 IGraphClient 管理文件夹
列出文件夹
通过调用 ListFolders 通过 MS Graph 客户端的方法,可以获取文件夹列表。每个文件夹都有一组参数,例如 DisplayName,可在 FolderInfo 类型。
var folders = client.ListFolders();
foreach (var folder in folders)
{
Console.WriteLine(folder.DisplayName);
}
更新文件夹
要使用 MS Graph 客户端创建文件夹,请使用 CreateFolder 方法。您将获得一个 FolderInfo 对象以及访问 DisplayName、ItemId、HasSubFolders 等属性的可能性。
var folderInfo = client.CreateFolder("FolderName");
folderInfo.DisplayName = "FolderAnotherName";
client.UpdateFolder(folderInfo);
复制文件夹
CopyFolder 此方法是使用 MS Graph 复制文件夹对象的关键方法。
var folderInfo1 = client.CreateFolder("Folder1");
var folderInfo2 = client.CreateFolder("Folder2");
// copy Folder2 to Folder1
client.CopyFolder(folderInfo1.ItemId, folderInfo2.ItemId);
移动和删除文件夹
使用 MoveFolder 此方法用于移动文件夹,接受 newParentId 和 itemId 参数。 删除 此方法用于通过 ID 删除项。
var folderInfo1 = client.CreateFolder("Folder1");
var folderInfo2 = client.CreateFolder("Folder2");
// move Folder2 to Folder1
client.MoveFolder(folderInfo1.ItemId, folderInfo2.ItemId);
// delete Folder1
client.Delete(folderInfo1.ItemId)
使用 IGraphClient 管理邮件
MS Graph 客户端在 Aspose.Email for .NET 中实现,提供了一套管理邮件和附件的方法:
- List messages
- Fetch message
- Create message
- 发送 message
- CopyMessage message
- Move message
- CreateAttachment
- FetchAttachment
- DeleteAttachment
- ListAttachments
列出邮件
var folders = client.ListFolders();
foreach (var folder in folders)
{
if (folder.DisplayName.Equals("Inbox"))
{
// list messages in inbox
var inboxMessages = client.ListMessages(folder.ItemId);
foreach (var messageInfo in inboxMessages)
{
Console.WriteLine(messageInfo.Subject);
}
}
}
按发送日期过滤邮件
该 OrderBy 库集合中的该方法使您能够根据发送日期以不同的排序顺序(升序和降序)检索邮件。以下代码示例展示了如何按发送日期对邮件进行排序:
IGraphClient client = GraphClient.GetClient(provider, TenantId);
var builder = new GraphQueryBuilder();
// create orderby messages query 'DESC'
builder.SentDate.OrderBy(false);
var messagePageInfo = client.ListMessages(KnownFolders.Inbox, new PageInfo(10), builder.GetQuery());
var messages = messagePageInfo.Items;
builder.Clear();
// create orderby messages query 'ASC'
builder.SentDate.OrderBy(true);
messagePageInfo = client.ListMessages(KnownFolders.Inbox, new PageInfo(10), builder.GetQuery());
messages = messagePageInfo.Items;
使用分页支持枚举邮件
该 API 在列出邮件时支持分页和过滤。这对于邮件量大的邮箱尤其有帮助,因为它只检索必要的摘要信息,从而节省时间。
以下代码示例和步骤演示了如何使用分页和过滤功能从收件箱文件夹检索邮件。
- 首先,初始化客户端。
- 然后,设置每页显示的项目数,例如 10。
- 使用以下方式创建仅检索未读邮件的过滤器: GraphQueryBuilder 类。builder.IsRead.Equals(false) 设置了过滤未读邮件的条件。
- 调用 ListMessages 在客户端对象上调用此方法,指定文件夹(Inbox)和每页项目数(PageInfo(itemsPerPage))作为参数。它还传递查询对象以应用未读邮件过滤器。返回的 PageInfo 对象(pageInfo)在 Items 属性中包含当前页面检索到的邮件。
- 创建一个循环,持续执行直到到达最后一页(pageInfo.LastPage 为 false)。检索到的消息使用 messages.AddRange(pageInfo.Items) 添加到现有消息列表中。
// reading unread messages with paging
using var client = GraphClient.GetClient(tokenProvider, config.Tenant);
// paging option
var itemsPerPage = 10;
// create unread messages filter
GraphQueryBuilder builder = new GraphQueryBuilder();
builder.IsRead.Equals(false);
var query = builder.GetQuery();
// list messages
var pageInfo = client.ListMessages(KnownFolders.Inbox, new PageInfo(itemsPerPage), query);
var messages = pageInfo.Items;
while (!pageInfo.LastPage)
{
pageInfo = client.ListMessages(KnownFolders.Inbox, pageInfo.NextPage, query);
messages.AddRange(pageInfo.Items);
}
// set messages state as read
foreach (var message in messages)
{
client.SetRead(message.ItemId);
}
获取消息
var folders = client.ListFolders();
foreach (var folder in folders)
{
if (folder.DisplayName.Equals("Inbox"))
{
// list messages in inbox
var inboxMessages = client.ListMessages(folder.ItemId);
if (inboxMessages.Count > 0)
{
// fetch the first message in inbox
var msg = client.FetchMessage(inboxMessages[0].ItemId);
Console.WriteLine(msg.BodyHtml);
}
}
}
创建消息
var msg = new MapiMessage(OutlookMessageFormat.Unicode)
{
Subject = "My message",
Body = "Hi, it is my message"
};
msg.Recipients.Add("sam@to.com", "Sam", MapiRecipientType.MAPI_TO);
// create message in inbox
client.CreateMessage(KnownFolders.Inbox, msg);
发送消息
// prepare the message
var msg = new MapiMessage(OutlookMessageFormat.Unicode)
{
Subject = "My message",
Body = "Hi, it is my message"
};
msg.Recipients.Add("sam@to.com", "Sam", MapiRecipientType.MAPI_TO);
msg.SetProperty(KnownPropertyList.SenderName, "John");
msg.SetProperty(KnownPropertyList.SentRepresentingEmailAddress, "John@from.com");
// send message
client.Send(msg);
发送草稿消息
// prepare the message
var msg = new MapiMessage(OutlookMessageFormat.Unicode)
{
Subject = "My message",
Body = "Hi, it is my message"
};
msg.Recipients.Add("sam@to.com", "Sam", MapiRecipientType.MAPI_TO);
msg.SetProperty(KnownPropertyList.SenderName, "John");
msg.SetProperty(KnownPropertyList.SentRepresentingEmailAddress, "John@from.com");
// add message to Draft folder
var draftMessage = client.CreateMessage(KnownFolders.Drafts, msg);
// send a draft message
client.Send(draftMessage.ItemId);
发送 EML 消息
使用 MailMessage 对象创建和发送电子邮件非常简单。以下代码示例演示了如何使用 Graph API 创建并发送电子邮件:
// prepare the message
var eml = new MailMessage
{
From = "from@domain.com",
To = "to1@domain.com, to2@domain.com",
Subject = "New message",
HtmlBody = "<html><body>This is the HTML body</body></html>"
};
// send the message
graphClient.Send(eml);
graphClient.Create(KnownFolders.Inbox, eml);
复制邮件
// copy message to Inbox folder
var copiedMsg = client.CopyMessage(KnownFolders.Inbox, msg.ItemId);
移动邮件
// move message to Inbox folder
var movedMsg = client.MoveMessage(KnownFolders.Inbox, msg.ItemId);
管理附件
// create an attachment
var attachment = new MapiAttachment();
attachment.SetProperty(KnownPropertyList.DisplayName, "My Attachment");
attachment.SetProperty(KnownPropertyList.AttachDataBinary, new byte[1024]);
// add an attachment to message
var createdAttachment = client.CreateAttachment(messageInfo.ItemId, attachment);
// fetch a message attachment
var fetchedAttachment = client.FetchAttachment(createdAttachment.ItemId);
// delete a message attachment
client.DeleteAttachment(createdAttachment.ItemId);
// list the message attachments
var attachments = client.ListAttachments(messageInfo.ItemId);
使用 Graph 客户端管理 Outlook 项目
管理日历事件
Aspose.Email 提供用于访问、管理和交互日历事件的 API。为此,它在以下位置提供了相应的方法: IGraphClient 接口:
- ListCalendars() - 检索日历信息集合。
- ListCalendarItems(string id) - 检索与指定日历 ID 关联的日历项集合。
- FetchCalendarItem(string id) - 根据提供的 ID 检索特定日历项。
- CreateCalendarItem(string calId, MapiCalendar mapiCalendar) - 在指定的日历中创建新日历项。
- UpdateCalendarItem(MapiCalendar mapiCalendar) - 更新现有日历项。
- UpdateCalendarItem(MapiCalendar mapiCalendar, UpdateSettings updateSettings) - 使用指定的更新设置更新现有日历项。
以下代码示例演示了如何使用 Aspose.Email 提供的方法在 Microsoft Graph API 客户端中与日历事件交互:
// List Calendars
CalendarInfoCollection calendars = graphClient.ListCalendars();
// List Calendar Items
MapiCalendarCollection calendarItems = graphClient.ListCalendarItems("calendarId");
// Fetch Calendar Item
MapiCalendar calendarItem = graphClient.FetchCalendarItem("calendarItemId");
// Create Calendar Item
MapiCalendar newCalendarItem = new MapiCalendar(
location: "Conference Room",
summary: "Team Meeting",
description: "Discuss project status and updates.",
startDate: startDate,
endDate: endDate
);
MapiCalendar createdCalendarItem = graphClient.CreateCalendarItem("calendarId", newCalendarItem);
// Update Calendar Item
createdCalendarItem.Location = "Zoom Meeting";
MapiCalendar updatedCalendarItem = graphClient.UpdateCalendarItem(createdCalendarItem);
管理类别
要使用 Aspose.Email for .NET 通过 MS Graph 管理类别,请使用以下方法:
// create a custom category with Orange color
var category = client.CreateCategory("My custom category", CategoryPreset.Preset1);
// fetch a category
var fetchedCategory = client.FetchCategory(category.Id);
// update category (change color to brown)
fetchedCategory.Preset = CategoryPreset.Preset2;
var updatedCategory = client.UpdateCategory(fetchedCategory);
// list available categories
var categories = client.ListCategories();
foreach (var cat in categories)
{
Console.WriteLine(cat.DisplayName);
}
// delete a category
client.Delete(fetchedCategory.Id);
管理联系人
Aspose.Email 提供用于访问、管理和交互联系人项的 API。为此,它在以下位置提供了相应的方法: IGraphClient 接口:
- ListContacts(string id) - 检索与指定文件夹 ID 关联的 MAPI 联系人集合。
- FetchContact(string id) - 根据提供的项目 ID 检索特定联系人。
- CreateContact(string folderId, MapiContact contact) - 在指定文件夹中创建新联系人。
- UpdateContact(MapiContact contact) - 更新现有联系人。
以下代码示例演示了如何使用 Aspose.Email 提供的方法在 Microsoft Graph API 客户端中与联系人交互:
// List Contacts
MapiContactCollection contacts = graphClient.ListContacts("contactFolderId");
// Fetch Contact
MapiContact contact = graphClient.FetchContact("contactId");
// Create Contact
MapiContact newContact = new MapiContact("Jane Smith", "jane.smith@example.com", "XYZ Corporation", "777-888-999");
MapiContact createdContact = graphClient.CreateContact("contactFolderId", newContact);
// Update Contact
createdContact.Telephones.PrimaryTelephoneNumber = "888-888-999";
MapiContact updatedContact = graphClient.UpdateContact(createdContact);
管理覆盖
要使用 Aspose.Email for .NET 通过 MS Graph 管理覆盖,请使用以下方法:
// Create an user's override
var userOverride = client.CreateOrUpdateOverride
(new MailAddress("JohnBrown@someorg.com", "JohnBrown"), ClassificationType.Focused);
// list the overrides
var overrides = client.ListOverrides();
// update override
userOverride.Sender.DisplayName = "John Brown";
var updatedOverride = client.UpdateOverride(userOverride);
// delete override
client.Delete(updatedOverride.Id);
管理规则
要使用 Aspose.Email for .NET 通过 MS Graph 管理规则,请使用以下方法:
// Create a rule
var rule = PrepareRule("user@someorg.com", "User");
var createdRule = client.CreateRule(rule);
// List all rules defined for Inbox
var rules = client.ListRules();
// Fetch a rule
var fetchedRule = client.FetchRule(createdRule.RuleId);
// Update a rule
fetchedRule.DisplayName = "Renamed rule";
fetchedRule.IsEnabled = false;
var updatedRule = client.UpdateRule(createdRule);
// Delete a rule
client.Delete(updatedRule.RuleId);
InboxRule PrepareRule(string email, string displayName)
{
var rule = new InboxRule()
{
DisplayName = "My rule",
Priority = 1,
IsEnabled = true,
Conditions = new RulePredicates(),
Actions = new RuleActions()
};
rule.Conditions.ContainsSenderStrings = new StringCollection { displayName };
rule.Actions.ForwardToRecipients = new MailAddressCollection
{ new MailAddress(email, displayName, true) };
rule.Actions.StopProcessingRules = true;
return rule;
}
管理笔记本
要使用 Aspose.Email for .NET 通过 MS Graph 管理笔记本,请使用以下方法:
// create a OneNote notebook
var newNotebook = new Notebook()
{
DisplayName = "My Notebook"
};
var createdNotebook = client.CreateNotebook(newNotebook);
// fetch a notebook
var fetchedNotebook = client.FetchNotebook(createdNotebook.Id);
// list the notebooks
var notebooks = client.ListNotebooks();
Microsoft Graph 中的任务管理
Aspose.Email 为开发者提供 API,通过以下方法访问、管理和交互用户的任务和任务列表 IGraphClient 接口:
- ListTaskLists() - 检索任务列表信息的集合。
- GetTaskList(string id) - 根据提供的 ID 检索特定任务列表。
- DeleteTaskList(string id) - 删除指定的任务列表。 -ListTasks(string id) - 检索与指定任务列表 ID 关联的一组任务。
- FetchTask(string id) - 根据提供的 ID 检索特定任务。
- CreateTask(MapiTask task, string taskListUri) - 在指定的任务列表中创建新任务。
- UpdateTask(MapiTask task) - 使用提供的信息更新现有任务。
- UpdateTask(MapiTask task, UpdateSettings updateSettings) - 使用指定的更新设置更新现有任务。
下面的代码示例演示了如何管理任务列表:
// List Task Lists
var taskLists = graphClient.ListTaskLists();
foreach (var tList in taskLists)
{
Console.WriteLine($"Task List: {tList.DisplayName}");
}
// Get Task List
var taskList = graphClient.GetTaskList("taskListId");
// Delete Task List
graphClient.DeleteTaskList("taskListId");
下面的代码示例演示了如何管理任务:
// List Tasks in a Task List
MapiTaskCollection tasks = graphClient.ListTasks("taskListId");
// Fetch Task
MapiTask task = graphClient.FetchTask("taskId");
// Create Task
var newTask = new MapiTask
{
Subject = "New Task",
DueDate = new DateTime(2023, 12, 31),
Status = MapiTaskStatus.NotStarted
};
MapiTask createdTask = graphClient.CreateTask(newTask, "taskListUri");
// Update Task
createdTask.Subject = "Updated Task Subject";
MapiTask updatedTask = graphClient.UpdateTask(createdTask);
// Update Task with UpdateSettings
var updateSettings = new UpdateSettings { SkipAttachments = true };
MapiTask updatedTaskWithSettings = graphClient.UpdateTask(createdTask, updateSettings);