2
votes

I created a C# console application to send email using Microsoft Graph API. On adding Mail.Send Application Permission, it works fine. But, because of company requirements, I was asked to use Mail.Send Delegated Permission instead and with that permission I don't see it working and I see this error:

enter image description here

Are there any steps I should consider doing after adding Mail.Send Delegated Permission in order to get this working?

enter image description here

Here is my code:

    static void Main(string[] args)
    {
        // Azure AD APP
        string clientId = "<client Key Here>";
        string tenantID = "<tenant key here>";
        string clientSecret = "<client secret here>";

        Task<GraphServiceClient> callTask = Task.Run(() => SendEmail(clientId, tenantID, clientSecret));
        // Wait for it to finish
        callTask.Wait();
        // Get the result
        var astr = callTask;
    }

    public static async Task<GraphServiceClient> SendEmail(string clientId, string tenantID, string clientSecret)
    {

        var confidentialClientApplication = ConfidentialClientApplicationBuilder
            .Create(clientId)
            .WithTenantId(tenantID)
            .WithClientSecret(clientSecret)
            .Build();

        var authProvider = new ClientCredentialProvider(confidentialClientApplication);       

        var graphClient = new GraphServiceClient(authProvider);

        var message = new Message
            {
                Subject = subject,
                Body = new ItemBody
                {
                    ContentType = BodyType.Text,
                    Content = content
                },
                ToRecipients = new List<Recipient>()
                {
                    new Recipient
                    {
                        EmailAddress = new EmailAddress { Address = recipientAddress }
                    }
                }
            };

         var saveToSentItems = true;

         await _graphClient.Users[<userprincipalname>]
                                .SendMail(message, saveToSentItems)
                                .Request()
                                .PostAsync();

        return graphClient;

    }

UPDATE:

Based on below answer, I updated code as follows:

var publicClientApplication = PublicClientApplicationBuilder
            .Create("<client-id>")
            .WithTenantId("<tenant-id>")
            .Build();

            var authProvider = new UsernamePasswordProvider(publicClientApplication);

var secureString = new NetworkCredential("", "<password>").SecurePassword;

User me = await graphClient.Me.Request()
                .WithUsernamePassword("<username>", secureString)
                .GetAsync();

I enabled "Allow public client flows" to fix an exception.

enter image description here

And now I see another exception: Insufficient privileges to complete the operation.

What am I missing?

UPDATE: Currently I see this exception with no changes in the code:

enter image description here

1

1 Answers

2
votes

The code you provided shows you use client credential flow to do the authentication. When you use Mail.Send Application permission, use client credential flow is ok. But if you use Mail.Send Delegated permission, we can not use client credential. You should use username/password flow to do authentication.

=================================Update===================================

Below is my code:

using Microsoft.Graph;
using Microsoft.Graph.Auth;
using Microsoft.Identity.Client;
using System;
using System.Collections.Generic;
using System.Security;

namespace ConsoleApp34
{
    class Program
    {
        static async System.Threading.Tasks.Task Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            var publicClientApplication = PublicClientApplicationBuilder
            .Create("client id")
            .WithTenantId("tenant id")
            .Build();

            string[] scopes = new string[] { "mail.send" };

            UsernamePasswordProvider authProvider = new UsernamePasswordProvider(publicClientApplication, scopes);

            GraphServiceClient graphClient = new GraphServiceClient(authProvider);

            var message = new Message
            {
                Subject = "Meet for lunch?",
                Body = new ItemBody
                {
                    ContentType = BodyType.Text,
                    Content = "The new cafeteria is open."
                },
                ToRecipients = new List<Recipient>()
                {
                    new Recipient
                    {
                        EmailAddress = new EmailAddress
                        {
                            Address = "to email address"
                        }
                    }
                }
            };

            var securePassword = new SecureString();
            foreach (char c in "your password")
                securePassword.AppendChar(c);

            var saveToSentItems = true;

            await graphClient.Me
                    .SendMail(message, saveToSentItems)
                    .Request().WithUsernamePassword("your email", securePassword)
                    .PostAsync();
        }
    }
}

The reason for your error message Insufficient privileges to complete the operation is you use the code:

User me = await graphClient.Me.Request()
                .WithUsernamePassword("<username>", secureString)
                .GetAsync();

This code is used to get the user(me)'s information but not send email, you haven't added the permission to the app. So it will show Insufficient privileges to complete the operation. Please remove this code and use the code block in my code instead:

await graphClient.Me.SendMail(message, saveToSentItems)
                    .Request().WithUsernamePassword("your email", securePassword)
                    .PostAsync();

==============================Update2====================================

enter image description here

enter image description here