Microsoft 365 Data Access and Management with Microsoft Graph
Optimize Microsoft 365 Data Access and Management with Aspose.Email Graph Client
Microsoft Graph is a REST API to access the Microsoft 365 data. The implementation of Graph Client in Aspose.Email for .NET allows the access to Microsoft Graph from our API. In the examples below, we will create an instance of MS Graph Client, providing the token. Then, we will examine the main methods to manage folders, update, copy and delete them. Messages, their content and attachments can also be accessed or changed with our MS Graph Client. Managing categories, rules, notebooks and overrides is an extended feature of Microsoft Graph Client by Aspose.Email.
Authenticate and Request with IGraphClient Using MSAL in .NET
To interact with Microsoft Graph services, you’ll need to create an IGraphClient object. Once authenticated, this client allows you to make various service requests. The GetClient method, which creates the IGraphClient
, requires an ITokenProvider implementation as its first parameter. This ITokenProvider
is responsible for providing the necessary authentication token. To obtain the token, we’ll use the Microsoft Authentication Library (MSAL) for .NET.
Here’s how to set up the authentication process:
Step 1: Setting Up the Authentication
The following steps will guide you on how to obtain an authorization token:
-
Create the AccessParameters Class.
Define an AccessParameters class to store your credentials.
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";
}
-
Add the MSAL.NET Package.
Install the
Microsoft.Identity.Client
NuGet package, which contains the MSAL.NET binaries needed for authentication. -
Implement the ITokenProvider Interface.
Create a
GraphTokenProvider
class that implements the ITokenProvider interface. This class will use the MSAL.NET library to acquire an access token.
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;
}
Step 2: Create an ITokenProvider Instance
After defining the GraphTokenProvider
class, you can create an instance of AccessParameters
and use it to instantiate the 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);
Step 3: Make Requests with IGraphClient
Finally, use the GraphTokenProvider
to create an authenticated IGraphClient and start making service requests.
using var client = GraphClient.GetClient(tokenProvider, accessParams.TenantId);
client.Resource = ResourceType.Users;
client.ResourceId = accessParams.UserId;
With these steps completed, your IGraphClient
is now ready to interact with Microsoft Graph services using authenticated requests.
Connecting to GCC High Endpoints
The GraphClient supports connecting to GCC High endpoints by using the EndPoint property. The following code sample demonstrates how to configure the GraphClient to connect to the GCC High endpoint for listing folders and retrieving messages.
client.EndPoint = "https://graph.microsoft.us";
var folders = client.ListFolders();
string folderId = folders.Find(x => x.DisplayName == "Inbox").ItemId;
var msgs = client.ListMessages(folderId);
Manage Folders with IGraphClient
List Folders
By calling ListFolders method from MS Graph Client, its possible to get the list of folders. Each folder has a set of parameters like DisplayName, which can be read in FolderInfo type.
var folders = client.ListFolders();
foreach (var folder in folders)
{
Console.WriteLine(folder.DisplayName);
}
Update Folders
To create folder with MS Graph Client, use CreateFolder method. You will get a FolderInfo object and the possibility to access DisplayName, ItemId, HasSubFolders and other properties.
var folderInfo = client.CreateFolder("FolderName");
folderInfo.DisplayName = "FolderAnotherName";
client.UpdateFolder(folderInfo);
Copy Folders
CopyFolder method is the key method to copy the folder object with MS Graph.
var folderInfo1 = client.CreateFolder("Folder1");
var folderInfo2 = client.CreateFolder("Folder2");
// copy Folder2 to Folder1
client.CopyFolder(folderInfo1.ItemId, folderInfo2.ItemId);
Move and Delete Folders
Use MoveFolder method is used to move the folder, it accepts newParentId and itemId. Delete method is used to delete a method by 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)
Manage Messages with IGraphClient
MS Graph Client, implemented in Aspose.Email for .NET, provides a set of methods to manage messages and attachments:
- List messages
- Fetch message
- Create message
- Send message
- CopyMessage message
- Move message
- CreateAttachment
- FetchAttachment
- DeleteAttachment
- ListAttachments
List Messages
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);
}
}
}
Filter Messages by Sent Date
The OrderBy method from the library collection enables you to retrieve messages with different sorting orders (ascending and descending) based on the date they were sent. The following code sample shows how to order messages by their sent date:
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;
Enumerate Messages with Paging Support
The API allows paging and filtering of the messages when listing them. It is especially helpful for mailboxes with a high volume of messages, as it saves time by retrieving only the necessary summary information.
The code sample and the steps below demonstrate how to retrieve messages from the Inbox folder using paging and filtering features.
- First, initiate the client.
- Then, set the number of items to display per page, for example, 10.
- Create a filter to only retrieve unread messages using the GraphQueryBuilder class. The builder.IsRead.Equals(false) is setting the condition for filtering unread messages.
- Call the ListMessages method on the client object, specifying the folder (Inbox) and the items per page (PageInfo(itemsPerPage)) as parameters. It also passes the query object to apply the unread messages filter. The returned PageInfo object (pageInfo) contains the retrieved messages for the current page in the Items property.
- Create a loop that continues until the last page is reached (pageInfo.LastPage is false). The retrieved messages are added to the existing messages list using 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);
}
Fetch Messages
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);
}
}
}
Create Messages
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);
Send Messages
// 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);
Send Draft Messages
// 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);
Send EML Messages
Creating and sending emails is easy using the MailMessage object. The following code sample demonstrates how to create and send an email message using 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 Messages
// copy message to Inbox folder
var copiedMsg = client.CopyMessage(KnownFolders.Inbox, msg.ItemId);
Move Messages
// move message to Inbox folder
var movedMsg = client.MoveMessage(KnownFolders.Inbox, msg.ItemId);
Manage Attachments
// 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);
Manage Outlook Items with Graph Client
Manage Calendar Events
Aspose.Email provides APIs to access, manage, and interact with calendar events. For these purposes, it offers the following methods in the IGraphClient interface:
- ListCalendars() - Retrieves a collection of calendar information.
- ListCalendarItems(string id) - Retrieves a collection of calendar items associated with the specified calendar ID.
- FetchCalendarItem(string id) - Retrieves a specific calendar item based on the provided ID.
- CreateCalendarItem(string calId, MapiCalendar mapiCalendar) - Creates a new calendar item in the specified calendar.
- UpdateCalendarItem(MapiCalendar mapiCalendar) - Updates an existing calendar item.
- UpdateCalendarItem(MapiCalendar mapiCalendar, UpdateSettings updateSettings) - Updates an existing calendar item with specified update settings.
The following code sample demonstrates how to interact with calendar events in a Microsoft Graph API client using the methods provided by Aspose.Email:
// 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);
Manage Categories
To manage categories with MS Graph by Aspose.Email for .NET, use the following methods:
// 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);
Manage Contacts
Aspose.Email provides APIs to access, manage, and interact with contact items. For these purposes, it offers the following methods in the IGraphClient interface:
- ListContacts(string id) - Retrieves a collection of MAPI contacts associated with the specified folder ID.
- FetchContact(string id) - Retrieves a specific contact based on the provided item ID.
- CreateContact(string folderId, MapiContact contact) - Creates a new contact in the specified folder.
- UpdateContact(MapiContact contact) - Updates an existing contact.
The following code sample demonstrates how to interact with contacts in a Microsoft Graph API client using the methods provided by Aspose.Email:
// 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);
Manage Overrides
To manage overrides with MS Graph by Aspose.Email for .NET, use the following methods:
// 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);
Manage Rules
To manage rules with MS Graph by Aspose.Email for .NET, use the following methods:
// 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;
}
Manage Notebooks
To manage notebooks with MS Graph by Aspose.Email for .NET, use the following methods:
// 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();
Tasks Management in Microsoft Graph
Aspose.Email provides developers with APIs to access, manage, and interact with users’ tasks and task lists using the following methods of the IGraphClient interface:
- ListTaskLists() - Retrieves a collection of task list information.
- GetTaskList(string id) - Retrieves a specific task list based on the provided ID.
- DeleteTaskList(string id) - Deletes the specified task list. -ListTasks(string id) - Retrieves a collection of tasks associated with the specified task list ID.
- FetchTask(string id) - Retrieves a specific task based on the provided ID.
- CreateTask(MapiTask task, string taskListUri) - Creates a new task in the specified task list.
- UpdateTask(MapiTask task) - Updates an existing task with the provided information.
- UpdateTask(MapiTask task, UpdateSettings updateSettings) - Updates an existing task with specified update settings.
The following code sample demonstrates how to manage task lists:
// 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");
The following code sample demonstrates how to manage tasks:
// 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);