4

I'm trying to use MS Graph API to read emails from a specific mailbox.

var client = await GetClient(); //getting a client with client id, secret
var users = await client.Users.Request()
                 .Filter("startswith(displayName,'roger')")
                 .GetAsync(); //getting the users matching a criteria

var user = users.First(); //get the first user

//log the user name, this works fine
log.LogInformation("Found user " +  user.DisplayName);

//this is null
var messages = user.MailFolders?.FirstOrDefault();

I get all the correct data from the user I fetch here but the user mailFolders property is null.

Why is this?

We want to scan for emails in a specific mailbox and process those emails and attachments. and I thought this could be a proper way to do this. But I'm stuck on the above and the documentation on MS Graph and especially the .NET API's are so so.

Is it an authority thing, can I somehow increase the privilege of our AD application registration to get this privilege?

Or is there something else going on here?

Marc LaFleur
  • 31,987
  • 4
  • 37
  • 63
Roger Johansson
  • 22,764
  • 18
  • 97
  • 193
  • 1
    Could you check at [Graph Explorer](https://developer.microsoft.com/en-us/graph/graph-explorer) if the user account in question has an exchange email account? I usually use fiddler or a similar tool to trace calls to Graph and then troubleshoot using the Graph Explorer – Kalyan Krishna Mar 23 '19 at 09:54

1 Answers1

7

The Graph Client is just a wrapper around the REST API and it doesn't do lazy loading of objects.

The User object is coming from AAD while MailFolders comes from Exchange and each as it's own endpoints.

As you noted, you're Users request is working properly. In order to retrieve the user's MailFolders you need to take the Id or UserPrincipalName from the User and use it to make a sperate request for the MailFolders. You'll also need to make another request to get the messages:

// Get all users with a displayName of roger*
var users = await graphClient
    .Users
    .Request()
    .Filter("startswith(displayName,'roger')")
    .GetAsync();

// Get the first user's mail folders
var mailFolders = await graphClient
    .Users[users[0].Id] // first user's id
    .MailFolders
    .Request()
    .GetAsync();

// Get messages from the first mail folder
var messages = await graphClient
    .Users[users[0].Id] // first user'd id
    .MailFolders[mailFolders[0].Id] // first mail folder's id
    .Messages
    .Request()
    .GetAsync();

If you only care about the "well-known" mail folders, you can simplify this request by using the well-known name. For example, you can request the inbox like this:

// Get message from the user's inbox
var inboxMessages = await graphClient
    .Users[users[0].Id] // first user'd id
    .MailFolders["inbox"]
    .Messages
    .Request()
    .GetAsync();

Given that you're only using id values, you can optimize this by requesting only the id property:

// Get all users with a displayName of roger*
var users = await graphClient
    .Users
    .Request()
    .Select("id") // only get the id
    .Filter("startswith(displayName,'roger')")
    .GetAsync();

// Get the first user's mail folders
var mailFolders = await graphClient
    .Users[users[0].Id] // first user's id
    .MailFolders
    .Request()
    .Select("id") // only get the id
    .GetAsync();
Marc LaFleur
  • 31,987
  • 4
  • 37
  • 63
  • I wish that would work. but I get this build error with MS.Grap v4.47.0: error CS1061: 'IMailFolderMessagesCollectionPage' does not contain a definition for 'Messages' and no accessible extension method 'Messages' accepting a first argument of type 'IMailFolderMessagesCollectionPage' could be found – more urgent jest Nov 23 '22 at 03:06